Calling C function from x64 assembly with registers instead of stack

筅森魡賤 提交于 2019-12-07 22:12:25

问题


This answer puzzled me.

According to the standard C calling conventions, the standard way to call C functions is to push arguments to the stack and to call the subroutine. That is clearly different from syscalls, where you set different registers with appropriate arguments and then syscall.

However, the answer mentioned above gives this GAS code:

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

which works with gcc hello.s -o hello. The part that calls printf is:

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

It is using the rdi register, not the stack, to pass the argument to printf. Changing the above to

        push $hello
        call printf

causes segmentation fault.

Since printf is a C function, unlike sys_write, I think the arguments should be passed to the stack, not the registers. What am I misunderstanding here? What about other standard C functions, such as malloc?

(Any reference would be truly appreciated.)


回答1:


Passing arguments to variadic functions is more complicated. See x86-64 ELF ABI, section 3.5.7. Otherwise, x86-64 passes its first 6 arguments using registers: %rdi, %rsi, %rdx, %rcx, %r8, %r9 (excluding float / vector arguments).

From the specification, %rax = 0 means that the variable argument list has no (0) floating-point arguments passed in vector registers. Your approach is wrong, as the first argument (e.g., the nul-terminated string: "Hello\n") must be passed in %rdi, and %rax must be zero when the function is called.



来源:https://stackoverflow.com/questions/28601414/calling-c-function-from-x64-assembly-with-registers-instead-of-stack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!