公司英文网站建设,建立百度网站,淘宝网站制作多少钱,泉州专业网站营销前言 一、X32汇编函数无参无返回分析 二、X64汇编函数无参无返回分析 总结 前言
提示#xff1a;以下是个人学习总结#xff1a;如有错误请大神指出来#xff0c;只供学习参考#xff0c;本内容使用使用VS2017开发工具#xff1a;语言是C#xff0c;需要一些常见的汇编指…前言 一、X32汇编函数无参无返回分析 二、X64汇编函数无参无返回分析 总结 前言
提示以下是个人学习总结如有错误请大神指出来只供学习参考本内容使用使用VS2017开发工具语言是C需要一些常见的汇编指令寄存器的概念不会的可以看下其他的博主的我用的这里方便学习全程debug函数用的默认Ccdecl调用约定模式可以网上查下调用约定右边入参到左边称为外平栈。 好久没更新博客了准备把汇编自我总结复习的顺带把过程记录下来接下来开始吧准备简单的无参函数。
一、X32汇编函数无参无返回分析 1.代码图片示例 不知道为什么不能赋值图这里直接赋值代码了。
#include iostreamvoid shenjianxz() {int a;int c;int d 3;int d2 4;a d - d2;
}int main()
{shenjianxz();} 0099179E call 00991131 这个就是上面那个简单shenjianxz函数调用 CPU主要执行的是根据EIP执行跳转的 call指令会 push 009917A3 压栈 因为我们调用完函数返回的时候会取这个地址跳转到下一行执行的代码 EIP寄存器00991131 现在我们跳去看看按F11 这里 jmp 中间跳转程序空间保存的函数地址 00EA1750,咱们先不管这不是重点 简单解下jmp 只改变eip地址cpu会自动运行到执行的地址去在点下F11进入 调用函数代码区了。 重点关注下ESP寄存器到哪了EBP寄存器值等于多少。 我讲解下上面代码含义 shenjianxz 009918F0 push ebp 保留ebp 寄存器009918F1 mov ebp,esp 为了后面恢复esp栈顶位置把他赋值给ebp进行操作009918F3 sub esp,0F0h 因为前面已经保存了esp的赋值就不担心这里esp就开始扩展0F0h 位置esp位置肯定就变了009918F9 push ebx 009918FA push esi 009918FB push edi 保留 ebxesiedi 寄存器位置 009918FC lea edi,[ebp-0F0h] 这里ebp的作用就体现了最前面我们不是把esp赋值给了ebp吗 这里就代表把sub esp,0F0h 地址赋值给edl00991902 mov ecx,3Ch 3c次数 00991907 mov eax,0CCCCCCCCh 0099190C rep stos dword ptr es:[edi] 重复3c次把occccccchint 3先不用管就理解是ccccccc赋值给edi 每次成功赋值就 edi4 0099190E mov dword ptr [ebp-20h],3 00991915 mov dword ptr [ebp-2Ch],4 0099191C mov eax,dword ptr [ebp-20h] 0099191F sub eax,dword ptr [ebp-2Ch] ebp的位置是push ebp的位置之后不是 ebpesb 下一句不是 sub esp,0F0h 扩展了0f0的大小空间么 那么ebp-20-2c都是在扩展的位置区间可见X32是ebp-N代表取局部变量00991922 mov dword ptr [ebp-8],eax 最终把结果放到ebp-8内存中 00991925 pop edi 00991926 pop esi 00991927 pop ebx 因为esp一直在栈顶所以还原3个寄存器 esp-Ch位置 00991928 mov esp,ebp esp已经距离很远了因为扩展了0F0h大小字节所以用ebp恢复esp位置esp在 push ebp位置了 0099192A pop ebp 恢复ebp栈底 0099192B ret 之前我们用call 调用的函数这里面push的是 call的下一条代码地址pop eip 让cpu跳转到eip位置下面是对应的自己画的图 2.小结 1X32是先保留push ebp寄存器在扩展堆栈大小 2mov ebp,esp 保留栈顶位置方便后面恢复 3[ebp-20][ebp-2c]都是在扩展的位置区间可见X32是ebp-N代表取局部变量参数获取这里演示无参数 二、X64汇编函数无参无返回分析
1.代码图片示例 同样的代码看不同 前面讲过这里也是jmp方式跳转到函数代码快继续F11跟进去因为中间重启过地址发生变化直接看下面的函数内容就行 00007FF7CA1717C0 push rbp 00007FF7CA1717C2 push rdi 00007FF7CA1717C3 sub rsp,168h 00007FF7CA1717CA lea rbp,[rsp20h] 00007FF7CA1717CF mov rdi,rsp 00007FF7CA1717D2 mov ecx,5Ah 00007FF7CA1717D7 mov eax,0CCCCCCCCh 00007FF7CA1717DC rep stos dword ptr [rdi] 这里是重复ecx的次数填充栈顶开始往回每次 rdi4 00007FF7CA1717DE lea rcx,[__D730393F_ccpp (07FF7CA181027h)] 00007FF7CA1717E5 call __CheckForDebuggerJustMyCode (07FF7CA171087h)这2行 因为是debug模式是检测堆栈的直接跳过看下面的 00007FF7CA1717EA mov dword ptr [rbp44h],3 00007FF7CA1717F1 mov dword ptr [rbp64h],4 RBPN 代表局部变量在X32中是EBP-N代表局部变量那么这里就是把立即数赋值给局部变量 我的理解因为之前 扩展168hrsp,168h 这里局部变量不能rbp148h大小范围,因为rsp20了之前大于了下一条就到了push rdi的位置了 00007FF7CA1717F8 mov eax,dword ptr [rbp64h] 00007FF7CA1717FB mov ecx,dword ptr [rbp44h] 看这里rbp64 44都是在扩展的局部变量赋值在范围内 00007FF7CA1717FE sub ecx,eax 00007FF7CA171800 mov eax,ecx 00007FF7CA171802 mov dword ptr [rbp4],eax 最后把值赋值给局部变量rbp4 00007FF7CA171805 lea rsp,[rbp0000000000000148h] 之前rsp-168h然后rbp20 这里在加个148h 不就回去了最早的push RDI位置 00007FF7CA17180C pop rdi 00007FF7CA17180D pop rbp 这里就是恢复 RDI RBP里的值 00007FF7CA17180E ret 这里pop eip 让cpu跳转到调用程序下一条指令执行 三、X32位汇编和X64位区别无参函数调用
总结
提示可以看下对比堆栈图变化和我说的文字区别
X32 1X32是先保留push ebp寄存器在扩展堆栈大小 2mov ebp,esp 保留栈顶位置方便后面恢复 3[ebp-20][ebp-2c]都是在扩展的位置区间可见X32是ebp-N代表取局部变量参数获取这里演示无参数 X64 1X64是先扩展栈顶大小在进行保留寄存器 2EBPN是获取局部变量 3EBP20ESP20,后用EBP进行局部变量赋值参数获取这里演示无参数