天天看點

實驗4 彙編應用程式設計和c語言程式反彙編分析

1. 實驗任務1

   教材「實驗9 根據材料程式設計」(P187-189)

   程式設計:在螢幕中間分别顯示綠色、綠底紅色、白底藍色的字元串\'welcome to masm!\'。

   程式正确編寫後,預期輸出結果如下:

實驗4 彙編應用程式設計和c語言程式反彙編分析

  實驗代碼4如下:

1 ;task1.ASM
 2 assume cs:code, ds:data
 3 data segment
 4     db \'welcome to masm!\'
 5     db 2h,24h,71h      
 6     ;綠色:2h,綠底紅字:24h,白底藍字:71h
 7 data ends
 8 
 9 code segment
10 start:
11     mov ax, data
12     mov ds, ax              ;傳遞data段的段位址給ds
13     mov ax,0b872h           ;根據提示得出的顯示器中心區域的顯存位址(第十二行)
14     mov es,ax               ;字元将要存入的顯存位址段
15     
16     mov di,0
17     mov ah,ds:[di+10h]       ;将資料段中用于修改顯示顔色的資料存入寄存器中
18     mov al,ds:[di+11h]
19     mov bh,ds:[di+12h]
20     mov si,0
21     mov cx,16              ;循環次數
22 s:  mov bl,ds:[si]          ;從資料段中取資料
23     mov es:[di],bl         ;存入顯存位址段中(在第十二行顯示)
24     mov es:[di+1],ah       ;修改字元顔色
25     mov es:[di+0a0h],bl    ;存入顯存位址段中(在第十三行顯示)
26     mov es:[di+0a1h],al    ;修改字元顔色
27     mov es:[di+140h],bl    ;存入顯存位址段中(在第十四行顯示)
28     mov es:[di+141h],bh    ;修改字元顔色
29     inc si
30     add di,2
31     loop s
32         
33     mov ax,4c00h
34     int 21h
35 code ends
36 end start      

  編譯、連接配接後執行task1.exe,結果如圖:

實驗4 彙編應用程式設計和c語言程式反彙編分析

     根據提示:doSbox顯示視窗是80×25彩色字元模式顯示,重複三次顯示\'welcom to masm!\'需要将資料存入的現存位址為:

      十二行中心區域:b800:0720~b800:0740(32個位元組(十六個字元十六個顔色))

                     十三行中心區域:b800:07C0~b800:07E0

                     十四行中心區域:b800:0860~b800:0880

     使用debug,在使用g指令執行完程式後檢視對應位址的資料:(虛拟機中win7系統的cmd指令視窗)

實驗4 彙編應用程式設計和c語言程式反彙編分析

 2. 實驗任務2   編寫子程式printStr,實作以指定顔色在螢幕上輸出字元串。調用它,完成字元串輸出。

  編寫子程式printStr,實作以指定顔色在螢幕上輸出字元串。調用它,完成字元串輸出。

  子程式printSar

         功能:以指定顔色在螢幕上(從螢幕左上角開始)輸出字元串

  要求:字元串以0結尾

  入口參數

  字元串的起始位址—> ds: si (其中,字元串所在段的段位址—> ds, 字元串起始位址的偏移位址—> si,字元串顔色—> al

  出口參數:無

  使用任意文本編輯器,錄入彙程式設計式task2.asm。

1 assume cs:code, ds:data
 2 data segment
 3     str db \'try\', 0
 4 data ends
 5 
 6 code segment
 7 start:  
 8     mov ax, data
 9     mov ds, ax
10 
11     mov si, offset str   ;取data資料段的偏移位址
12     mov al, 2            ;用于顯示字元的顔色
13     call printStr        ;跳轉到标号printStr(原IP入棧,再給IP賦新值,即标号printStr得偏移位址)
14 
15     mov ah, 4ch
16     int 21h
17 
18 printStr:
19     push bx             ;儲存子程式調用前相關寄存器的狀态,用于在執行完子程式塊後回到該狀态
20     push cx
21     push si
22     push di
23 
24     mov bx, 0b800H      ;字元顯示處的位址段
25     mov es, bx          ;es記錄顯存位址
26     mov di, 0
27 s:      mov cl, [si]    ;取出資料段中的段資料(存入cx的低位中)
28     mov ch, 0           ;cx高位為0
29     jcxz over           ;cx為0則轉到标号over處執行(當data資料段的取完即取出的是最後一個資料(0)時跳轉)
30     mov ch, al          ;已經判斷cx不為0,data資料段的資料未取完
31     mov es:[di], cx
32     inc si              ;移向下一個位元組
33     add di, 2
34     jmp s               ;無條件跳轉
35 
36 over:   pop di          ;跳轉到此處說明data段的字元已經顯示在顯示器上
37     pop si              ;調用完成,恢複到調用前狀态
38     pop cx
39     pop bx
40     ret                 ;利用棧中的資料修改IP(使用 call指令時将IP壓入棧中)
41 
42 code ends
43 end start      

   彙編、運作程式,觀察運作結果。

實驗4 彙編應用程式設計和c語言程式反彙編分析

  對源程式做如下修改:

    把line3改為:

str 1 db \'another try\', 0      

   把line12改為:

mov al, 4      

    再次彙編、運作程式,觀察運作結果。

實驗4 彙編應用程式設計和c語言程式反彙編分析

基于運作結果,了解源代碼,以及,組合使用轉移指令call和ret實作子程式的原理與方法。具體地,在line18-40中:

line19-22, line36-39,這組對稱使用的push、pop,這樣用的目的是什麼?line31的功能是什麼?

  ine19-22中使用push将寄存器的值壓入棧中,目的是儲存程式跳轉前的狀态;

  line36-39,使用pop指令對資料進行出棧操作,目的是回到程式跳轉前的狀态;

  line31:mov  es:[di] ,cx作用是将取出的data段中的字元資料以及該字元顯示的顔色資料存入顯存位址中。

     實驗代碼中用cl存儲data段中取出的資料,ch先置為0,經過jcxz指令通過後在将控制顔色的資料傳給ch;

       當cl還未取到data資料段的最後一個資料時,cx的值就不為零,在将控制顔色的資料傳給ch,然後将cx的資料存入顯存位址段中。

       當cl取到data資料段的末尾時(最後一個資料為0),在執行jcxz指令時cx為0 ,跳轉(同時說明資料取完)。

3. 實驗任務3

  使用任意文本編輯器,錄入彙編源程式task3.asm。

  子程式num2str:

         功能:把0~2559之間的任意整數轉換成數字字元串,例如,把1984轉換成\'1984\'

     入口參數

       要轉換的整數 —> ax

       數字字元串的起始位址 —> ds:di (其中:數字字元串所在段的段位址—> ds,字元串起始位址的偏移位址—>di)

     出口參數:無 1 assume cs:code, ds:data 2 data segment

1 assume cs:code, ds:data
 2 data segment
 3         x dw 1984
 4         str db 16 dup(0)
 5 data ends
 6 
 7 code segment
 8 start:  
 9         mov ax, data
10         mov ds, ax
11         mov ax, x
12         mov di, offset str
13         call num2str
14 
15         mov ah, 4ch
16         int 21h
17 
18 num2str:
19         push ax
20         push bx
21         push cx
22         push dx
23         
24         mov cx, 0
25         mov bl, 10
26 s1:      
27         div bl            ;做除法,除數8位,被除數預設ax中,結果:al商,ah餘數
28         inc cx            ;統計個數
29         mov dl, ah        ;将餘數存入dl中(整數中拆分出來的單個數字)
30         push dx            ;商壓入棧中
31         mov ah, 0        ;ah置為零
32         cmp al, 0        ;比較al是否為0
33         jne s1            ;不等于則轉移到s1(為0說明整數全部都被拆分出來了)
34 
35         mov ax,0b800h
36         mov es,ax
37         mov si,0
38         mov ah,2h
39 s2:        
40         pop dx            ;出棧,取拆分出來的數字(在bl中)
41         or dl, 30h        ;或運算,轉換數字對應的字元(0000 xxxx或0011 0000,0011 xxxx)數子字元30H~39H(0~9)
42         mov [di], dl    ;将拆分出來的數字字元送入data資料段中
43         mov es:[si],dl
44         mov es:[si+1],ah
45         add si,2h
46         inc di
47         loop s2
48         
49         pop dx
50         pop cx
51         pop bx
52         pop ax
53 
54         ret
55 code ends
56 end start      

閱讀源代碼,了解子程式num2str的彙編實作。

子任務1

  對task3.asm進行彙編、連結,得到可執行程式後,在debug中使用u指令反彙編,使用g指令執行

  到line15(程式退出之前),使用d指令檢視資料段内容,觀察是否把轉換後的數字字元串\'1984\'存放

  在資料段中str标号後面的單元。

子任務2

  對task3.asm源代碼進行修改、完善,把task2.asm中用于輸出以0結尾的字元串的子程式加進來,

  實作對轉換後的字元串進行輸出。

  預期輸入結果如下:

實驗4 彙編應用程式設計和c語言程式反彙編分析

把task3.asm源代碼中,line3中整數改成0~2559之間的任意數值,運作測試,觀察結果。

 任務1:

對task3.asm進行彙編、連結,得到可執行程式後,在debug中對程式進行調試:

1、使用u指令反彙編:

實驗4 彙編應用程式設計和c語言程式反彙編分析

2、使用g指令執行到line15(程式退出之前),使用d指令檢視資料段内容,

實驗4 彙編應用程式設計和c語言程式反彙編分析

子任務2

  對task3.asm源代碼進行修改、完善,把task2.asm中用于輸出以0結尾的字元串的子程式加進來,實作對轉換後的字元串進行輸出。

  在代碼中增加line35~38,line43~45,将拆分出來的數字顯示在視窗上,如圖:

實驗4 彙編應用程式設計和c語言程式反彙編分析

将line3中的整數改為2000,編譯連接配接後運作結果如圖:

l

實驗4 彙編應用程式設計和c語言程式反彙編分析

 将line3中的整數改為199,編譯連接配接後運作結果如圖:

實驗4 彙編應用程式設計和c語言程式反彙編分析

4. 實驗任務4

使用任意文本編輯器,錄入彙編源程式task4.asm。

1 assume cs:code, ds:data
 2 data segment
 3         str db 80 dup(?)    ;内容不确定
 4 data ends
 5 
 6 code segment
 7 start:  
 8         mov ax, data
 9         mov ds, ax
10         mov si, 0
11 
12 s1:        
13         mov ah, 1          ;int 21的1号子功能,從鍵盤輸入單個字元
14         int 21h            ;出口函數al,鍵入的字元,存放在al中
15         mov [si], al       ;将鍵入的字元存入data資料段中
16         cmp al, \'#\'        ;al與\'#\'比較
17         je next            ;等于則轉移,不是\'#\'則繼續循環輸入字元
18         inc si
19         jmp s1
20 next:
21         mov cx, si        ;鍵入的字元個數
22         mov si, 0
23 s2:     mov ah, 2        ;int 21的2号子功能,将dl寄存器中的内容在螢幕上輸出
24         mov dl, [si]    
25         int 21h
26         inc si
27         loop s2
28 
29         mov ah, 4ch
30         int 21h
31 code ends
32 end start      

彙編、連結、運作程式,輸入一個字元串并以#結束(比如,2020, bye#)觀察運作結果。

結合運作結果,了解程式功能,了解軟中斷指令。具體地:

line12-19實作的功能是?

line21-27實作的功能是?

編譯連接配接後運作結果如圖:輸入字元串為2020,bye#

實驗4 彙編應用程式設計和c語言程式反彙編分析

   輸入結束符号#後程式立即輸出出入的字元串(除#)

   line12-19實作的功能是:使用int 21h的1号子功能從鍵盤中輸入字元,儲存到data資料段中,輸入的字元以#結尾(#不存入,也不做輸出)。

   line21-27實作的功能是:使用int 21h的2号子功能将存入data資料段中的字元在螢幕上輸出。

5. 實驗任務5

   在visual studio內建環境中,編寫一個簡單的包含有函數調用的c程式。代碼如下:

1 #include<stdio.h>
 2 int sum(int, int);
 3 
 4 int main() {
 5     int a = 2, b = 7, c;
 6     c = sum(a, b);
 7     return 0;
 8 }
 9 
10 int sum(int x, int y) {
11     return (x + y);
12 }      

在line7, line13分别設定斷點,在調試模式下,檢視反彙編代碼。

分析反彙編代碼,從彙編的角度,觀察進階語言中參數傳遞和傳回值是通過什麼實作的,以及,參數入

棧順序,傳回值的帶回方式,等等。

該段c程式反彙編結果如圖:

實驗4 彙編應用程式設計和c語言程式反彙編分析

程式開始:将棧底指針ebp壓入棧中,以棧底指針作為新的棧頂指針将各寄存器的狀态壓入棧中

實驗4 彙編應用程式設計和c語言程式反彙編分析

 傳值:将值存入位址單元中。然後執行到語句調用sum函數

實驗4 彙編應用程式設計和c語言程式反彙編分析

在位址單元中取出零個參數的值,存放在eax,ecx中,同時将連個寄存器的值壓入棧中(參數副本),

  在調試中檢視入棧時的位址空間如圖:

  

實驗4 彙編應用程式設計和c語言程式反彙編分析

 call跳轉到位址00321078,如圖:

實驗4 彙編應用程式設計和c語言程式反彙編分析

 再次跳轉到003216f:調用sum函數反彙編如圖:

實驗4 彙編應用程式設計和c語言程式反彙編分析

 調用sum函數,也是先儲存寄存器狀态,再執行。執行完之後再還原寄存器狀态,傳回到main函數。

  以下兩條彙編語句:取值得記憶體單元為:115320和115324(參數副本存入得記憶體單元)

  

實驗4 彙編應用程式設計和c語言程式反彙編分析

   sum函數得結果存放在eax寄存器中。

main函數的傳回語句:

實驗4 彙編應用程式設計和c語言程式反彙編分析

程式執行結束,恢複相關寄存器的值:

實驗4 彙編應用程式設計和c語言程式反彙編分析

 退出程式。

實驗4 彙編應用程式設計和c語言程式反彙編分析