【问题标题】:Calling C function from x64 assembly with registers instead of stack使用寄存器而不是堆栈从 x64 程序集调用 C 函数
【发布时间】:2015-04-20 12:06:59
【问题描述】:

This answer 让我很困惑。

根据standard C calling conventions,调用C 函数的标准方法是将push 参数传递给堆栈和call 子例程。这与syscalls 明显不同,在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

(任何参考将不胜感激。)

【问题讨论】:

标签: assembly x86-64 calling-convention gnu-assembler


【解决方案1】:

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

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

【讨论】:

  • 这正是我一直在寻找的。非常感谢。
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 2015-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-28
  • 2016-06-26
相关资源
最近更新 更多