函数调用的步骤:
-
参数准备:
- 在x86-64架构中,前六个整数或指针参数通常通过寄存器传递,分别是:
RDI
,RSI
,RDX
,RCX
,R8
,R9
。 - 浮点参数通常通过
XMM0
至XMM7
寄存器传递。 - 如果有更多参数,或者参数是复杂的数据结构,它们通常会被放在调用者堆栈上。
- 在x86-64架构中,前六个整数或指针参数通常通过寄存器传递,分别是:
-
调用指令:
call
指令用于实际调用函数。这条指令会将下一条指令的地址(返回地址)推入堆栈,然后跳转到函数的起始地址执行。 -
进入被调用函数(被调用者):
- 被调用的函数首先需要保存调用者寄存器的状态,这通常通过将这些寄存器的值推入堆栈来完成。
- 接着,它会为局部变量分配空间,这是通过调整栈指针
RSP
来实现的。 - 在这个阶段,被调用函数也可能会创建一个新的栈帧,通过更新基指针
RBP
,使其指向当前的栈顶。
-
函数执行:
函数执行它的操作,可能会进一步调用其他函数,或者访问/修改它的参数和局部变量。 -
设置返回值:
函数执行完成后,任何返回值通常会放在RAX
(对于整数和指针)或XMM0
(对于浮点数)寄存器中。 -
恢复调用者环境:
函数在返回之前需要恢复调用者的栈帧,这通常包括释放局部变量占用的栈空间和恢复任何保存的寄存器。 -
返回指令:
ret
指令用于从函数返回。这条指令从堆栈中弹出返回地址并跳转到那里,这样控制权就回到了调用者。