彙編之循環語句

今天看了《加密與解密》循環語句部分,接下來將從do-while循環,while循環,for循環三個方面去學習循環的彙編。

0x01 do-while循環

do-while循環的流程是:先執行語句塊,在進行表達式判斷,當表達式爲真時,在繼續執行語句塊。接下來先看一段C語言代碼

 #include "stdafx.h"

    int main(int argc, char* argv[])
    {
        int nCount=0;
        do{
            printf("%d\r\n",nCount);
            nCount++;   
        }
            while(nCount<argc);   argc爲整型,用來統計程序運行時發送給main函數的命令行參數的個數,在VS中默認值爲1return 0;
    }

切到反彙編模式
在這裏插入圖片描述
可以看到,先執行了輸出語句和nCount的自增,然後比較nCount和argc的大小,若小於則循環,否則將線性向下執行。
下面是我寫的彙編代碼


 #include "stdafx.h"

    int main(int argc, char* argv[])
    {
            //int nCount=0;
            char *str="%d\r\n";
            _asm{
                          mov eax,0
        circle:           push eax
                          push str
                         call printf       //調用printf函數
                          add esp,8       //平衡棧
                          inc eax         //nCount自增,         
                        cmp eax,dword ptr [ebp+8]
                       jl circle             //if (nCount<argc),跳轉到circle循環執行
                       xor eax,eax     //設置返回值爲0
            }
    }

成功運行!
在IDA Pro裏面識別do—while循環
在這裏插入圖片描述在這裏插入圖片描述

0x02 while循環

while循環的流程是:先進行表達式判斷,在執行語句塊,當表達式爲真時,會繼續執行語句塊,示例如下

#include<stdio.h>
void main()
{
      char *str="%d\n";
_asm{
                  mov eax,1             //i=1
                  mov ebx,0            //sum=0
circle:           cmp eax,100
                  jg   end
                 add ebx,1              //sum++
                 inc eax,1            //i++
                 jmp circle
end:
                 push ebx
                 push str
                 call printf
                 add esp,8
}
}

切入到反彙編:
在這裏插入圖片描述
可以看到,先比較i與100的大小,若i<=100,則執行語句塊,否則就直接輸出sum。
下面是我寫的彙編代碼

#include<stdio.h>
void main()
{
      char *str="%d\n";
_asm{
                    mov eax,1             //i=1
                  mov ebx,0            //sum=0
circle:           cmp eax,100
                  jg   end
                 add ebx,1              //sum++
                  inc eax,1            //i++
                 jmp circle
end:
                  push ebx
                  push str
                  call printf
                 add esp,8
}
}

在IDA Pro裏面識別while循環
在這裏插入圖片描述在這裏插入圖片描述
循環的特點是會向低地址跳轉。while循環和do-while循環區別:
1.while循環使用的是jmp循環,while循環使用的是jxx彙編指令需要取反
2.while循環比do循環多一次if判斷,因此性能上while循環不如do循環高,在Release版本中,編譯器會把while循環優化成等價的do循環。

0x03 for循環

for語句由賦初值,循環條件,循環步長三條語句組成,示例如下:

  #include "stdafx.h"

    int main(int argc, char* argv[])
    {
        for(int nCount=0; nCount<argc;nCount++)
               {
                            printf("%d\r\n",nCount);
               }
                    return 0;
    }

切入到反彙編
在這裏插入圖片描述
在這裏可以看到,對nCount賦值以後,就跳到判斷的位置,如果判斷結果爲真,就跳上去執行語句塊
接下來是我寫的彙編代碼

   #include "stdafx.h"

    int main(int argc, char* argv[])
    {
          char *str="%d\r\n";
    _asm{
                mov eax,0   
                         jmp judge
    circle:      add eax,1
    judge:     cmp eax,dword ptr[ebp+8]
                                 jge circle
                          push eax
                          push str
                          call printf
                add esp,8
                xor eax,eax
    }
    }

在IDA Pro裏面識別for循環
在這裏插入圖片描述在這裏插入圖片描述關於循環語句的學習就先到這裏。

eax加1,可以有如下兩種表示:

    inc eax
    add eax,1

複製代碼
雖然功能一樣,可還是有以下區別:
(1) 機器碼長度不同,inc短,add長。(這不是關鍵)
(2)INC不改變標誌位CF,而ADD則改變CF。(這點很關鍵。)
例如:

        number dw 0FFFFH,1234H,0,0,0
       表示的80位數1234FFFFH,希望給它加2。
        MOV SI,OFFSET NUMBER
         MOV CX,4              ;4個高位的字單元
        ADD WORD PTR [SI],2   ;最低位加2
L1:
         INC SI
         ADC WORD PTR [SI],0   ;把產生的進位加到高位
        LOOP L1

若把INC SI換成ADD SI,1就會出錯。原因是 ADD WORD PTR [SI],2產生了CF,若用ADD SI,1就會把CF清0,從而後面的ADC就不能把前面的進位加上。

   dec eax
   sub eax,1

複製代碼
eax減1,dec和sub的區別也和加1類似。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章