您的位置:首页 > 其它

x86 function call and return --- stack save the return address.

2015-12-09 15:02 330 查看
ARM has LR register to store the return address of the caller.

But X86 has no this kind register.

So how the function call return to the caller ?

The answer is the function call stack and the register EBP and ESP.

EBP stores caller's stack top address.

ESP stores function stack top address.

call instruction will push the return address( the address of next instruction of call) in to ESP stack, then jump to the function.

In the function: 0x80483e4 <func_a>: push %ebp
0x80483e5 <func_a+1>: mov %esp,%ebp
0x80483e7 <func_a+3>: push %ebx
0x80483e8 <func_a+4>: sub $0x24,%esp // new stack
0x80483eb <func_a+7>: mov 0xc(%ebp),%eax
0x80483ee <func_a+10>: mov 0x8(%ebp),%edx
0x80483f1 <func_a+13>: add %edx,%eax
0x80483f3 <func_a+15>: mov %eax,-0x10(%ebp)
0x80483f6 <func_a+18>: mov 0x4(%ebp),%ebx
0x80483f9 <func_a+21>: mov %ebx,-0xc(%ebp)
0x80483fc <func_a+24>: mov $0x8048540,%eax
0x8048401 <func_a+29>: mov -0xc(%ebp),%edx
0x8048404 <func_a+32>: mov %edx,0x4(%esp)
0x8048408 <func_a+36>: mov %eax,(%esp)
0x804840b <func_a+39>: call 0x8048300 <printf@plt>
0x8048410 <func_a+44>: mov -0x10(%ebp),%eax
0x8048413 <func_a+47>: add $0x24,%esp // return to call stack
0x8048416 <func_a+50>: pop %ebx
0x8048417 <func_a+51>: pop %ebp // pop EBP
0x8048418 <func_a+52>: ret
Attention: the stack is still caller's stack.

The first instruction of the function is push EBP to the ESP stack(save caller's caller stack address).

The second instruction is mov ESP to EBP (save caller's stack in EBP) .

The fourth instruction create the new stack for this function and set it in ESP. Here start to run with function's stack.

leave instruction will restore EBP to ESP, then pop the EBP from the ESP stack.

ret instruction will pop the return address to EIP.

So we could get the caller's return address by access EBP+4 memory. Following is the code.

#include <stdio.h>

static volatile int func_a(int a, int b)
{
int c=a+b;
unsigned int caller;
asm("mov 4(%%ebp),%0":"=r"(caller):);
printf("caller address is 0x%x\n",caller);
return c;
}

int main(int argc,char** argv)
{
int a = 5;
int b = 9;
int c = 0;
c=func_a(a,b);
printf("c is %d\n",c);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  x86 函数