- 前6个参数使用寄存器传递 (%rdi, %rsi, %rdx, %rcx, %r8, %r9)
- 第7个开始往后用栈传递,后面的参数先压栈(高地址),左边的参数后压栈(低地址)
- %rax作为返回值使用
举例来说:
$ cat test.c
void foo(long p1, long p2, long p3, long p4, long p5, long p6, long p7, long p8, long p9) {
}
void callee(long p1, long p2, long p3, long p4, long p5, long p6, long p7, long p8, long p9) {
foo(p1, p2, p3, p4, p5, p6, p7, p8, p9);
}
void caller() {
callee(1L,2L,3L,4L,5L,6L,7L,8L,9L);
}
image.png
$ gcc -S -O0 test.c
看汇编码:
1 caller:
2 pushq %rbp
3 movq %rsp, %rbp
4 subq $24, %rsp // 为第7,8,9这三个参数分配栈空间
5 movq $9, 16(%rsp) // 压入第9个参数,后面的参数在高地址
6 movq $8, 8(%rsp) // 压入第8个参数
7 movq $7, (%rsp) // 压入第7个参数
8 movl $6, %r9d // 第6个参数,寄存器%r9
9 movl $5, %r8d // 第5个参数,寄存器%r8d
10 movl $4, %ecx // 第4个参数,寄存器%rcx
11 movl $3, %edx // 第3个参数,寄存器%rdx
12 movl $2, %esi // 第2个参数,寄存器%rsi
13 movl $1, %edi // 第1个参数,寄存器%rdi
14 call callee
15 leave
16 ret
看callee:
1 callee:
2 pushq %rbp
3 movq %rsp, %rbp
4 subq $72, %rsp -- 为所有参数准备本地空间 9 * 8 = 72
5 movq %rdi, -8(%rbp) -- 第1个参数,存入高地址
6 movq %rsi, -16(%rbp) -- 第2个参数,存入
7 movq %rdx, -24(%rbp) -- 第3个参数,存入
8 movq %rcx, -32(%rbp) -- 第4个参数,存入
9 movq %r8, -40(%rbp) -- 第5个参数,存入
10 movq %r9, -48(%rbp) -- 第6个参数,存入,前面6个参数都是通过寄存器传递的
-- 下面开始为调用foo准备参数
11 movq -48(%rbp), %r9 -- 准备第6个参数,入%r9
12 movq -40(%rbp), %r8 -- 准备第5个参数,入%r8
13 movq -32(%rbp), %rcx -- 准备第4个参数,入%rcx
14 movq -24(%rbp), %rdx -- 准备第3个参数,入%rdx
15 movq -16(%rbp), %rsi -- 准备第2个参数,入%rsi
16 movq -8(%rbp), %rax -- 准备第1个参数,入%rax,注意这里是%rax是临时寄存器,最后会存入%rdi
17 movq 32(%rbp), %rdi -- 下面两行,准备第9个参数,存入栈16(%rsp)
18 movq %rdi, 16(%rsp)
19 movq 24(%rbp), %rdi -- 下面两行,准备第8个参数,存入栈8(%rsp)
20 movq %rdi, 8(%rsp)
21 movq 16(%rbp), %rdi -- 下面两行,准备第7个参数,存入栈0(%rsp)
22 movq %rdi, (%rsp)
23 movq %rax, %rdi -- 把16行准备好的第一个参数,存入最终寄存器%rdi
24 call foo
25 leave
26 ret
网友评论