C++ 逆向辅助学习----汇编基础 指令集合所有指令 7

60 篇文章 2 订阅
17 篇文章 2 订阅

九、汇编减法指令sub
    1.sun指令
       减法指令sub(subtract)
       格式: sub 操作数A,操作数B      A = A-B
       功能:两个操作数的相减,即从A中减去B,其结果放在A中
       
      ZF零标志位:若当前的运算结果为零,则ZF为1,否则为0
      注意:SUB指令影响ZF标志位

      
十、CMP和转移指令
    1.比较指令CMP
        格式:CMP 操作数A,操作数B    //A - B
        功能:两个操作数的相减,即从A中减去B,其结果会影响标志位,
              对标志位的影响与SUB指令相同。
              CMP指令主要是用于配合条件转移指令使用,如:JZ/JE  当ZF=1时跳转  

    2.等于条件转移指令JE/JZ
        格式:JE/JZ 标号   //等于跳转
        功能:ZF=1,跳转到指定地址执行
        说明:
           (1)JE与JZ等价,他们是根据标志位ZF进制转移的指令
           (2)JE、JZ均为一条指令的两种助记符表示方法
    
            1    if( a != b )   JE/JZ
                {
            2       a = b;
                }
            3    a = 2*b;
    
    3.不等于转移指令JNE/JNZ
        (1)JNE/JNZ功能
            条件转移指令JNE/JNZ  //不等于转移
            格式:JNE/JNZ 标号
            功能:ZF=0,转移至标号地址处执行
            1    if( a == b )   JNE/JNZ
                {
            2       a = b;
                }
            3    a = 2*b;
                
    4.无条件跳转指令jmp和goto指令
        (1)GOTO与JMP
            无条件跳转指令
            格式:JMP   A

        (2)其中A为转移的目的地址。程序转移到目的地址所指向的指令继续往下执行。
        (3)本组指令对标志位无影响
            
    
    5.有符号小于/不大于等于转移指令JL/JNGE
       格式: JL/JNGE  标号地址
       功能: 小于/不大于等于 时转移到标号地址
       JL    有符号      小于         则跳转 (Jump if less)
       JNGE  有符号      不大于等于   则跳转 (Jump if not greater or equal)
       
       SF = 1;  符号标志位为1    则跳转到标号地址执行(结果为负数)  
       
          Jump     跳转/转移
          Not      不
          Equal    相等
          Zero     零
          Less     小于
          Greater  大于

        if( a >=b ) //JL/JNGE
        {
            printf("do  a>=b\n");
        }
        printf("do a < b\n");

    6.有符号小于等于/不大于转移指令JLE/JNG
       格式: JLE/JNG  标号地址
       功能: 小于等于/不大于  时转到标号地址
       JNG   有符号   不大于         则跳转   (Jump  if  Not Greater)
       JLE   有符号   小于等于       则跳转   (Jump  if  Less or Equal)

       ZF = 1 ||  SF != OF (溢出标志位)  (SF = 1 && OF = 0  两个数相减   结果为负,且没有溢出)
                                           (SF = 0 && OF = 1  两个数相减   结果为正,且有溢出)

    7.有符号大于/不小于等于转移指令JG/JNLE
       格式: JG/JNLE 标号地址
       功能: 大于/不小于等于  时转到目标地址
       JG     有符号     大于           则跳转    (Jump if  Greater)
       JNLE   有符号     不小于等于     则跳转    (Jump if  Not Less or Equal)
    
       ZF = 0  &&  SF = OF  (SF=1 && OF=1  两个数相减 结果为负,有溢出)
                               (SF=0 && OF=0  两个数相减 结果为正,没有溢出)
                                           
    8.程序状态字寄存器PSW                                       
       (1)CF进位标志位
             当执行一个加法(减法)运算时,最高位产生进位(或借位)时,CF为1,否则为0

       (2)ZF零标志位
             若当前的运算结果为零,则ZF为1,否则为0
            
       (3)SF符号标志位
             该标志位于运算结果的最高位相同。即运算结果为负,则SF为1,否则为0

       (4)OF溢出标志位
             若运算结果超出机器能够表示的范围称为溢出,此时OF为1,否则为0       
            
              判断否是溢出的方法是:
               进行二进制运算时,最高位的进位与次高位的进位值进行异或运算
               若运算结果为1则表示溢出OF=1 ,否则OF=0               
                                           
            三条原则:
              同号相加和异号相减才会发生溢出
              同号相加结果的符号与参与运算的符号不同就溢出              
              异号相减结果的符号位与被减数的符号位不同就产生溢出                               
                                           
       (5)PF奇偶标志
             当运算结果的最低16位中含1的个数为偶数则PF=1,否则PF=0       
                                           
       (6)AF辅助进位标志
             一个加法(减法)运算结果的低4位向高4位有进位(或借位)时则AF=1,否则AF=0       
                                            
       (7)TF跟踪标志                                   
                 该标志位为方便程序调试而设置。若TF=1,CPU出于单步工作方式,
                 即在每条指令执行结束后,产生中断
                
       (8)IF中断标志位
              该标志位用来控制CPU是否响应可屏蔽中断。若IF=1则运行中断,否则禁止中断

       (9)DF方向标志
             该标志位用来控制串处理指令的处理方向。若DF=1则串处理过程中自动递减,否则自动递增       
       
    9.无符号大于转移指令 JA/JNBE   
       JA    :  高于           时跳转         即  >  时跳转
       JNBE  :  不低于等于     时跳转         即 <=  时不跳转
       
       Above   高于
       Below   低于
       
       JA与JG区别
           JG是带符号数比较    >
           JA是无符号数比较    >
       
       CF = 0 && ZF = 0      则跳转
       
    10.无符号大于等于转移指令JNB/JAE/JNC   
        JNB :  不低于      时跳转     即   >=  时不跳转
        JAE :  高于等于    时跳转     即   <   时不跳转
       
        JNC : Jump Not carry   没有进位时跳转   //CF=0
       
        unsigned int a = 5, b = 10;
        if(a2 < b2) //JAE/JNB
        {
            ....
        }
       
    11.无符号小于转移指令JB/JNAE/JC
        JB:      低于          时跳转           即   < 时跳转
        JNAE:    高于等于      时不跳转         即  >= 时不跳转
        
        JC : Jump  Carry    进位时跳转 //CF=1
          
       
    12.无符号大于转移指令JBE/JNA
        JBE:   低于等于       时跳转           即  <= 时跳转
        JNA:   高于           时不跳转         即  >  时不跳转


     课后自己写if条件语句来验证,注意区分无符号转移和有符号转移的区别

 

十一、CALL框架
       EBP 寄存器 栈底指针
       ESP 寄存器 栈顶指针

     1.EBP栈底指针
          EBP是一个特殊的寄存器,通过EBP+偏移量 可以访问CALL里边的局部变量
          它的低16位叫BP。   //EAX和AX的关系          

     2.ESP栈顶指针
          ESP栈顶指针与EBP栈底指针构成一段空间大小,一般就是本CALL局部变量的空间大小总和。
          ESP指针配合EBP使用。//SP
        
        总结:
          (1)每个CALL会分配一个独立的栈段空间,供局部变量使用

          (2)CALL栈平衡。进入CALL前与出CALL后,EBP和ESP的值不变


十二、PUSH、POP和CALL栈平衡RETN指令          
     1.PUSH 入栈指令 (压栈指令):
          格式: PUSH 操作数
          
          push ebp相当于:
               sub esp,4
               mov [esp],ebp

          操作数可以是寄存器,存储器,或者立即数
          
     2.POP出栈指令   (弹栈指令)      
          格式:POP  操作数
          
          pop ebp 相当于:
              mov ebp,[esp]
              add esp,4
 
         操作数是寄存器,或者存储器,不能是立即数
       
     3.代码分析
        (1)测试PUSH和POP 与ESP栈顶指针关系
        

        (2)CALL和RET(RETN)与ESP的关系
              CALL 执行时 会   PUSH  EIP
              RETN 执行时 会   POP   EIP
    
        (3)参数和局部变量的表示
               [EBP - ??]   ;本call中的局部变量
               [EBP + ??]   ;上一个call 局部变量,作为传入参数
       
       
十三、调用约定
     配置属性 --> c/c++ -->高级-->调用约定
    
    
    1.cdecl调用约定
          __cdecl  是C Declaration的缩写,所以参数从右到左依次入栈,
         这些参数由调用者清除,称为手动清栈。
        
        
        VC++ 默认约定__cdecl
        
        (1)源代码
            int __cdecl add1(int a,int b)
            {
                return a + b;
            }
        
        
        (2)生成的汇编代码
            013C1000  /$  55                    push    ebp                                     ; 保存main函数EBP栈底指针
            013C1001  |.  8BEC                  mov     ebp, esp                                ; 把栈底指针指向上一个call的栈顶
            013C1003  |.  8B45 08               mov     eax, dword ptr [arg.1]                  ; eax = a
            013C1006  |.  0345 0C               add     eax, dword ptr [arg.2]                  ; eax=eax+b=a + b
            013C1009  |.  5D                    pop     ebp                                     ; 恢复main函数的EBP栈底指针
            013C100A  \.  C3                    ret

        (3)调用代码
            013C1021  |.  6A 02                 push    2
            013C1023  |.  6A 01                 push    1
            013C1025  |.  E8 D6FFFFFF           call    013C1000                               
            013C102A  |.  83C4 08               add     esp, 8
        

    2.stdcall 调用约定
         API函数调用约定 __stdcall
        
         _stdcall 是standardcall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,
         如果是调用类成员的话,最后一个入栈的是this指针。
        
         这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是retn X,
         X表示参数占用的字节数(内存空间大小),CPU在ret之后自动弹出X个字节的栈空间,称为自动清栈。
        
        (1)源代码
           int __stdcall add2(int a,int b)
           {
                return a + b;
           }

        (2)生成的汇编代码
            009B1010  /$  55                    push    ebp                                    
            009B1011  |.  8BEC                  mov     ebp, esp
            009B1013  |.  8B45 08               mov     eax, dword ptr [ebp+8]
            009B1016  |.  0345 0C               add     eax, dword ptr [ebp+0C]
            009B1019  |.  5D                    pop     ebp
            009B101A  \.  C2 0800               ret     8

        (3)调用代码
            009B103D  |.  6A 04                 push    4
            009B103F  |.  6A 03                 push    3
            009B1041  |.  E8 CAFFFFFF           call    009B1010                              


    3.fastcall 调用约定
          _fastcall 是编译器指定的快速调用方式
           
        fastcall通常规定将前两个(或者若干个)参数由寄存器传递,其余参数还是通过堆栈传递。
        不同编译器编译的程序规定的寄存器不同。返回方式和stdcall相同。        


        (1)源代码
            int __fastcall add3(int a,int b)
            {
                return a + b;
            }

        (2)生成的汇编代码
            00221020  /$  55                    push    ebp
            00221021  |.  8BEC                  mov     ebp, esp
            00221023  |.  83EC 08               sub     esp, 8
            00221026  |.  8955 F8               mov     dword ptr [local.2], edx
            00221029  |.  894D FC               mov     dword ptr [local.1], ecx
            0022102C  |.  8B45 FC               mov     eax, dword ptr [local.1]
            0022102F  |.  0345 F8               add     eax, dword ptr [local.2]
            00221032  |.  8BE5                  mov     esp, ebp
            00221034  |.  5D                    pop     ebp
            00221035  \.  C3                    ret

        (3)调用代码
            00221066  |.  BA 06000000           mov     edx, 6
            0022106B  |.  B9 05000000           mov     ecx, 5
            00221070  |.  E8 ABFFFFFF           call    00221020                               

           参数传递没有用到栈,所以不用堆栈平衡

      
           但是如果参数比较多的话,那就需要自己平衡堆栈了:
            00101040  /$  55                    push    ebp                                    
            00101041  |.  8BEC                  mov     ebp, esp
            00101043  |.  83EC 08               sub     esp, 8
            00101046  |.  8955 F8               mov     dword ptr [local.2], edx
            00101049  |.  894D FC               mov     dword ptr [local.1], ecx               
            0010104C  |.  8B45 FC               mov     eax, dword ptr [local.1]
            0010104F  |.  0345 F8               add     eax, dword ptr [local.2]
            00101052  |.  0345 08               add     eax, dword ptr [arg1]
            00101055  |.  0345 0C               add     eax, dword ptr [arg2]
            00101058  |.  0345 10               add     eax, dword ptr [arg3]
            0010105B  |.  8BE5                  mov     esp, ebp
            0010105D  |.  5D                    pop     ebp
            0010105E  \.  C2 0C00               ret     0C


            001010A5  |.  6A 0B                 push    0B                                      ; /Arg3 = 0B
            001010A7  |.  6A 0A                 push    0A                                      ; |Arg2 = 0A
            001010A9  |.  6A 09                 push    9                                       ; |Arg1 = 9
            001010AB  |.  BA 08000000           mov     edx, 8                                  ; |
            001010B0  |.  B9 07000000           mov     ecx, 7                                  ; |
            001010B5  |.  E8 86FFFFFF           call    00101040                                ; \Lesson13.00101040

       
       注:
         C中不加说明的默认函数为_cdecl方式
         C++也一样,但是默认的调用方式可以在IDE(开发环境)中设置
        
         带有可变参数的函数必须且只能使用_cdecl方式,如:
          int printf(char* fmtstr,...);
          int scanf(char* fmtstr,...);
       


十四、常见C语句反汇编练习
    1.if-else 结构反汇编代码分析
      因为if{...} 语句块中的代码被执行的话,else{...}语句块的代码不会被执行,
      所以if{...} 中的代码执行完成之后,需要(jmp)无条件跳转到else{...}语句块
      后面的代码执行。
      
      ifelse02.exe 作为课后练习

    2.switch-case结构反汇编代码分析
     (1)普通情况
        013E1000  /$  55            push    ebp                              ; INT Lesson14.main(void)
        013E1001  |.  8BEC          mov     ebp, esp
        013E1003  |.  83EC 08       sub     esp, 8                           ; 两个4字节的局部变量
        013E1006  |.  68 F4203E01   push    offset 013E20F4                  ; ASCII "switch-case",LF
        013E100B  |.  FF15 A0203E01 call    dword ptr [<&MSVCR100.printf>]
        013E1011  |.  83C4 04       add     esp, 4
        013E1014  |.  C745 FC 03000 mov     dword ptr [ebp-4], 3             ; a = 3
        013E101B  |.  8B45 FC       mov     eax, dword ptr [ebp-4]           ; eax = a
        013E101E  |.  8945 F8       mov     dword ptr [ebp-8], eax           ; temp=eax=a
        013E1021  |.  837D F8 01    cmp     dword ptr [ebp-8], 1             ; temp与1作比较
        013E1025  |.- 74 0E         je      short 013E1035                   ; 等于则跳转
        013E1027  |.  837D F8 02    cmp     dword ptr [ebp-8], 2             ; temp与2作比较
        013E102B  |.- 74 18         je      short 013E1045
        013E102D  |.  837D F8 0A    cmp     dword ptr [ebp-8], 0A            ; temp与10作比较
        013E1031  |.- 74 22         je      short 013E1055
        013E1033  |.- EB 30         jmp     short 013E1065
        013E1035  |>  68 04213E01   push    offset 013E2104                  ; ASCII "111",LF
        013E103A  |.  FF15 A0203E01 call    dword ptr [<&MSVCR100.printf>]
        013E1040  |.  83C4 04       add     esp, 4
        013E1043  |.- EB 2E         jmp     short 013E1073                   ; jmp printf("end")
        013E1045  |>  68 0C213E01   push    offset 013E210C                  ; ASCII "222",LF
        013E104A  |.  FF15 A0203E01 call    dword ptr [<&MSVCR100.printf>]
        013E1050  |.  83C4 04       add     esp, 4
        013E1053  |.- EB 1E         jmp     short 013E1073
        013E1055  |>  68 14213E01   push    offset 013E2114                  ; ASCII "333",LF
        013E105A  |.  FF15 A0203E01 call    dword ptr [<&MSVCR100.printf>]
        013E1060  |.  83C4 04       add     esp, 4
        013E1063  |.- EB 0E         jmp     short 013E1073
        013E1065  |>  68 1C213E01   push    offset 013E211C                  ; ASCII "default",LF
        013E106A  |.  FF15 A0203E01 call    dword ptr [<&MSVCR100.printf>]
        013E1070  |.  83C4 04       add     esp, 4
        013E1073  |>  68 28213E01   push    offset 013E2128                  ; ASCII "end",LF
        013E1078  |.  FF15 A0203E01 call    dword ptr [<&MSVCR100.printf>]
        013E107E  |.  83C4 04       add     esp, 4
        013E1081  |.  33C0          xor     eax, eax
        013E1083  |.  8BE5          mov     esp, ebp
        013E1085  |.  5D            pop     ebp
        013E1086  \.  C3            ret
    
      
    (2)跳转表  
        002A1000  /$  55                    push    ebp
        002A1001  |.  8BEC                  mov     ebp, esp
        002A1003  |.  83EC 08               sub     esp, 8
        002A1006  |.  68 F4202A00           push    offset 002A20F4                         ; ASCII "switch-case 2",LF
        002A100B  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A1011  |.  83C4 04               add     esp, 4
        002A1014  |.  C745 FC 20000000      mov     dword ptr [local.1], 20
        002A101B  |.  8B45 FC               mov     eax, dword ptr [local.1]
        002A101E  |.  8945 F8               mov     dword ptr [local.2], eax
        002A1021  |.  8B4D F8               mov     ecx, dword ptr [local.2]
        002A1024  |.  83E9 10               sub     ecx, 10                                 ; temp = temp - 0x10
        002A1027  |.  894D F8               mov     dword ptr [local.2], ecx
        002A102A  |.  837D F8 12            cmp     dword ptr [local.2], 12                 ; temp 与 0x12 做比较
        002A102E  |.  77 61                 ja      short 002A1091
        002A1030  |.  8B55 F8               mov     edx, dword ptr [local.2]                ; edx = temp
        002A1033  |.  0FB682 CC102A00       movzx   eax, byte ptr [edx+2A10CC]              ; Switch (cases 0..5, 6 exits)
        002A103A  |.  FF2485 B4102A00       jmp     dword ptr [eax*4+2A10B4]
        002A1041  |>  68 04212A00           push    offset 002A2104                         ; ASCII "0x13",LF, case 1 of switch Lesson14.2A1033
        002A1046  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A104C  |.  83C4 04               add     esp, 4
        002A104F  |.  EB 4E                 jmp     short 002A109F
        002A1051  |>  68 0C212A00           push    offset 002A210C                         ; ASCII "0x15",LF, case 2 of switch Lesson14.2A1033
        002A1056  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A105C  |.  83C4 04               add     esp, 4
        002A105F  |.  EB 3E                 jmp     short 002A109F
        002A1061  |>  68 14212A00           push    offset 002A2114                         ; ASCII "0x10",LF, case 0 of switch Lesson14.2A1033
        002A1066  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A106C  |.  83C4 04               add     esp, 4
        002A106F  |.  EB 2E                 jmp     short 002A109F
        002A1071  |>  68 1C212A00           push    offset 002A211C                         ; ASCII "0x20",LF, case 3 of switch Lesson14.2A1033
        002A1076  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A107C  |.  83C4 04               add     esp, 4
        002A107F  |.  EB 1E                 jmp     short 002A109F
        002A1081  |>  68 24212A00           push    offset 002A2124                         ; ASCII "0x22",LF, case 4 of switch Lesson14.2A1033
        002A1086  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A108C  |.  83C4 04               add     esp, 4
        002A108F  |.  EB 0E                 jmp     short 002A109F
        002A1091  |>  68 2C212A00           push    offset 002A212C                         ; ASCII "default",LF, case 5 of switch Lesson14.2A1033
        002A1096  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A109C  |.  83C4 04               add     esp, 4
        002A109F  |>  68 38212A00           push    offset 002A2138                         ; ASCII "end",LF
        002A10A4  |.  FF15 A0202A00         call    dword ptr [<&MSVCR100.printf>]
        002A10AA  |.  83C4 04               add     esp, 4
        002A10AD  |.  33C0                  xor     eax, eax
        002A10AF  |.  8BE5                  mov     esp, ebp
        002A10B1  |.  5D                    pop     ebp
        002A10B2  \.  C3                    ret

      
    3.for循环结构反汇编代码分析  
      
      for(int i = 1; i<=10; ++i)
      {
        printf("%d",i);
      }
      
      
      (1)禁用优化情况下的for循环反汇编代码(0x43字节)
        00C51000  /$  55                    push    ebp
        00C51001  |.  8BEC                  mov     ebp, esp
        00C51003  |.  51                    push    ecx                                     ; sub esp,4; int i;
        00C51004  |.  68 F420C500           push    offset 00C520F4                         ; /Format = "for ",LF,""
        00C51009  |.  FF15 A020C500         call    dword ptr [<&MSVCR100.printf>]          ; \MSVCR100.printf
        00C5100F  |.  83C4 04               add     esp, 4
        00C51012  |.  C745 FC 01000000      mov     dword ptr [local.1], 1                  ; i = 1
        00C51019  |.  EB 09                 jmp     short 00C51024
        00C5101B  |>  8B45 FC               /mov     eax, dword ptr [local.1]
        00C5101E  |.  83C0 01               |add     eax, 1
        00C51021  |.  8945 FC               |mov     dword ptr [local.1], eax               ; ++i; i = i+1;
        00C51024  |>  837D FC 0A            |cmp     dword ptr [local.1], 0A
        00C51028  |.  7F 14                 |jg      short 00C5103E                         ; i > 10 跳转
        00C5102A  |.  8B4D FC               |mov     ecx, dword ptr [local.1]
        00C5102D  |.  51                    |push    ecx                                    ; /<%d> => [LOCAL.1]
        00C5102E  |.  68 FC20C500           |push    offset 00C520FC                        ; |Format = "%d"
        00C51033  |.  FF15 A020C500         |call    dword ptr [<&MSVCR100.printf>]         ; \MSVCR100.printf
        00C51039  |.  83C4 08               |add     esp, 8                                 ; esp = esp + 8
        00C5103C  |.^ EB DD                 \jmp     short 00C5101B
        00C5103E  |>  33C0                  xor     eax, eax
        00C51040  |.  8BE5                  mov     esp, ebp
        00C51042  |.  5D                    pop     ebp
        00C51043  \.  C3                    ret                                             ; return 0;

      (2)大小最小化优化情况下的for循环反汇编代码(0x27字节)
        010C1000  /$  56                    push    esi
        010C1001  |.  8B35 A0200C01         mov     esi, dword ptr [<&MSVCR100.printf>]
        010C1007  |.  57                    push    edi
        010C1008  |.  68 F4200C01           push    offset 010C20F4                         ; /Format = "for ",LF,""
        010C100D  |.  FFD6                  call    esi                                     ; \MSVCR100.printf
        010C100F  |.  33FF                  xor     edi, edi
        010C1011  |.  59                    pop     ecx                                     ; add esp,4; esp = esp + 4
        010C1012  |.  47                    inc     edi                                     ; edi = 1; int i = 1;
        010C1013  |>  57                    /push    edi                                    ; /<%d>
        010C1014  |.  68 FC200C01           |push    offset 010C20FC                        ; |Format = "%d"
        010C1019  |.  FFD6                  |call    esi                                    ; \MSVCR100.printf
        010C101B  |.  47                    |inc     edi                                    ; ++i
        010C101C  |.  59                    |pop     ecx
        010C101D  |.  59                    |pop     ecx                                    ; add esp,8
        010C101E  |.  83FF 0A               |cmp     edi, 0A
        010C1021  |.^ 7E F0                 \jle     short 010C1013                         ; if(i <=10 ) goto 0140c1013
        010C1023  |.  5F                    pop     edi
        010C1024  |.  33C0                  xor     eax, eax
        010C1026  |.  5E                    pop     esi
        010C1027  \.  C3                    ret

    (3)最大化速度优化情况下的for循环汇编代码
        010D1000  /$  56                    push    esi
        010D1001  |.  57                    push    edi
        010D1002  |.  8B3D A0200D01         mov     edi, dword ptr [<&MSVCR100.printf>]
        010D1008  |.  68 F4200D01           push    offset 010D20F4                         ; /Format = "for ",LF,""
        010D100D  |.  FFD7                  call    edi                                     ; \MSVCR100.printf
        010D100F  |.  83C4 04               add     esp, 4
        010D1012  |.  BE 01000000           mov     esi, 1                                  ; int i = 1
        010D1017  |>  56                    /push    esi                                    ; /<%d>
        010D1018  |.  68 FC200D01           |push    offset 010D20FC                        ; |Format = "%d"
        010D101D  |.  FFD7                  |call    edi                                    ; \MSVCR100.printf, add esp,8
        010D101F  |.  46                    |inc     esi                                    ; ++i
        010D1020  |.  83C4 08               |add     esp, 8
        010D1023  |.  83FE 0A               |cmp     esi, 0A
        010D1026  |.^ 7E EF                 \jle     short 010D1017                         ; if( i <=10) goto 010d1017
        010D1028  |.  5F                    pop     edi                                     ; i > 10 跳转
        010D1029  |.  33C0                  xor     eax, eax
        010D102B  |.  5E                    pop     esi
        010D102C  \.  C3                    ret

    (4)完全优化
        001A1000  /$  56                    push    esi
        001A1001  |.  57                    push    edi
        001A1002  |.  8B3D A0201A00         mov     edi, dword ptr [<&MSVCR100.printf>]
        001A1008  |.  68 F4201A00           push    offset 001A20F4                         ; /Format = "for ",LF,""
        001A100D  |.  FFD7                  call    edi                                     ; \MSVCR100.printf
        001A100F  |.  83C4 04               add     esp, 4
        001A1012  |.  BE 01000000           mov     esi, 1                                  ; int i = 1
        001A1017  |>  56                    /push    esi                                    ; /<%d>
        001A1018  |.  68 FC201A00           |push    offset 001A20FC                        ; |Format = "%d"
        001A101D  |.  FFD7                  |call    edi                                    ; \MSVCR100.printf, add esp,8
        001A101F  |.  46                    |inc     esi                                    ; ++i
        001A1020  |.  83C4 08               |add     esp, 8
        001A1023  |.  83FE 0A               |cmp     esi, 0A
        001A1026  |.^ 7E EF                 \jle     short 001A1017                         ; if( i <=10) goto 010d1017
        001A1028  |.  5F                    pop     edi                                     ; i > 10 跳转
        001A1029  |.  33C0                  xor     eax, eax
        001A102B  |.  5E                    pop     esi
        001A102C  \.  C3                    ret

       
    4.自增++和自减--语句
      (1)加1指令inc
         inc  操作符
          
         inc  a    相当于 add a,1   //i++ ++i
        
         优点 速度比add指令快,占用空间小
         这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF进位标志位
        
      (2)减1指令dec
         dec 操作符
        
         dec a 相当于sub a,1 //i-- --i
        
         优点 速度比sub指令快,占用空间小
         这条指令执行结果影响AF、OF、PF、SF、ZF标志位,但不影响CF进位标志位
      
      (3)用汇编理解前++、前--、后++、后--区别
        

    5.do-while和while 循环结构反汇编代码分析
      (1)do-while循环
      (2)while循环      
      (3)for while do-while的区别
       
十五、浮点指令
    1.浮点数的存放方式
        01311000  /$  55                    push    ebp
        01311001  |.  8BEC                  mov     ebp, esp
        01311003  |.  51                    push    ecx
        01311004  |.  68 F4203101           push    offset 013120F4                         ; ASCII "fld",LF
        01311009  |.  FF15 A0203101         call    dword ptr [<&MSVCR100.printf>]
        0131100F  |.  83C4 04               add     esp, 4
        01311012  |.  D905 08213101         fld     dword ptr [1312108]                     ; float 8.786000
        01311018  |.  D95D FC               fstp    dword ptr [local.1]
        0131101B  |.  D945 FC               fld     dword ptr [local.1]
        0131101E  |.  DC05 00213101         fadd    qword ptr [1312100]                     ; float 1.000000000000000
        01311024  |.  D95D FC               fstp    dword ptr [local.1]
        01311027  |.  33C0                  xor     eax, eax
        01311029  |.  8BE5                  mov     esp, ebp
        0131102B  |.  5D                    pop     ebp
        0131102C  \.  C3                    ret

    
    2.st0至st7
       80位的两用寄存器
       MMX FPU

    3.浮点指令
        1).FLD类似于   PUSH指令
            向st0中放入数据
            
        2).FSTP类似于  POP指令
            st0 中的数据取出
            
        3).FADD类似于  ADD指令
            格式
            fadd memvar   //st0 = st0 + memvar

        3).FSUB类似于  SUB指令
           格式
           fsub memvar   //st0 = st0 - memvar

        5).FMUL 乘法指令
           格式
           fmul memvar  //st0 = st0 * memvar;
           
        6).FDIV 除法指令
           格式
           FDIV memvar  //st0 = st0 / menvar           
 
        7)FILD 整数转浮点指令
            整数放入st0寄存器
            FILD  memvar    // st0 = (double)memvar            
         
        8)CVTTSD2SI 浮点转整数指令
          cvttsd2si r32,  st0/m32
          运用截断处理将st0/m32 中的一个单精度浮点值转换成r32
          中的一个有符号的双字整数

          and     esp, FFFFFFF8(优化对齐)


十六、位移指令
    1.逻辑位移指令
       (1)SHR 逻辑右移指令
            右移一位相当于整除2,用0来补位
    
       (2)SHL 逻辑左移指令
           左移一位相当于乘2,用0来补位(有可能会溢出)       
    
    
    2.算术位移指令
       (1)SAR  算术右移指令
           SAR与SHR指令:
             SAR 右移时保留操作数的符号,即用符号位来补足
             SHR 右移时总是用0来补足
       
       (2)SAL 算术左移指令
            SAL与SHL 功能完全一样
    
       (3)循环位移指令
           ROL  循环左移
           ROR  循环右移
           
           
十七、逻辑运算符
    1.或运算
      1)逻辑或(C语言中的||)
         条件真和假:非零为真,零为假      
          
         假假为假    
         
         c = a || b
         if( c )
         {
            
         }
        
         截断原理
        
      2)按位或(C语言中的|)
          0x33       00110011
        | 0x66       01100110
        = 0x77       01110111
    
        OR指令
    
    
    2.与运算
      1)逻辑与(C语言中的&&)
         真真为真
    
         c = a && b
         if( c )
         {
            
         }
         截断原理

      2)按位与(C语言中&)      
            0x33       00110011
        & 0x66       01100110
        = 0x22       00100010

        AND指令
    
    3.非运算
      1)逻辑取反(C语言中的 !)    
         假变真  真变假
    
        SETE(SETZ)       取ZF标志位的值保存
        SETNE(SETNZ)     将ZF标志位的值取反后保存
        
      2).按位取反(C语言中的~)       
        ~  0x33      00110011    
        =  0xcc      11001100
        
        NOT 指令    
        
    4.异或运算
      1)按位异或(C语言中的^)    
         1^1 = 0;   0^0 = 0;  相同为0
         0^1 = 1;   1^0 = 1;  不同为1        
        
            1101
          ^ 0110
          = 1011      
        
        XOR 指令
          xor  eax,eax   将eax置0
        
       不借助第三个变量,将两个数做交换
        int a = 5, b = 7;
        a = a + b;
        b = a - b;
        a = a - b;
        
        a = a^b;
        b = a^b;
        a = a^b;
        
       
    逻辑运算指令小结:
     OR  : 按位或运算,有1为1,全0为0。
        如:101100   
        OR  110101
        =   111101    
       
    AND :  按位与运算,有0为0,全1为1。    
        如:1011
       AND  1101
         =   1001
       
    NOT : 取反运算,0变成1,1变成0   
        如: NOT  1011
             =    0100
       
    XOR : 异或运算,相同则为0,不相同为1
        如: 1101
        XOR  0110
         =   1011


十八、字符操作相关指令
    1.字符串的比较函数strcmp反汇编分析        
        VS设置 项目->属性->C/C++ ->优化->启动内部函数->"否"

    
    2.REPNE和SCASB指令    
     1)SCASB指令
        SCASB编译后: SCAS BTYP PTR [EDI]
                
        相当于:
          cmp byte prt[edi],al

        对标志位的影响相当于sub指令,同时还会修改寄存器EDI的值:
           如果标志位DF为0,则 inc EDI;
           如果标志位DF为1,则 dec EDI;
           
     2)REPNE指令
        repnz scasb 编译后:REPNE SCAS BTYP PTR ES:[EID]    
           
        当ECX!=0并且ZF=0时,重复执行后边的指令(SCAS BTYP PTR ES:[EDI]),
        每执行一次ECX的值减1

        REPNE 和REPNZ 是同一条指令的不同助记符
        
           
     3)SCASB、SCASW、SCASD指令
          SCASB  SCAS BTYP PTR [EDI]       char    s1[0]   byte  1
          SCASW     SCAS WORD PTR [EDI]       short   s1[0]   word  2
          SCASD  SCAS DWORD PTR [EDI]      int     s1[0]  dword  4    

        REPNE SCAS BTYP PTR [EDI]  当ECX!=0并且ZF=0、DF=0时,重复执行后面的指令
        每次执行一次EDI的值加1,ECX的值减1
        
        REPNE SCAS WORD PTR [EDI]  当ECX!=0并且ZF=0、DF=0时,重复执行后面的指令
        每次执行一次EDI的值加2,ECX的值减1
        
        REPNE SCAS DWORD PTR [EDI]  当ECX!=0并且ZF=0、DF=0时,重复执行后面的指令
        每次执行一次EDI的值加4,ECX的值减1
 
       (调试时,按F7才能单步执行)

     4)实例运用
         1.计算字符串长度
         2.定位特定字符串位置(索引)
         3.在内存中定位一串特征码
       
     小结:
       REPNZ/REPNE与SCASB指令结合使用,表示当串未结束(ECX!=0),且当
       对应串元素不相同(ZF=0)时,继续重复执行串比较指令

    
    3.REPE/REPZ和CMPSB、CMPSW、CMPSD指令
      1)CMPS
         cmps byte ptr [edi],byte ptr [esi]      
         cmps word ptr [edi],byte ptr [esi]
         cmps dword ptr [edi],byte ptr [esi]
       
        对标志位的影响相当于sub指令,同时还会修改寄存器EDI和ESI的值:
          如果标志DF为0,则edi、esi按相对于大小(byte word dword)递增
          如果标志DF为1,则edi、esi按相对于大小(byte word dword)递减
       
      2)REPE/REPZ
        repe/repz cmpsb 当ecx!=0并且ZF=1时,重复执行后面的指令
        每执行一次ecx的值减1

      3)实例运用
          比较串是否相等

          
    4.汇编编写字符串比较函数
        1)asm_strcmp函数
           __declspec(naked)  告诉编译器用纯汇编方式编译函数,不自动添加
                               寄存器保护和堆栈平衡代码
           寄存器入栈保护
           维持堆栈平衡
           asm_strcmpA/asm_strcmpW           
       
       2)STD/CLD指令(DF方向标志位相关)
         STD    DF = 1
         CLD    DF = 0
       

       
十九、串存储和串的加载指令
      1.串存储指令STOSB、STOSW、STOSD
        stosb      stos byte  ptr [edi]
        stosw      stos word  ptr [edi]
        stosd      stos dword ptr [edi]

        相当于:
          mov byte  ptr [edi],al
          mov word  ptr [edi],ax
          mov dword ptr [edi],eax

        rep stosb       rep stos byte ptr [edi]
        用al的值 填充byte ptr [edi],每次ecx值减1,edi的值增加1
           
        rep stosw       rep stos word ptr [edi]
        用ax的值 填充word ptr [edi],每次ecx值减1,edi的值增加2

        rep stosd       rep stos dword ptr [edi]
        用eax的值 填充dword ptr [edi],每次ecx值减1,edi的值增加4        
       
     定位main函数位置的步骤:
    
    第一步:打开程序,程序启动后停在这里,直接jmp跳转
        013012E2  /$  E8 82040000           call    01301769
        013012E7  \.^ E9 B3FDFFFF           jmp     0130109F

    第二步:jmp跳转跟随之后,找到call    dword ptr [<&MSVCR100.exit>]退出的代码的位置
        013011AA  |.  FF35 1C303001         push    dword ptr [130301C]
        013011B0  |.  FF35 20303001         push    dword ptr [1303020]
        013011B6  |.  FF35 18303001         push    dword ptr [1303018]
        013011BC  |.  E8 3FFEFFFF           call    01301000
        013011C1  |.  83C4 0C               add     esp, 0C
        013011C4  |.  A3 30303001           mov     dword ptr [1303030], eax
        013011C9  |.  391D 24303001         cmp     dword ptr [1303024], ebx
        013011CF  |.  75 37                 jne     short 01301208
        013011D1  |.  50                    push    eax
        013011D2  |.  FF15 84203001         call    dword ptr [<&MSVCR100.exit>]

    第三步:call    dword ptr [<&MSVCR100.exit>]的前一个call就是main函数
        013011AA  |.  FF35 1C303001         push    dword ptr [130301C]
        013011B0  |.  FF35 20303001         push    dword ptr [1303020]
        013011B6  |.  FF35 18303001         push    dword ptr [1303018]
        013011BC  |.  E8 3FFEFFFF           call    01301000
        013011C1  |.  83C4 0C               add     esp, 0C


    2.串载入指令LODSB、LODSW、LODSD
      lodsb      lods byte ptr [esi]    
      lodsw      lods word ptr [esi]
      lodsd      lods dword ptr [esi]

      相当于:
        mov al,  byte ptr [esi]
        mov ax,  word ptr [esi]
        mov eax, dword ptr [esi]
        
     rep lodsb     rep  lods byte ptr [esi]
     用byte ptr [esi]的值,填充al,每次ecx值减1,esi的值增加1    
        
     rep lodsw     rep  lods word ptr [esi]
     用word ptr [esi]的值,填充ax,每次ecx值减1,esi的值增加2    
        
     rep lodsd     rep  lods dword ptr [esi]
     用dword ptr [esi]的值,填充eax,每次ecx值减1,esi的值增加4    
    
    
二十、循环控制指令
       格式: LOOP 标号
       loop  start/end
         功能:
          (1)ECX = ECX - 1
          (2)ECX != 0,则转移至标号处循环执行
          (3)直至ECX = 0,继续执行后面的指令
    
       本指令是用ECX寄存器作为计数器,来控制程序的循环
    

二十一、条件置位指令
    1. (== 比较时)
        SETZ(SETE)     取ZF标志位的值保存    
    
    2. (!= 比较时)
        SETNZ(SETNE)  将ZF标志位值取反后保存
    
    3.SETG ( > 比较时)    
       setg al
      当 ZF == 0 && SF == 0 && OF == 1时 al = 1
    
    4.SETL( < 比较时)
       setl al
      当SF==1 || OF == 1时 al = 1

    5.SETGE(>=比较时)
       SETGE 操作数
         操作数可以是一个字节的存储单元,可以是一个字节宽度的寄存器
        
       作用: >=时,设定操作数值1,否则为0,一般与cmp指令组合使用

       标志位:JGE 对标志的需求  SF=OF时,操作数的值将为1

    6.SETGE(<=比较时)
       SETLE 操作数
         操作数可以是一个字节的存储单元,可以是一个字节宽度的寄存器
        
       作用: <=时,设定操作数值1,否则为0,一般与cmp指令组合使用

       标志位:JLE 对标志的需求  ZF=1 || SF != OF 时,操作数的值将为1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值