函数反汇编以及栈结构分析.docx_第1页
函数反汇编以及栈结构分析.docx_第2页
函数反汇编以及栈结构分析.docx_第3页
函数反汇编以及栈结构分析.docx_第4页
函数反汇编以及栈结构分析.docx_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

#include using namespace std;int func(int a,int b);void main()int x = 1;int y = 2;int z = func(x,y);int func(int a,int b)return a + b;汇编解析:void main()/这个函数头产生的汇编代码是:main:013E13A0 push ebp 013E13A1 mov ebp,esp 013E13A3 sub esp,0E4h 013E13A9 push ebx 013E13AA push esi 013E13AB push edi 013E13AC lea edi,ebp-0E4h 013E13B2 mov ecx,39h 013E13B7 mov eax,0CCCCCCCCh 013E13BC rep stos dword ptr es:edi *int x = 1;int y = 2;/这个的汇编代码是:013E13BE mov dword ptr x,1 013E13C5 mov dword ptr y,2 */接下来就是函数的调用了,先是把参数压栈013E13CC mov eax,dword ptr y 013E13CF push eax 013E13D0 mov ecx,dword ptr x 013E13D3 push ecx /参数压栈后就是调用函数013E13D4 call func (13E11D1h) / 在这个地方用F11调试步进,可以进入子函数func的汇编代码,如下:013E11D1 jmp func (13E35B0h) func:013E35B0 push ebp 013E35B1 mov ebp,esp 013E35B3 sub esp,0C0h 013E35B9 push ebx 013E35BA push esi 013E35BB push edi 013E35BC lea edi,ebp-0C0h 013E35C2 mov ecx,30h 013E35C7 mov eax,0CCCCCCCCh 013E35CC rep stos dword ptr es:edi 013E35CE mov eax,dword ptr a 013E35D1 add eax,dword ptr b 013E35D4 pop edi 013E35D5 pop esi 013E35D6 pop ebx 013E35D7 mov esp,ebp 013E35D9 pop ebp 013E35DA ret /func函数执行完毕后返回主函数中013E13D9 add esp,8 013E13DC mov dword ptr z,eax 013E13DF xor eax,eax 013E13E1 pop edi 013E13E2 pop esi 013E13E3 pop ebx 013E13E4 add esp,0E4h 013E13EA cmp ebp,esp 013E13EC call ILT+315(_RTC_CheckEsp) (13E1140h) 013E13F1 mov esp,ebp 013E13F3 pop ebp 013E13F4 ret 接下来再看看各个寄存器都是怎么变的,里面存的什么东西1 首先进入main函数最开始:再看看此时的寄存器的内容:EAX=00851D88 EBX=7E0BC000 ECX=00854A30 EDX=00000001 ESI=00000000 EDI=00000000 EIP=013E13A0 ESP=009BF76C EBP=009BF7B8 EFL=00000202 2再进行单步调试:再观察一下寄存器的内容:EAX=00851D88 EBX=7E0BC000 ECX=00854A30 EDX=00000001 ESI=00000000 EDI=00000000 EIP=013E13A1 ESP=009BF768 EBP=009BF7B8 EFL=00000202 我们发现esp的值少了4,这就说明了函数压栈时是从高字节到低字节递减,越是后压进来的越是字节低。3 再把esp的值保存一下再看一下寄存器的内容:EAX=00851D88 EBX=7E0BC000 ECX=00854A30 EDX=00000001 ESI=00000000 EDI=00000000 EIP=013E13A3 ESP=009BF768 EBP=009BF768 EFL=00000202 Ebp就保存了esp的值4再步进到直到main函数调用func函数之前我们再观察内存的情况连续定义的变量,他们在内存中紧挨着,之间相差4个字节。其实在堆栈中每次内存偏移必须是4个字节的整数倍。这个在参数数目以及类型可变的函数中可以体会到字节对齐的这种思想。我们再观察下此时的寄存器的内容:EAX=00000002 EBX=7E0BC000 ECX=00000001 EDX=00000001 ESI=00000000 EDI=009BF768 EIP=013E13D3 ESP=009BF674 EBP=009BF768 EFL=00000206 我们可以发现实参x,y的值都是先传进寄存器,然后再压栈。当把参数全部压进去后才开始调用函数。同时我们也可以发现EIP寄存器它里面总是放着下一条要执行的指令。5再调试函数到子函数func里面观察此时对应的寄存器EAX=00000002 EBX=7E0BC000 ECX=00000001 EDX=00000001 ESI=00000000 EDI=009BF768 EIP=013E35B0 ESP=009BF66C EBP=009BF768 EFL=00000206 其中的EBP = 009BF768是之前进入main函数时堆栈的栈顶指针。现在我们要把它保存,所以要push以下,放到堆栈的内存中。然后呢,因为进入main函数之后,直到进入func子函数时,我们又要维护这个在main函数中产生的栈顶指针,所以要把栈顶指针的值保存以下,保存在ebp中,所以此时要move以下。通俗的说就是,你这个子函数要在人家main函数的地盘进行栈操作,你就得负责人家main函数之前的栈(栈顶指针),这样在子函数调用结束后,main函数可以直接接着原来的栈干事。同时子函数维护的还有ebx,esi,edi,凡是要在子函数中用到的寄存器,那么子函数就要保存调用它的函数中在这些寄存器中的值。6往后再看看函数的返回值,继续单步调试到:再看相关的寄存器EAX=00000003 EBX=7E0BC000 ECX=00000000 EDX=00000001 ESI=00000000 EDI=009BF668 EIP=013E35D4 ESP=009BF59C EBP=009BF668 EFL=00000206 可以看到两个数相加的结果保存在了寄存器EAX中。函数体中的代码执行完毕就要释放栈空间,接下来就是一系列的pop了。7我们再看看pop完后的寄存器:观察对应的寄存器:EAX=00000003 EBX=7E0BC000 ECX=00000000 EDX=00000001 ESI=00000000 EDI=009BF768 EIP=013E35DA ESP=009BF66C EBP=009BF768 EFL=00000206 我们可以看到EBP变回了之前的009BF66C(main函数中保存的先前函数的栈顶指针),ESP变回了之前的009BF66C(main函数进入func子函数栈顶指针)。这样就把之前保存在栈内存中的东西重新返回到寄存器中了。再研究下从子函数返回后main函数中的代码013E13D9 add esp,8 /func函数有两个int参数,所以释放8个字节013E13DC mov dword ptr z,eax /把函数的返回值赋给变量z013E13DF xor eax,eax /将eax清零,xor表示异或运算,自己跟自己异或肯定是0013E13E1 pop edi 013E13E2 pop esi 013E13E3 pop ebx 013E13E4 add esp,0E4h 013E13EA cmp ebp,esp 013E13EC call ILT+315(_RTC_CheckEsp) (13E1140h) 013E13F1 mov esp,ebp 013E13F3 pop ebp 013E13F4 ret 总结:1:函数的返回值通过这些例子我们也可以看出函数可以返回在函数中定义的局部变量的值,因为函数的返回值最后传递给了EAX 寄存器,所以即便函数调用结束后,栈中内存释放,但是寄存器却保存了返回值,但是如果返回一个指向栈内存的指针或者地址那就不行了,因为栈被释放了。2:参数的获取有些人或许要问,参数的值都是实参传递给形参的,这还需要什么获取,这话没有错误,但是如果函数时比较特殊的函数,例如:int func();int func(int,int);int func(int,);这种类型的呢,这些函数要么是可变参数,要么是参数名字没有给。在这种极端比较恶心的条件下,我们依然可以获取传递的实参的值。通过上面我们可以发现栈的结构是:参数n参数n-1参数1函数的返回地址(call 指令后面的那一句)EBP局部变量1局部变量2局部变量n-1局部变量nEBXESIEDI所以我们可以通过EBP寄存器通过偏移固定的位置就可以找到对应的参数,例如第一个参数只需要EBP的地址加上8得到。3 关于这里esp减值的问题通过控制函数的形参个数,以及函数内部定义的局部变量我们可以发现有这样一个规律。(1) 函数内部没有定义局部变量是,改变形参的个数不影响esp减去的值,此时esp减去的值都是0C0h。(2) 函数内部每多定义一个int类型的局部变量,减去的值就会增加12,就是说多开辟12个字节。(3) 函数内部每多定义一个double类型的局部变量,减去的值就会增加16,就是说多开辟16个字节(4) 函数内部每多定义一个char类型的局部变量,减去的值就会增加12,就是说多开辟12个字节。(5) 函数内部每多定义一个float类型的局部变量,减去的值就会增加12,就是说多开辟12个字节。4 寄存器4个数据寄存器(EAX、EBX、ECX和EDX)2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)6个段寄存器(ES、CS、SS、DS、FS和GS)1个指令指针寄存器(EIP) 1个标志寄存器(EFlags)EBP :(Extended Base Pointer)基址指针寄存器,存放栈底指针ESP :(Extended Stack Pointer)栈指针寄存器,存放栈顶指针EAX :(Extended Accumulate )累加寄存器,用做加减乘除运算EBX :(Extended Base)基址寄存器,可以用来存储指针ECX :(Extended Count)计数寄存器,用在循环中控制循环的次数EDX :(Extended Data)数据寄存器,在进行乘、除运算时,它可作为默认的操作数参与运算,通常用来保存余数。也可用于存放I/O的端口地址ESI:(Extended Source Index)源索引寄存器,可以存放任何数据,但是习惯把它存放指针。EDI:(Extended Destination Index)目的索引寄存器,但是ESI和EDI虽然他俩经常配合,但是之间的区别还是比较大的。在字符串处理指令中,ESI和DS结合,DS:ESI构成全指针,在穿处理指令方面,ESI负责只读,EDI负责只写。关于为啥只能ESI和DS结合形参全指针,这是硬件构造决定的,没有选择性。ES:EDI,同样构成全指针。EIP:(Extended Instruction Pointer)指令指针寄存器,要存放下一条执行指令的地址EFL:(Extended Flag)标志寄存器,用来运算结果标志(进位,溢出等),状态控制标志(跟踪,中断允许等)。CS代码段寄存器(Code Segment Register),其值为代码段的段值;DS数据段寄存器(Data Segment Register),其值为数据段的段值;ES附加段寄存器(Extra Segment Register),其值为附加数据段的段值;SS堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;FS附加段寄存器(Extra Segment Register),其值为附加数据段的段值;GS附加段寄存器(Extra Segment Register),其值为附加数据段的段值。5 个别语句解释002E13F3 sub esp,0CCh ;(1)002E13F9 push ebx :(2)002E13FA push esi ;(3)002E13FB push edi ;(4)002E13FC lea edi,ebp-0CCh ;(5)002E1402 mov ecx,33h ;(6)002E1407 mov eax,0CCCCCCCCh;(7) 002E140C rep stos dword ptr es:edi ;(8)(1) 表示栈指针减去occh,就是开辟0cch的栈内存空间来存放临时变量(2) 保存ebx到栈内存(3) 保存esi到栈内存(4) 保存edi到栈内存(5) 将临时变量的最低内存地址放到edi中(6) Ecx

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论