栈帧,反汇编解析

来源:互联网 发布:编程语言 知乎 编辑:程序博客网 时间:2024/06/13 10:16

示例:

int main()

{

int a = 10;

int b = 20;

int ret = 0;

ret = Add(a, b);

printf("ret=%d\n", ret);

system("pause");

return 0;

}

int Add(int x,int y)

{

int ret = 0;

ret = x + y;

return ret;

}

图片:


解析:

首先分配一块栈空间,用寄存器ebp,esp来保护,上面叫栈顶,下面叫栈底,esp(黑色)存放指向栈顶的指针,ebp(黑色)存放指向栈底的指针。

栈空间的使用是从高地址向低地址分配的,main函数结束来到--tmainCRTStartup(它调用main函数),而--tmainCRTStartup也被mainCRTStarup调用,也就是说main函数在调用前也被其他函数调用了,为每一次调用都开辟空间,如图给--tmainCRTStartupmainCRTStarup都开辟了空间,空间的增长之后,esp(红色),ebp(红色)也向上走,维护--tmainCRTStartup这个栈帧,从高地址向低地址走,图倒过来画也可行,但最底下的空间依旧存在,一会儿还要回来。

-----------------------------------------------------------------------------------------------

进入main函数的反汇编:

push ebp,在栈顶开辟一块空间,栈顶esp增长(变绿色),把ebp放入,此ebp--tmainCRTStartupebp,因为调用完main函数,要回到--tmainCRTStartup函数内部,找到自己的栈帧。

Mov ebp,espespebp,就是ebp(绿色)也指向esp(绿色)在当前最上面,

sub esp,0E4h,给esp减去4Ch,相当于申请了一个大空间4Chesp上移(变橙色),这块空间就是暂时给main函数开辟的空间。

Push ebx;push esi;push edi;往上分配三个空间,esp向上挪(变蓝色),

lea edi,[ebp-4Ch]lea是加载有效地址,把[ebp-4Ch]放到edi里面,刚才esp减去4Ch和这里是在同一个位置,这里把这个地址给edi存放,

mov ecx,13h13h1919乘以476,放到ecx里面,4Ch也是76

mov eax0CCCCCCCCh0CCCCCCCCh是随机值,把随机值放到eax里面,

rep stos dword ptr [edi],从edi每次存储双字,四个字节,从edi开始向下重复赋值,重复赋值ecx次,赋的值是eax,栈顶esp就下降到(橙色),打开“内存” 输入栈顶esp就会出现其内存地址,往下四个就是edi,运行一下就会初始化19CC CC CC CC19乘以4就是76,初始化了76个字节,刚才三次push之后,栈底就跳到esi那里(有问题)

------------------------------------------------------------------------------------------------

开始执行代码,上面都是系统调用开销。

Mov dword ptr [ebp-4],0Ah向上挪四个字节,放入a=10

Mov dword ptr [ebp-8],14h向上挪八个字节,放入b=20

Mov dword ptr [ebp-0Ch],0向上挪十二个字节,放入ret=0。下来是函数调用,

mov eax,dword ptr [ebp-8]push eax;把实参拿出放过去,然后在栈顶放进去b的值,栈顶esp上移(变绿色)。

mov ecx,dword ptr [ebp-4]push ecx;在栈顶放入a的值栈顶esp上移(变暗红)。

call @ILT+30(_average) (00401023);记住call指令下一条指令的地址(00401023),记录其,当调用完回到Add函数。add esp,8;在“内存”中按F11,栈顶地址就变为(00401023),在栈顶悄悄地压入该地址,esp上移(变紫色)。

mov dword ptr [ebp-0Ch],eax;。

-----------------------------------------------------------------------------------------------

再走程序,进入Add函数,和刚才main函数前面一样。push ebp

在栈顶压入main函数的ebp,栈顶上移(变青蓝色)内存里的ebp也会随着改变(变红色),mov ebp,esp...esp上移(变红色),为Add函数开辟空间,push三次ebx,esi,ediesp上移(变黑色),内存又变,像上面所说一样也是初始化,17行。

-----------------------------------------------------------------------------------------------

Int ret=0;

Mov dword ptr [ebp-4],0ebp减去4申请一个空间,四个字节存放ret=0,局部变量的创建。

-----------------------------------------------------------------------------------------------

ret=x+y;

mov eax,dword ptr [ebp+8]ebp+8向回指向到“把aecx,10”,把它再给eaxadd eax,dword ptr [ebp+0Ch]ebp+0Ch]指向“把beax,20”,把它再给eax(此时是10)加,就相当于a+b,变成30mov dword ptr [ebp-4],eax;加出来的结果放到ebp-4就是ret

------------------------------------------------------------------------------------------------

return ret;

Mov eax,dword ptr [ebp-4];将ret的值给寄存器eax,是30

pop edi; pop esi; pop ebx; 三次出栈,刚才放的都弹出,esp下移(变红色)

mov esp,ebp;esp再下移(变青蓝色),Add空间释放,ret局部变量也丢失,

pop ebp;把“ebp-main”弹出放到ebp中,这就是main函数的ebp回到main函数,

ret直接跳到刚才call指令记录的地方,call指令下是add esp,8,给esp8,释放两个形参,到edi处(变蓝色),

mov dword otr [ebp-0Ch],eax eax30)放到ebp-0Ch也就是ret

-----------------------------------------------------------------------------------------------

printf(“ret=%d\n”,ret);

    mov  edx,dword ptr [ebp-0Ch]  通过寄存器带回参数

  push  edx  

  push  offset string “...............

  call   printf (00401060)

  add   esp,8