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.)