Call 指令的实现
Near Call. When executing a near call, the processor pushes the value of the EIP register (which contains the offsetof the instruction following the CALL instruction) on the stack (for use later as a return-instruction pointer). The
processor then branches to the address in the current code segment specified by the target operand. The target
operand specifies either an absolute offset in the code segment (an offset from the base of the code segment) or a
relative offset (a signed displacement relative to the current value of the instruction pointer in the EIP register; this
value points to the instruction following the CALL instruction). The CS register is not changed on near calls.
call func_b;
next_instruction;
when executing the instrution of "call func_b"
EIP = address of next_instruction;
let tempEIP = EIP;
let tempEIP = EIP + offset to func_b = address of func_b;
call func_b = two instructions
1: push current EIP (= next_instruction)
2: EIP = tempEIP (= address of func_b)
函数调用示例
stack of calling function
func_a()
{
func_b(x,y,z)
next_instruction;
}
func_a 完成
push z
push y
push x
call func_b == push %EIP (= next_instruction)
mov %EIP func_b
func_b 完成
push %ebp
mov %ebp, %esp
对栈操作的语句 影响到的寄存器
func_a:
pushl z
pushl y
pushl x
pushl %EIP
movl %EIP next_instruction (following the call func_b);
funb_b:
pushl %EBP
movl %EBP %ESP
示意图1
示意图2
x86-64
- %rax 作为函数返回值使用。
- %rsp 栈指针寄存器,指向栈顶
- %rdi,%rsi,%rdx,%rcx,%r8,%r9 用作函数参数,依次对应第1参数,第2参数。。。
- %rbx,%rbp,%r12,%r13,%14,%15 用作数据存储,遵循被调用者使用规则,简单说就是随便用,调用子函数之前要备份它,以防他被修改
- %r10,%r11 用作数据存储,遵循调用者使用规则,简单说就是使用之前要先保存原值