gpt4 book ai didi

c - 选择外部调用的特定寄存器

转载 作者:行者123 更新时间:2023-11-30 15:11:37 26 4
gpt4 key购买 nike

我对汇编非常陌生,正在努力自学。

到目前为止,我了解到,根据从调用者传递到被调用者的参数数量,如果只有少数几个参数要传递,则只使用一些特定的寄存器,而不是进行推送/弹出操作.

  • 例如,将参数传递给交换函数 void asm_swap(int *x, int *y) 时,C 编译器使用寄存器 rcx 和 < rdx 寄存器传递变量的地址(在这种情况下不需要返回值)。从 _cdecl 切换到 _fastcall 没有任何区别。

  • 对于另一个函数int asm_fact(int x),即计算x的阶乘,C编译器使用rcx来传递x的值,和rax返回计算的阶乘。同样,从 _cdecl 切换到 _fastcall 没有任何区别。

关于这个问题,我有两个问题:

  1. 我可以推断出这样一个断言:每当我编译相同的代码时,调用者肯定会使用相同的寄存器来发送和接收数据吗?
  2. 有没有办法选择特定寄存器作为传递变量的工具(例如,对于函数asm_fact,我更喜欢使用rdx来保存x 的值,而不是 rcx

系统:Windows 10 (64)、VS-2013。

示例代码:文件“main.c”

#include <stdlib.h>
#include <stdio.h>

extern void asm_swap();
extern signed long long int asm_fact();

typedef signed long long int sint64;

sint64 fact_sint64(sint64 n) {
sint64 ret = (sint64)1;
if (n > (sint64)1) {
while (n > (sint64)1) {
ret *= n--;
}
}
return (ret);
}

void swap_sint64(sint64 *a, sint64 *b) {
sint64 t = *a;
*a = *b;
*b = t;
}

int main(void) {
sint64 x, y;
x = 8;
y = 3;
printf("(initial) -> x = %lli y = %lli\n\n", x, y);
swap_sint64(&x, &y);
printf("(swap in c) -> x = %lli y = %lli\n\n", x, y);
asm_swap(&x, &y);
printf("(swap in asm) -> x = %lli y = %lli\n\n", x, y);
y = fact_sint64(x);
printf("(fact in c) -> fact(%lli) = %lli\n\n", x, fact_sint64(x));
y = asm_fact(x);
printf("(fact in asm) -> fact(%lli) = %lli\n\n", x, y);
getchar();
return (0);
}

文件“Assembly.asm64”

.data

.code
asm_swap proc
mov r8, [rcx]
mov r9, [rdx]
mov [rcx], r9
mov [rdx], r8
ret
asm_swap endp

asm_fact proc
mov rax, 1
cmp rcx, 1
jle $exit@fact
$loop@fact:
imul rax, rcx
dec rcx
cmp rcx, 1
jg $loop@fact
$exit@fact:
ret
asm_fact endp
end

最佳答案

对于 Windows,有一个 ABI 指定

  1. 参数如何传递
  2. 调用中需要保留哪些寄存器

Msdn:microsoft calling conventions

为了作为 C 函数进行调用,您应该遵守这些规则。

您必须保留非 volatile 寄存器(保存和恢复它们)

关于c - 选择外部调用的特定寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35565995/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com