使用寄存器而不是堆栈从x64程序集调用C函数

时间:2015-02-19 08:16:13

标签: assembly x86-64 calling-convention gas

This answer困惑了我。

根据standard C calling conventions,调用C函数的标准方法是向堆栈push个参数和call子例程。这明显不同于syscalls,您可以使用适当的参数设置不同的寄存器,然后syscall

但是,上面提到的答案给出了这个GAS代码:

        .global main
        .section .data
hello:  .asciz "Hello\n"
        .section .text
main:
        movq $hello, %rdi
        movq $0, %rax
        call printf
        movq $0, %rax
        ret

适用于gcc hello.s -o hello。调用printf的部分是:

        movq $hello, %rdi
        movq $0, %rax
        call printf

使用rdi寄存器而不是堆栈将参数传递给printf。将上述内容更改为

        push $hello
        call printf

导致分段错误。

由于printf是一个C函数,与sys_write不同,我认为参数应该传递给堆栈,而不是寄存器。我在这里误解了什么?那么其他标准C函数呢,比如malloc

(任何参考都会非常感激。)

1 个答案:

答案 0 :(得分:3)

将参数传递给可变参数函数更复杂。请参阅x86-64 ELF ABI,第3.5.7节。否则,x86-64使用寄存器传递其前6个参数:%rdi, %rsi, %rdx, %rcx, %r8, %r9(不包括float / vector参数)。

根据规范,%rax = 0表示变量参数列表在向量寄存器中没有传递(0)浮点参数。您的方法是错误的,因为第一个参数(例如,以空字符结尾的字符串:"Hello\n")必须在%rdi中传递,并且%rax在调用函数时必须为零。 / p>

相关问题