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
?
(任何参考都会非常感激。)
答案 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>