百科问答小站 logo
百科问答小站 font logo



汇编过程调用是怎样操作栈的? 第1页

  

user avatar   bei-ji-85 网友的相关建议: 
      

书里应该要表达的是stack frame的意思吧?

x86/x64里面,stack frame就是根据当前的ebp能反推出整个调用栈。

ebp esp eip的几个特性:

1. 主流编译器在函数调用的caller里,执行call指令会让eip入栈;

2. 被调函数(callee)里头两句一定是

push ebp

mov ebp, esp

最后一句一定是

mov esp, ebp

pop ebp

3. ebp在函数内部是不会改变的,入栈出栈动作只改变esp,于是通过ebp就能反推出整个调用栈了。

反推栈帧的方法

当前的ebp就是当前函数入口时的esp;

入口时的[esp-4]就是前一个函数的ebp;

入口时的[esp-8]就是前一个函数的eip值;

拿到前一个函数的ebp值继续反推就能获得整个调用栈的ebp esp eip,这就是stack frame。

如果是64位:

寄存器换成rip rbp rsp,栈指针一次减8;

其它方面:

1. 基本没有far call(系统调用、中断除外),所以,栈上一般只有IP,没有CS;

2. 32位多数情况下参数用栈传输,64位下是用寄存器的更多,具体要看编译器;

3. enter和leave指令等效于push ebp; mov ebp, esp和mov esp, ebp; pop ebp;

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

实例:

函数调用up_align_to -> align_to,汇编为VS2008

       size_t up_align_to(size_t val, size_t align)     { 011914B0 55               push        ebp   011914B1 8B EC            mov         ebp,esp  011914B3 81 EC C0 00 00 00 sub         esp,0C0h  011914B9 53               push        ebx   011914BA 56               push        esi   011914BB 57               push        edi   011914BC 8D BD 40 FF FF FF lea         edi,[ebp-0C0h]  011914C2 B9 30 00 00 00   mov         ecx,30h  011914C7 B8 CC CC CC CC   mov         eax,0CCCCCCCCh  011914CC F3 AB            rep stos    dword ptr es:[edi]      return align_to(val, align, 1); 011914CE 6A 01            push        1                   //参数3 011914D0 8B 45 0C         mov         eax,dword ptr [align]  011914D3 50               push        eax                 //参数2 011914D4 8B 4D 08         mov         ecx,dword ptr [val]  011914D7 51               push        ecx                 //参数1 011914D8 E8 08 FD FF FF   call        align_to (11911E5h) //函数调用 011914DD 83 C4 0C         add         esp,0Ch      } 011914E0 5F               pop         edi   011914E1 5E               pop         esi   011914E2 5B               pop         ebx   011914E3 81 C4 C0 00 00 00 add         esp,0C0h  011914E9 3B EC            cmp         ebp,esp  011914EB E8 73 FC FF FF   call        @ILT+350(__RTC_CheckEsp) (1191163h)  011914F0 8B E5            mov         esp,ebp  011914F2 5D               pop         ebp   011914F3 C3               ret        size_t align_to(size_t val, size_t align, int is_up)     { 01191420 55               push        ebp                //保存ebp 01191421 8B EC            mov         ebp,esp            //保存esp 01191423 81 EC C0 00 00 00 sub         esp,0C0h  01191429 53               push        ebx   0119142A 56               push        esi   0119142B 57               push        edi   0119142C 8D BD 40 FF FF FF lea         edi,[ebp-0C0h]  01191432 B9 30 00 00 00   mov         ecx,30h  01191437 B8 CC CC CC CC   mov         eax,0CCCCCCCCh  0119143C F3 AB            rep stos    dword ptr es:[edi]      if (val % align == 0)     

执行到参数3以后

       [栈上其它数据] [参数3] []  <-esp,ebp为up_align_to入口时的esp值     

执行到参数2以后

       [栈上其它数据] [参数3] [参数2] []  <-esp,ebp为up_align_to入口时的esp值     

执行到参数1以后

       [栈上其它数据] [参数3] [参数2] [参数1] []  <-esp,ebp为up_align_to入口时的esp值     

执行CALL以后

       [栈上其它数据] [参数3] [参数2] [参数1] [eip] []  <-esp,ebp为up_align_to入口时的esp值     

执行到保存ebp以后

       [栈上其它数据] [参数3] [参数2] [参数1] [eip] [ebp] []  <-esp,ebp为up_align_to入口时的esp值     

执行到保存esp以后

       [栈上其它数据] [参数3] [参数2] [参数1] [eip] [ebp] []  <-esp,ebp为align_to入口时的esp值     

[ebp-4]就是up_align_to入口时的esp值

[ebp-8]就是call指令后面的地址(011914DD)

[[ebp-4]-4]是上上个调用函数入口时的esp值

[[ebp-4]-8]是上上个调用函数call后边的地址

所以,求stack frame只要递归求[ebp-4]就行了,每个ebp-4挨着的就是eip




  

相关话题

  有了 IP 地址,为什么还要用 MAC 地址? 
  MATLAB在逐渐被Python淘汰吗? 
  为什么不能有把中文想法直接转换成电脑程序的编程呢? 
  为什么总感觉DNA有种智慧设计的味道,更象一种编程语言,一定有人说是演化的结果,但是做个假设,如果? 
  如果华为自己做手机操作系统,你对这个操作系统有什么建议? 
  作为一名程序员,最大的成就感来自哪里? 
  有没有三维的数据结构? 
  学习python与c语言哪个好? 
  计算机专业大学生想要在以后有一份好工作,在大学期间应该及时考哪些证书? 
  华为自研的「仓颉」编程语言,未来能取代java的地位吗? 

前一个讨论
自己开发的Windows7 64位驱动程序需要签名,怎么解决?
下一个讨论
为什么广州和福州之间没有任何直达火车?





© 2024-05-17 - tinynew.org. All Rights Reserved.
© 2024-05-17 - tinynew.org. 保留所有权利