Suppose we are given a simple program
#include <cstdio>
int main(int argc, char* argv[]) {
int n = argc;
if (n > 1) {
n = 1;
}else {
n = -1;
}
printf("%d\n", n);
return 0;
}
and assembly code snippet generated using g++ main.cpp -S -O1
under ubuntu x64(Windows subsystem)
subq $8, %rsp
cmpl $1, %edi
setg %dl
movzbl %dl, %edx
leal -1(%rdx,%rdx), %edx
movl $.LC0, %esi
movl $1, %edi
movl $0, %eax
call __printf_chk
movl $0, %eax
addq $8, %rsp
ret
There is neither a push
nor any instruction that accesses and writes memory. So the argument n
must be passed through %edx
. Now I wonder how the c library function __printf_chk
knows that %edx
contains the expected argument? More generally, how does it know which register(s) has(have) used?
This is specified by the platform's ABI (application binary interface). The compiler has compiled __printf_chk
to follow your platforms ABI (in this case, the amd64 SysV ABI), causing it to expect arguments to be in certain locations. For further reading, have a look at this ABI document.