X86-64下有16个64位寄存器,其中%rdi、%rsi、%rdx,%rcx、%r8、%r9用作传递函数参数,分别对应第1个参数、第2个参数直到第6个参数,如下图所示(图片来自网络):
如果函数的参数个数超过6个,则超过的参数直接使用栈来传递。在被调用函数执行前,会先将寄存器中的参数压入堆栈,之后的访问会通过栈寄存器加上偏移位置来访问。下面我们结合程序及其反汇编的结果来看一看。C语言程序如下所示:
#
include
<stdio.h
>
# include <stdlib.h >
static int func2( int i, int j)
{
int k;
k = i + j;
return k;
}
static int func( int fd, const char *ptr, int arg3, int arg4, int arg5,
int arg6, int arg7, int arg8)
{
int ret;
ret = arg7 + arg8;
func2(fd, arg3);
return ret;
}
int main( void)
{
func( 12, "Hello,World!", 3, 4, 5, 6, 7, 8);
return 0;
}
# include <stdlib.h >
static int func2( int i, int j)
{
int k;
k = i + j;
return k;
}
static int func( int fd, const char *ptr, int arg3, int arg4, int arg5,
int arg6, int arg7, int arg8)
{
int ret;
ret = arg7 + arg8;
func2(fd, arg3);
return ret;
}
int main( void)
{
func( 12, "Hello,World!", 3, 4, 5, 6, 7, 8);
return 0;
}
将上述程序保存为m.c,使用gcc加上-g选项编译,然后使用gdb来进行调试,我们在main调用func的位置及func()和func2()函数三处加上断点,如下所示:
(gdb) b m.c
:
26
Breakpoint 1 at 0x4004d4 : file m.c, line 26.
(gdb) b func
Breakpoint 2 at 0x4004ac : file m.c, line 17.
(gdb) b func2
Breakpoint 3 at 0x40047e : file m.c, line 8.
(gdb)
Breakpoint 1 at 0x4004d4 : file m.c, line 26.
(gdb) b func
Breakpoint 2 at 0x4004ac : file m.c, line 17.
(gdb) b func2
Breakpoint 3 at 0x40047e : file m.c, line 8.
(gdb)
然后我们在第一个断点处停下,反汇编当前的main函数,查看参数传递方式,如下所示:
(gdb) disassemble
/m main
Dump of assembler code for function main :
25 {
0x00000000004004cc < + 0 > : push %rbp
0x00000000004004cd < + 1 > : mov %rsp, %rbp
0x00000000004004d0 < + 4 > : sub $0x10, %rsp
26 func( 12, "Hello,World!", 3, 4, 5, 6, 7, 8);
= > 0x00000000004004d4 < + 8 > : movl $0x8,0x8( %rsp)
0x00000000004004dc
Dump of assembler code for function main :
25 {
0x00000000004004cc < + 0 > : push %rbp
0x00000000004004cd < + 1 > : mov %rsp, %rbp
0x00000000004004d0 < + 4 > : sub $0x10, %rsp
26 func( 12, "Hello,World!", 3, 4, 5, 6, 7, 8);
= > 0x00000000004004d4 < + 8 > : movl $0x8,0x8( %rsp)
0x00000000004004dc