stand on the shoulders of giants

【代码真相】之 汇编

寄存器

1. 8个32位寄存器
eax     ebx     ecx     edx
esp     ebp     edi     esi

eax-edx这四个是通用寄存器  ax-dx 访问低十六位,其中ah是高八位 al低八位
esp-esi这四个主要是寻址时用来存放偏移或指针,所以,也就称为指针寄存器或变址寄存器了

ESP(堆栈指针寄存器): 
     指向栈顶
EBP(基址指针寄存器): 
     与堆栈段寄存器SS(堆栈段)联用来确定堆栈中的某一存储单元的地址
     ESP用来指示段顶的偏移地址,而EBP可作为堆栈区中的一个基地址以便访问堆栈中的信息。
     EBP始终指向的是当前函数所在栈区的栈基址。ebp操作上层函数传来的变量时,是通过ebp加上一个数值取参数,当操作自己函数内部定义的变量的时候,是通过EBP减去一个数值来取得。
ESI(源变址寄存器)和EDI(目的变址寄存器)
     一般与数据段寄存器DS联用,用来确定数据段中某一存储单元的地址。
     这两个变址寄存器有自动增量和自动减量的功能,可以很方便地用于变址。

2. EIP(指令指针寄存器): 
     指向的就是下一条将要执行的指令的指针!

3. flags(标志寄存器): 
     存放条件标志码、控制标志和系统标志的寄存器! 
     ZF(零标志) 当计算结果是零时该标志被设置(compare实际上是只设置标志不保存结构的减法) 
     SF(符号标志) 结果为负就设置 
     CF(carry标志) Carry标志中存放计算后最右的位。 
     OF(溢出标志) 标明一个溢出了的计算。如,结构和目标不匹配。

4. 段寄存器:
     cs代码段,ds数据段,ss堆栈段,es附加段
     在Win32编程中段的概念已经不重要了

常用命令

cmp eax,ecx     比较eax和ecx,置标志位!eax-ecx = 0 置zf为1,否则zf为0
jge XXXXXXXX    条件跳转命令 “如果大于等于就跳转”(jge)和“符号标志=溢出标志”一样

xor eax,eax     eax与自己异或,是清零的操作!
lea eax,str     并不传送数据,只传送该数据的地址,将str字符串的地址传到eax
push dword ptr ds:[*****]      在ds(数据段)把[*****]开始的一个双字长数值取出来
     szTextFmt   BYTE '%d',0 
     mov al,byte ptr ds:szTextFmt      就把 % 取出来 而不包括 d

指令的长度
所谓指令的长度,就是描述一条指令所需要的字节数,用一个字节能描述的指令我们叫1字节指令,同理,用两个字节描述的叫2字节指令,用三个字节描述的指令就叫3字节指令。


常用代码结构

1. For循环

for(int i=0; i<100; i++)
 {
  
//循环体
 }

 
//Next Line

汇编中的结构是这样的

for(int i=0; i<100; i++)
0040179F   mov         dword ptr [ebp-8],0         //int i=0
004017A6   jmp         main+31h (004017b1)
004017A8   mov         eax,dword ptr [ebp-8]     // i++
004017AB   add         eax,1
004017AE   mov         dword ptr [ebp-8],eax
004017B1   cmp         dword ptr [ebp-8],64h    //和100比较
004017B5   jge         main+42h (004017c2)      //大于等于跳转 i>=100
29:       {
.循环体
31:       }
004017C0   jmp         main+28h (004017a8)
32:
004017C2   Next Line


2. Whille循环

int j = 0;
while (j<100) {
  //循环体 
}
// Next Line

27:       int j = 0;
00401798   mov         dword ptr [ebp-4],0
28:       while (j<100) {
0040179F   cmp         dword ptr [ebp-4],64h
004017A3   jge         main+30h (004017b0)
29:         //循环体  
30:           j++;
004017A5   mov         eax,dword ptr [ebp-4]
004017A8   add         eax,1
004017AB   mov         dword ptr [ebp-4],eax
31:       }
004017AE   jmp         main+1Fh (0040179f)
32:
33:       int szNum[5] = { 12345 };
004017B0   Next Line

 

3. Swich

switch(i) {
 case 0:
  //...
  break;
 case 1:
  //...
  break;
 default:
  //....
 }
// Next Line

28:       switch(i) {
004017BF   mov         eax,dword ptr [ebp-4]
004017C2   mov         dword ptr [ebp-30h],eax       将i的值放入临时变量中
004017C5   cmp         dword ptr [ebp-30h],0         与0比较
004017C9   je          main+33h (004017d3)           相等则跳转
004017CB   cmp         dword ptr [ebp-30h],1         与1比较
004017CF   je          main+53h (004017f3)
004017D1   jmp         main+73h (00401813)
29:       case 0:
004017D3   //
30:       break;
004017F1   jmp         main+91h (00401831)
31:       case 1:
004017F3   //
32:       break;
00401811   jmp         main+91h (00401831)
33:       default:
34:           break;
35:       }                                         switch函数结束
36:
47:       //Next Line
00401831  

 





 

posted @ 2008-12-16 23:34  DylanWind  阅读(342)  评论(0编辑  收藏  举报