I have been following the excellent book Programming Ground Up, wanting to learn assembly. Although not in the book at this point, I wanted to call my assembly function from C. on a 32 bit machine, this works as is when working from the book.
What I do here is storing the first argument in %ebx
and the second in %ecx
.
.type power, @function
.globl power
power:
pushq %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
I compile this (and the rest of the function) into an object file, create a main.c, where I prototype the function and call it, something like this:
int power(int b, int x);
int a = power(2, 1);
However, when I compile this on a 64 bit machine, I get some very unexpected results. I modified the obvious, like the fact that %esp
and %epb
needs to be replaced with %rsp
and %rpb
, but digging with GDB reveals that the arguments are nowhere to be found on the stack!
Checking out what happens by using the -S
option to GCC I can see that instead of pushing the variables on the stack, GCC stores the arguments in registers.
movl $1, %esi
movl $2, %edi
call power
On the 32 bit machine, it does what I expect and push the arguments on the stack:
movl $1, 4(%esp)
movl $2, (%esp)
call power
Now what is going on here? Why does GCC pass the arguments in registers on 64 bit and on the stack on 32 bit? This is very confusing! And I can't find any mention on this anywhere. Is there anyone who can enlighten me on this situation?
64-bit C calling convention is: %rdi, %rsi, %rdx, %rcx, %r8 and %r9
See full description here: "System V Application Binary Interface: AMD64 Architecture Processor Supplement" http://www.x86-64.org/documentation/abi.pdf
3.2 Function Calling Sequence
When I learned the same topic, I made small C programs with required functions, compiled them in 64 bit compiler and read the Assembly code produced by C compiler. C/C++ compiler can be used like kind of Assembly reference.