C 是否确定存储了哪些寄存器参数和变量?
我仍然不确定汇编程序是如何使用寄存器的 假设我有一个程序:C 是否确定存储了哪些寄存器参数和变量?,c,assembly,x86-64,att,C,Assembly,X86 64,Att,我仍然不确定汇编程序是如何使用寄存器的 假设我有一个程序: int main(int rdi, int rsi, int rdx) { rdx = rdi; return 0; } 这在汇编中是否可以翻译为: movq %rdx, %rdi ret rax; mov %rdi, %rdx # move %rdi into %rdx xor %eax, %eax # zero return value ret # return 我是AT&T的新手,很难预测某个寄存器何
int main(int rdi, int rsi, int rdx) {
rdx = rdi;
return 0;
}
这在汇编中是否可以翻译为:
movq %rdx, %rdi
ret rax;
mov %rdi, %rdx # move %rdi into %rdx
xor %eax, %eax # zero return value
ret # return
我是AT&T的新手,很难预测某个寄存器何时会被使用。
从计算机系统看这张图表——程序员的视角,第三版,R.E.Bryant和D.R.O'Hallaron:
不,它将被翻译成:
movq %rdx, %rdi
ret rax;
mov %rdi, %rdx # move %rdi into %rdx
xor %eax, %eax # zero return value
ret # return
当然,编译器很可能会删除rdx=rdi
(因此mov%rdi,%rdx
),因为不再使用rdx
幸亏在我之前发现了这一点
是否确定存储了哪些寄存器参数和变量
仅在函数的入口和出口处
无法保证在函数中使用哪些寄存器,即使对于作为函数参数的变量也是如此。编译器可以(通常也会)在寄存器之间移动变量,以优化寄存器/堆栈的使用,特别是在x86等寄存器匮乏的体系结构上
在这种情况下,像
rdx=rdi
这样的简单赋值操作可能根本不会编译成任何汇编代码,因为编译器将简单地识别两个值现在都可以在寄存器%rdi
中找到。即使对于更复杂的操作,如rdx=rdi+1
,编译器也可以自由地将值存储在任何寄存器中,而不是专门存储在%rdx
中。(它甚至可能将值存储回%rdi
,例如inc%rdi
,如果它意识到原始值以后从未使用过。)您忘记了指令,at&t使用src、dst顺序,因此它是mov%rdi,%rdx
。当然,任何优化编译器都会删除它,因为没有使用rdx
。另外,ret-rax
也没有意义,尤其是因为您的代码有一个返回0
。例如,xor%eax,%eax;将
归零rax
并返回。在可以查看GCC、clang、ICC或MSVC asm输出的地方自己尝试一下。(也适用于一些非x86 ISA)使用带有三个整数参数的函数名main()
,这不是一个明显的名称选择-参数的含义是由实现定义的,很可能实际上是未定义的行为。GCC可能会抱怨main()
函数上的签名不正确。忽略函数名的问题,代码不会处理影响计算状态的参数,优化器很可能会删除赋值。也没有任何东西将名为rdi
、rsi
和rdx
的变量与任何具有类似名称的寄存器相关联。当然,除了sysv-abi调用约定之外,它为这些参数指定了这些寄存器。对于我来说,清除了很多,谢谢Jonathani如果你从中抄袭了这篇文章,那么给予他们信任是一种常见的礼貌。如果你把这篇文章做成一篇社区维基文章,也会有所帮助。@MartijnPieters不完全是这样,但我已经添加了一个链接。