C到汇编调用约定32位对64位

时间:2010-11-24 10:54:47

标签: c linux assembly x86 x86-64

我一直在关注优秀的编程基础,希望学习装配。虽然现在不在书中,但是我想在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位堆栈上传递参数?这非常令人困惑!在任何地方我都找不到任何提及。有没有人可以在这种情况下启发我?

1 个答案:

答案 0 :(得分:27)

64位C调用约定是:%rdi,%rsi,%rdx,%rcx,%r8和%r9

请在此处查看完整说明: "System V Application Binary Interface: AMD64 Architecture Processor Supplement" http://www.x86-64.org/documentation/abi.pdf

3.2函数调用序列

当我学到同样的主题时,我制作了具有所需功能的小型C程序,用64位编译器编译它们并读取C编译器生成的汇编代码。 C / C ++编译器可以像汇编参考一样使用。