1. 程式人生 > 實用技巧 >第02組 每週小結 (2/3)

第02組 每週小結 (2/3)

一、實驗目的

1. 理解80×25彩色字元模式顯示原理

2. 理解轉移指令jmp, loop, jcxz的跳轉原理,掌握使用其實現分支和迴圈的用法

3. 理解轉移指令call, ret, retf的跳轉原理,掌握組合使用call和ret/retf編寫彙編子程式的方法,掌握 引數傳遞方式

4. 理解標誌暫存器的作用

5. 理解條件轉移指令je, jz, ja, jb, jg, jl等的跳轉原理,掌握組合使用匯編指令cmp和條件轉移指令實 現分支和迴圈的用法

6. 瞭解在visual studio/Xcode等環境或利用gcc命令列引數反彙編c語言程式的方法,理解編譯器生成 的反彙編程式碼

7. 綜合應用定址方式和彙編指令完成應用程式設計


二、實驗內容

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

程式碼實現:

assume cs:codesg, ds:datasg, ss:stacksg
  
datasg segment
        db 'welcome to masm!'
        db 2h,24h,71h                
datasg ends


stacksg segment stack
        db 16 dup (0)
stacksg ends

codesg segment

start:
        mov ax,datasg
        mov ds,ax

        mov ax,stacksg
        mov ss,ax
        mov sp,
16 mov ax,0B872h mov es,ax mov cx,3 mov bx,0 s: push cx mov cx,16 mov si,0 mov di,0 s0: mov al,ds:[di] mov ah,ds:[bx+16] mov es:[si],ax add si,
2 inc di loop s0 pop cx mov ax,es add ax,00ah mov es,ax inc bx loop s mov ax,4c00h int 21h codesg ends end start

結果顯示:

程式碼簡析:首先借助PPT可知,8086下視訊記憶體空間的大小為25*80個字,開始地址為b800H,想要顯示在螢幕中間,偏移地址所佔的行數應該從第11行開始,查表可得對應的十

進位制偏移地址為1760,又因為視訊記憶體單元高位位元組控制顏色,低位位元組控制內容,所以“welcome to masm!”和其對應的顏色欄位共佔16個字,從而開始地址應該為第11行往後,

(80-16)/2=36,第36列。所以,最終的偏移地址:1760+36*2=1832;轉為十六進位制:0720H。由於要顯示三行且顏色不同,因此採用雙層迴圈實現,利用棧空間來使暫存器CX的值

依據迴圈層次的不同變化,除此之外,其基本實現原理與實驗三中類似。

2.編寫子程式printStr,實現以指定顏色在螢幕上輸出字串。呼叫它,完成字串輸出。

程式碼實現:

assume cs:code, ds:data
data segment
    str db 'try', 0
data ends

code segment
start:  
	mov ax, data
	mov ds, ax

	mov si, offset str
	mov al, 2
	call printStr

	mov ah, 4ch
	int 21h

printStr:
	push bx
	push cx
	push si
	push di

	mov bx, 0b800H
	mov es, bx
	mov di, 0
s:      mov cl, [si]
	mov ch, 0
	jcxz over
	mov ch, al
	mov es:[di], cx
	inc si
	add di, 2
	jmp s

over:   pop di
	pop si
	pop cx
	pop bx
	ret

code ends
end start

結果顯示:

對源程式做如下修改,將line3改為str db 'another try', 0將line12改為mov al, 4,再次彙編,觀察執行結果。

  • line19-22, line36-39,這組對稱使用的push、pop,這樣用的目的是什麼?
  • 答:line19-22中將可能用到的暫存器bx,cx,si,di壓棧,以防止在子程式執行過程中改變了某些重要資料。line36-39將它們出棧,恢復進入子程式前的環境。
  • line30的功能是什麼?
  • 答:將字元以及對應的顏色資訊儲存到

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

程式碼如下:

assume cs:code, ds:data
data segment
        x dw 1984
        str db 16 dup(0)
data ends

code segment
start:  
        mov ax, data
        mov ds, ax
        mov ax, x
        mov di, offset str
        call num2str

        mov ah, 4ch
        int 21h

num2str:
        push ax
        push bx
        push cx
        push dx
        
        mov cx, 0
        mov bl, 10
s1:      
        div bl
        inc cx
        mov dl, ah
        push dx
        mov ah, 0
        cmp al, 0
        jne s1
s2:        
        pop dx
        or dl, 30h
        mov [di], dl
        inc di
        loop s2
        
        pop dx
        pop cx
        pop bx
        pop ax

        ret
code ends
end start

子任務1:task3.asm進行彙編、連結,得到可執行程式後,在debug中使用u命令反彙編,使用g命令執行 到line15(程式退出之前),使用d命令檢視資料段內容,觀察是否把轉

換後的數字字串'1984'存放 在資料段中str標號後面的單元。

觀察可得:1984被轉為了字元,存放在076a:2-076a:f中,對應的ASCLL碼分別是31,39,38,34。

子任務2:對task3.asm原始碼進行修改、完善,把task2.asm中用於輸出以0結尾的字串的子程式加進來, 實現對轉換後的字串進行輸出。

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

assume cs:code, ds:data
data segment
        str db 80 dup(?)
data ends

code segment
start:  
        mov ax, data
        mov ds, ax
        mov si, 0

s1:        
        mov ah, 1
        int 21h
        mov [si], al
        cmp al, '#'
        je next
        inc si
        jmp s1
next:
        mov cx, si
        mov si, 0
s2:     mov ah, 2
        mov dl, [si]
        int 21h
        inc si
        loop s2

        mov ah, 4ch
        int 21h
code ends
end start

執行截圖:

  • line12-19實現的功能是?
  • 答:迴圈讀入從鍵盤輸入的字元,遇到‘#’停止,最大長度不得超過80。
  • line21-27實現的功能是?
  • 答:把si的值賦給cx,表明迴圈次數,然後把讀入的字元再重新輸出在螢幕上。

5.在visual studio整合環境中,編寫一個簡單的包含有函式呼叫的c程式。程式碼如下:

#include <stdio.h>
int sum(int, int);
int main() {
int a = 2, b = 7, c;
c = sum(a, b);
return 0;
}
int sum(int x, int y) {
return (x + y);
}

總結對這個簡單的c程式碼反彙編後,你對反彙編出來的彙編指令分析的內容總結。

通過觀察反彙編程式碼,引數的入棧順序是先定義的後入棧,在呼叫sum函式之前,將a,b的值分別儲存到eax和ecx中,併入棧儲存現場,然後通過call命令轉到sum子程式執行,

引數的傳遞和返回值都是藉助暫存器實現的,sub esp,0c0h 是為了生成一段新的棧空間,lea edi,[ebp-0c0h]是將esp的地址存放在edi中,在執行完畢後,會將之前儲存的暫存器

的狀態出棧,恢復現場,執行ret操作回到主程式。