1.假设有如下C语言文件 "test.c"
int sumNine(int one, int two, int three, int four, int five, int six, int seven, int eight, int nine) { int x; x = one + two + three + four + five + six + seven + eight + nine; return x; } int main(void) { int total; int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; int f = 6; int g = 7; int h = 8; int i = 9; total = sumNine(a, b, c, d, e, f, g, h, i); return 0; }
2.通过GCC 命令 "gcc -o test.s -fverbose-asm -S -O0 -g test.c" 查看生成的汇编语言
main: endbr64 pushq %rbp # movq %rsp, %rbp #, subq $48, %rsp #, # test.c:14: int a = 1; movl $1, -40(%rbp) #, a # test.c:15: int b = 2; movl $2, -36(%rbp) #, b # test.c:16: int c = 3; movl $3, -32(%rbp) #, c # test.c:17: int d = 4; movl $4, -28(%rbp) #, d # test.c:18: int e = 5; movl $5, -24(%rbp) #, e # test.c:19: int f = 6; movl $6, -20(%rbp) #, f # test.c:20: int g = 7; movl $7, -16(%rbp) #, g # test.c:21: int h = 8; movl $8, -12(%rbp) #, h # test.c:22: int i = 9; movl $9, -8(%rbp) #, i # test.c:23: total = sumNine(a, b, c, d, e, f, g, h, i); movl -20(%rbp), %r9d # f, tmp84 movl -24(%rbp), %r8d # e, tmp85 movl -28(%rbp), %ecx # d, tmp86 movl -32(%rbp), %edx # c, tmp87 movl -36(%rbp), %esi # b, tmp88 movl -40(%rbp), %eax # a, tmp89 pushq %rdi # tmp90 movl -12(%rbp), %edi # h, tmp91 pushq %rdi # tmp91 movl -16(%rbp), %edi # g, tmp92 pushq %rdi # tmp92 movl %eax, %edi # tmp89, call sumNine # addq $24, %rsp #, movl %eax, -4(%rbp) # tmp93, total # test.c:24: return 0; movl $0, %eax #, _13 # test.c:25: } leave ret sumNine: pushq %rbp movq %rsp, %rbp subq $48, %rsp movl %edi, -20(%rbp) # save one movl %esi, -24(%rbp) # save two movl %edx, -28(%rbp) # save three movl %ecx, -32(%rbp) # save four movl %r8d, -36(%rbp) # save five movl %r9d, -40(%rbp) # save six movl -24(%rbp), %eax # load two movl -20(%rbp), %edx # load one, subtotal addl %eax, %edx # add two to subtotal movl -28(%rbp), %eax # load three addl %eax, %edx # add to subtotal movl -32(%rbp), %eax # load four addl %eax, %edx # add to subtotal movl -36(%rbp), %eax # load five addl %eax, %edx # add to subtotal movl -40(%rbp), %eax # load six addl %eax, %edx # add to subtotal movl 16(%rbp), %eax # load seven addl %eax, %edx # add to subtotal movl 24(%rbp), %eax # load eight addl %eax, %edx # add to subtotal movl 32(%rbp), %eax # load nine addl %edx, %eax # add to subtotal movl %eax, -4(%rbp) # x <- total movl $.LC0, %edi call puts movl -4(%rbp), %eax leave ret
Main函数中allocate了48个字节作为local variable的空间。
在调用sumNine的时候,前面6个需要传输的参数通过设置指定的Register来传输数据[2],多余的3个参数通过插入当前stack的形式来传输数据。(但是这边很奇怪的是48 + 3 * 8 = 72字节,stack pointer (rsp) 并没有16字节对齐,有知道的小伙伴告诉我一下为啥没有16字节对齐也能work)。在被调用的函数中前面6个传输通过register中获取,后面3个参数通过stack来获取。在调用sumNine的时候的Stack如下图所示。所有的参数都是通过8字节传输,并且在最后在stack中插入返回地址。
当调用到sumNine里面的时候, stack的样子设置如下。可以通过(rbp+16)拿到传入到函数中的参数,注意stack中包含了Return Address 和 Caller's rbp,所以需要加16才能拿到数据。
方法间的调用的时候,是通过Register和Stack传输数据的。并且需要返回的地址也会在调用函数的时候被插入。在调用其他函数之前 rbp 和 rsp 之间的数据存放着local variable 和 需要调用其他函数的参数。
[1] https://bob.cs.sonoma.edu/IntroCompOrg-x64/bookch11.html#x31-13800011
[2]
[3]