在Visual Studio 2013中,新建一个空的32位C++工程,只有一个main()方法,如下:
点鼠标右键,反汇编以后如下:
下面是用到的寄存器的简单说明:
eax -- 是累加器(accumulator), 它是很多加法乘法指令的缺省寄存器。
ebx -- 是基地址(base)寄存器, 在内存寻址时存放基地址。
ecx -- 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
edx -- 则总是被用来放整数除法产生的余数。
esi/edi -- 分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.
ebp -- 是"基址指针"(BASE POINTER),被形象地称为是栈底指针, 它最经常被用作高级语言函数调用的"框架指针"(frame pointer).
esp -- 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。
下面是用到的指令的简单说明:
mov dest,src :把一个字节,字或双字从源操作数src传送至目的操作数dest
pop dest : 从栈顶弹出操作数送入目的操作数dest 。在32位平台上,出栈操作pop使esp每次增加4字节。
lea reg,mem : 将源操作数mem的有效地址传送到通用寄存器reg
push src : 将源操作数src压下堆栈,使esp每次减少4字节
sub dest,src : 将目的操作数减源操作数,结果送目的操作数
xor dest,src : 目的操作数和源操作数按位进行逻辑异或运算,结果送目的操作数。 xor eax,eax 相当于mov eax,0
rep : 指令的目的是重复其后面的指令.ecx的值是重复的次数.rep可以是任何字符传指令(CMPS, LODS, MOVS, SCAS, STOS)的前缀. rep能够引发其后的字符串指令被重复, 只要ecx的值不为0, 重复就会继续. 每一次字符串指令执行后, ecx的值都会减小.
stos dst : 把eax的内容拷贝到目的地址 dst。其中stos是 store into string的简写。
ret: 用栈中的数据,修改eip的内容,从而实现近转移. 相当于进行 pop eip
理解:
void main()
{
}
点鼠标右键,反汇编以后如下:
void main()
{
01301380 push ebp
01301381 mov ebp,esp
01301383 sub esp,0C0h
01301389 push ebx
0130138A push esi
0130138B push edi
0130138C lea edi,[ebp-0C0h]
01301392 mov ecx,30h
01301397 mov eax,0CCCCCCCCh
0130139C rep stos dword ptr es:[edi]
}
0130139E xor eax,eax
013013A0 pop edi
013013A1 pop esi
013013A2 pop ebx
013013A3 mov esp,ebp
013013A5 pop ebp
013013A6 ret
下面是用到的寄存器的简单说明:
eax -- 是累加器(accumulator), 它是很多加法乘法指令的缺省寄存器。
ebx -- 是基地址(base)寄存器, 在内存寻址时存放基地址。
ecx -- 是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器。
edx -- 则总是被用来放整数除法产生的余数。
esi/edi -- 分别叫做"源/目标索引寄存器"(source/destination index),因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.
ebp -- 是"基址指针"(BASE POINTER),被形象地称为是栈底指针, 它最经常被用作高级语言函数调用的"框架指针"(frame pointer).
esp -- 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。
下面是用到的指令的简单说明:
mov dest,src :把一个字节,字或双字从源操作数src传送至目的操作数dest
pop dest : 从栈顶弹出操作数送入目的操作数dest 。在32位平台上,出栈操作pop使esp每次增加4字节。
lea reg,mem : 将源操作数mem的有效地址传送到通用寄存器reg
push src : 将源操作数src压下堆栈,使esp每次减少4字节
sub dest,src : 将目的操作数减源操作数,结果送目的操作数
xor dest,src : 目的操作数和源操作数按位进行逻辑异或运算,结果送目的操作数。 xor eax,eax 相当于mov eax,0
rep : 指令的目的是重复其后面的指令.ecx的值是重复的次数.rep可以是任何字符传指令(CMPS, LODS, MOVS, SCAS, STOS)的前缀. rep能够引发其后的字符串指令被重复, 只要ecx的值不为0, 重复就会继续. 每一次字符串指令执行后, ecx的值都会减小.
stos dst : 把eax的内容拷贝到目的地址 dst。其中stos是 store into string的简写。
ret: 用栈中的数据,修改eip的内容,从而实现近转移. 相当于进行 pop eip
理解:
void main()
{
01301380 push ebp ;将ebp压栈
01301381 mov ebp,esp ;将现在的栈顶esp作为函数调用时的栈底
01301383 sub esp,0C0h ; 把esp往上移动一个范围0C0h,等于在栈中空出一片空间来存局部变量
01301389 push ebx ;保存寄存器的值
0130138A push esi ;保存寄存器的值
0130138B push edi ;保存寄存器的值
0130138C lea edi,[ebp-0C0h] ;把ebp-0C0h加载到edi中,目的是保存局部变量的区域
01301392 mov ecx,30h ;从ebp-0C0h开始的区域初始化成全部0CCCCCCCCh,就是int3断点,一个中断指令,初始化局部变量空间
01301397 mov eax,0CCCCCCCCh
0130139C rep stos dword ptr es:[edi]
}
0130139E xor eax,eax
013013A0 pop edi ;恢复原来寄存器的值,怎么“吃”进去,怎么“吐”出来
013013A1 pop esi
013013A2 pop ebx
013013A3 mov esp,ebp ;还原栈顶指针 恢复原来的esp和ebp,让上一个调用函数正常使用
013013A5 pop ebp ;还原栈底指针
013013A6 ret ;将返回地址存入eip,转移流程