反汇编分析C++代码
2024-09-05 06:01:35
编译环境:Windows 10 + VS2015
1、问题引入
在Win32环境下,CPU小端模式,参数用栈来传递,写出输出结果。
代码如下:
int main()
{
long long a = 1;
long long b = 2;
long long c = 3;
printf("%d%d%d", a, b, c);//输出结果102
return 0;
}
反汇编代码如下:
int main()
{
010C2AB0 push ebp
010C2AB1 mov ebp,esp //ebp地址为0x00cffcd0
010C2AB3 sub esp,0F0h
010C2AB9 push ebx
010C2ABA push esi
010C2ABB push edi
/*
将ebp-0f0处地址(0x00cffbe0)赋给目标变址寄存器edi。
注意lea与mov指令的区别,如果为mov,则表示将0x00cffbe0处存放的数据赋给edi。
*/
010C2ABC lea edi,[ebp-0F0h] 010C2AC2 mov ecx,3Ch
010C2AC7 mov eax,0CCCCCCCCh
/*
rep 表示重复执行其后面指令stos,重复次数由计数器ecx决定,没执行一次,ecx自动减小,ecx为0时,停止执行其后的指令。
stos 表示将edi指向的内容写成eax中的值,rep过程中edi自动增加。由f0h除以3ch=04得知每次自动增加4个字节,刚好为win32环境下指针长度。
*/
010C2ACC rep stos dword ptr es:[edi]
long long a = 1;
/*
dword 双字节 即四个字节
prt pointer缩写,即针
[]里的数据是一个地址值,这个地址指向一个双字节类型数据
mov ptr [a],1,表示把1数据赋给变量a。
mov eax,dword ptr[00cffbe0] 表示把地址00cffbe0中的双字节型(32位)数据赋给eax累加器。
*/
010C2ACE mov dword ptr [a],1
010C2AD5 mov dword ptr [ebp-8],0
long long b = 2;
010C2ADC mov dword ptr [b],2
long long b = 2;
010C2AE3 mov dword ptr [ebp-18h],0
long long c = 3;
010C2AEA mov dword ptr [c],3
010C2AF1 mov dword ptr [ebp-28h],0
printf("%d%d%d", a, b, c);
010C2AF8 mov eax,dword ptr [ebp-28h]
010C2AFB push eax
010C2AFC mov ecx,dword ptr [c]
010C2AFF push ecx
010C2B00 mov edx,dword ptr [ebp-18h]
010C2B03 push edx
010C2B04 mov eax,dword ptr [b]
010C2B07 push eax
010C2B08 mov ecx,dword ptr [ebp-8]
010C2B0B push ecx
010C2B0C mov edx,dword ptr [a]
010C2B0F push edx
010C2B10 push offset string "%d%d%d" (010C9B30h)
010C2B15 call _printf (010C152Dh)
010C2B1A add esp,1Ch
return 0;
010C2B1D xor eax,eax
}
010C2B1F pop edi
010C2B20 pop esi
010C2B21 pop ebx
010C2B22 add esp,0F0h
010C2B28 cmp ebp,esp
010C2B2A call __RTC_CheckEsp (010C1181h)
010C2B2F mov esp,ebp
010C2B31 pop ebp
010C2B32 ret
参数压栈后栈中数据结构如下,所以按整型输出是,读取的是地址0x011df900~0x011df908内容。按小端模式取出的结果为102。
2、寄存器简介
1)数据寄存器:保存操作数和运算结果等信息。
- EAX:Accumulator。是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。也可用作函数返回值。取低16位为AX,分割为8位寄存器AH-AL。指令ret返回用到。
- EBX:Base Register。 是"基地址"(base)寄存器, 在内存寻址时存放基地址。
- ECX:Count Register。是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
- EDX:Data Register。则总是被用来放整数除法产生的余数。
2)指针寄存器:EBP,ESP可作为通用寄存器,即可存储算术逻辑运算的操作数和运算结果。
- EBP:Base Pointer,基指针寄存器,直接访问栈中的数据。
- ESP:Stack Pointer,栈指针寄存器,只可访问栈顶。指令pop/push时自动变。
- EIP:Instruction Pointer,指令指针寄存器,存放下次将要执行的指令在代码段中的偏移量。每走一条指令自动变一次,如果希望跳转后能返回继续就需要跳转前把它放入栈中,返回时出栈。
3)变址寄存器:主要用于存放存储单元在段内的偏移量。
- ESI: Source Index,源变址寄存器。EDS:ESI即源串段寄存器:源串变址,ESI在串操作中自动增减。
- EDI:Destination Index,目标变址寄存器。EES:EDI即目标串段寄存器:目标串变址,EDI在串操作中自动增减。
4)段寄存器:内存分段。这里最多为6个内存段,不同的内存段放入不同的东西。
- ECS:Code Segment Register,代码段寄存器。
- EDS:Data Segment Register,数据段寄存器。
- EES:Extra Segment Register,附加段寄存器。
- ESS:Stack Segment Register,栈段寄存器。
- EFS:Extra Segment Register,附加段寄存器。
- EGS:Extra Segment Register,附加段寄存器。
最新文章
- sql注入的基本防范手段
- web api :Routing in ASP.NET Web API
- 【extjs】 ext5 Ext.grid.Panel 分页,搜索
- unknown software exception
- JPA学习---第八节:使用JPQL语句进行查询
- Excel2010: Excel使用小技巧(不断更新)
- [LeetCode226]Invert Binary Tree
- Kinect的学习笔记发展一Kinect引进和应用
- twisted学习笔记 No.1
- ios开发之简单实现loading动画效果
- GO中的数组切片
- 老男孩最新Python全栈开发视频教程(92天全)重点内容梳理笔记 看完就是全栈开发工程师
- 用yii2给app写接口(下)
- [BZOJ3460] Jc的宿舍
- Linq 延迟加载
- c#进阶一:使用ILDASM来查看c#中间语言
- centos7修改网卡名字为传统名字
- Weekly Contest 119
- 3sum 求三数之和等于0,不允许重复
- VB6 Collection实现百万文本去重
热门文章
- sql-labs 1-14
- python学习第一天:window安装python开发环境完整篇
- 第三十六个知识点:Index Calculus算法
- 4.1.4 统计“锦途网”旅游线路平均价格,并采用尽可能多的方式将该价格赋给用户会话变量 @avg_short_price,并输出该变量
- Java访问Elasticsearch报错Request cannot be executed; I/O reactor status: STOPPED
- 【VUE】VUE使用常见问题搜集
- window10 查看端口列表 - 查看占用的进程-销毁该进程
- Centos 修改环境变量
- 制作JavaCV应用依赖的基础Docker镜像(CentOS7+JDK8+OpenCV4)
- Android官方文档翻译 三 1.1Creating an Android Project