我一直在关注优秀的编程基础,希望学习装配。虽然现在不在书中,但是我想在32位机器上调用我的汇编函数,这在本书的工作中是有效的。
我在这里做的是将第一个参数存储在%ebx
中,将第二个参数存储在%ecx
中。
.type power, @function
.globl power
power:
pushq %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
我将这个(以及函数的其余部分)编译成目标文件,创建一个main.c,在那里我对函数进行原型化并调用它,如下所示:
int power(int b, int x);
int a = power(2, 1);
然而,当我在64位机器上编译它时,我得到一些非常意外的结果。我修改了显而易见的事实,例如%esp
和%epb
需要替换为%rsp
和%rpb
这一事实,但是使用GDB进行挖掘后发现无法找到参数在堆栈上!
通过对GCC使用-S
选项查看发生了什么我可以看到,GCC不是在堆栈上推送变量,而是将参数存储在寄存器中。
movl $1, %esi
movl $2, %edi
call power
在32位机器上,它完成我的预期并推送堆栈中的参数:
movl $1, 4(%esp)
movl $2, (%esp)
call power
现在发生了什么?为什么GCC在64位寄存器和32位堆栈上传递参数?这非常令人困惑!在任何地方我都找不到任何提及。有没有人可以在这种情况下启发我?
答案 0 :(得分:27)
64位C调用约定是:%rdi,%rsi,%rdx,%rcx,%r8和%r9
3.2函数调用序列
当我学到同样的主题时,我制作了具有所需功能的小型C程序,用64位编译器编译它们并读取C编译器生成的汇编代码。 C / C ++编译器可以像汇编参考一样使用。