1. 程式人生 > 實用技巧 >assembly language 實驗3 多個段的彙編源程式編寫與除錯

assembly language 實驗3 多個段的彙編源程式編寫與除錯

目錄


實驗內容

實驗任務1
使用任意文字編輯器,錄入彙編源程式task1.asm。

assume cs:code, ds:data
data segment
        db 'Nuist'
        db 5 dup(2)
data ends

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

        mov ax, 0b800H
        mov es, ax

        mov cx, 5
        mov si, 0
        mov di, 0f00h
s:      mov al, [si]
        and al, 0dfh
        mov es:[di], al
        mov al, [5+si]
        mov es:[di+1], al
        inc si
        add di, 2
        loop s

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

理論分析:
程式首先將Data段中的資料的小寫字母轉化為大寫字母,同時將顏色轉變為綠色然後移動資料到顯示卡記憶體上使之顯示出來。
實驗步驟:

task1.asm執行結果
task1.exe反彙編
data段資料
修改資料之後的執行結果
根據修改之後的結果推測,修改的資料是用來控制字型顏色的。 回到頂部

實驗任務2
已知資料段data中定義位元組資料如下:

data segments
      db 23,50,66,71,35
data ends

編寫程式,在螢幕上以十進位制整數形式列印輸出這5個兩位數。

編寫程式碼:

assume cs:code, ds:data
data segment
	db 23,50,66,71,35
data ends

code segment
start:
	mov ax,data
	mov ds,ax
	mov dh,0ah

	mov di,0
	mov cx,5
s:	mov al,[di]
	mov ah,00h
	div dh
	add al,30h		;數字與字元相差48,即16進位制30h
	add ah,30h
	mov bx,ax
	inc si

	mov ah,2
	mov dl,bl
	int 21h
	mov dl,bh
	int 21h
	loop s
 
	mov ah,4ch
	int 21h
code ends
end start

實驗步驟;

task2.asm執行結果
回到頂部

實驗任務3
教材「實驗5 編寫、除錯具有多個段的程式」(1)
將下面的程式編譯、連線,用Debug載入、跟蹤,然後回答問題
···
assume cs:code, ds:data, ss:stack
data segment
dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
data ends

stack segment
dw 0, 0, 0, 0, 0, 0, 0, 0
stack ends

code segment
start: mov ax,stack
mov ss, ax
mov sp,16

    mov ax, data
    mov ds, ax
    
    push ds:[0]
    push ds:[2]
    pop ds:[2]
    pop ds:[0]
    
    mov ax,4c00h
    int 21h

code ends
end start
···
回答問題:

  • CPU執行程式,程式返回前,data段中的資料為多少?
    答:data段中資料為23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09
  • CPU執行程式,程式返回前,cs=?, ss=?, ds=?
    答:cs:076C, ss:0769, ds:075A
  • 設程式載入之後, code段的段地址為X,則data段的段地址為?,stack段的段地址為?
    答:data段的段地址為X-1,stack段的段地址為X-2
實驗步驟:
debug中檢視task3.asm
反彙編檢視data段資料和stack段資料
除錯到程式返回前
回到頂部

實驗任務4
教材「實驗5 編寫、除錯具有多個段的程式」(2)
將下面的程式編譯、連線,用Debug載入,追蹤,然後回答問題。

assume cs:code, ds:data, ss:stack
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0, 0
stack ends

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
end start

回答問題:

  • CPU執行程式,程式返回前,data段中的資料為多少?
    答:data段中資料為23 01 56 04
  • CPU執行程式,程式返回前,cs=?, ss=?, ds=?
    答:cs:076C, ss:0769, ds:075A
  • 設程式載入之後, code段的段地址為X,則data段的段地址為?,stack段的段地址為?
    答:data段的段地址為X-1,stack段的段地址為X-2
  • 對於如下定義的段:
    name segment
    ...
    name ends

    如果段中資料佔N個位元組,則程式載入之後,該段實際佔有的空間為?
    答:該段實際佔有的空間為⌈N/16⌉*16位元組
實驗步驟:
debug中檢視task4.asm
反彙編檢視data段資料和stack段資料
除錯到程式返回前
回到頂部

實驗任務5
教材「實驗5 編寫、除錯具有多個段的程式」(3)
將下面的程式編譯、連線,用Debug載入,追蹤,然後回答問題。

assume cs:code, ds:data, ss:stack

code segment
start:  mov ax,stack
        mov ss, ax
        mov sp,16
        
        mov ax, data
        mov ds, ax
        
        push ds:[0]
        push ds:[2]
        pop ds:[2]
        pop ds:[0]
        
        mov ax,4c00h
        int 21h

code ends
data segment
  dw 0123h, 0456h
data ends

stack segment
  dw 0,0
stack ends
end start

回答問題:

  • CPU執行程式,程式返回前,data段中的資料為多少?
    答:data段中資料為23 01 56 04 89 07 BC 0A EF 0D ED 0F BA 0C 87 09
  • CPU執行程式,程式返回前,cs=?, ss=?, ds=?
    答:cs:076A, ss:0769, ds:075A
  • 設程式載入之後, code段的段地址為X,則data段的段地址為?,stack段的段地址為?
    答:data段的段地址為X-1,stack段的段地址為X-2
實驗步驟:
debug中檢視task5.asm
反彙編檢視data段資料和stack段資料
除錯到程式返回前
在除錯過程中,發現在程式碼中data段和stack段位置的不同會影響這兩個段的資料儲存的相對位置。如果data段和stack段在code段前面,那麼實際儲存的過程中段地址stack=code-1,data=code-2; 如果data段和stack段在code段後面,那麼實際儲存的過程中段地址stack=code+程式碼長度+1,data=code+程式碼長度+2; 回到頂部

實驗任務6
教材「實驗5 編寫、除錯具有多個段的程式」(4)
如果將(1)、(2)、(3)題中的最後一條偽指令”end start“改為”end“也就是說不知名程式的入口),則哪個程式任然可以正確執行?請說明理由。
(3)題中的程式可以正確執行,因為end start是指定程式的入口,如果刪掉start,那麼機器會將程式碼一開始作為程式的入口,但是(1)(2)中程式碼開始定義的是data段和stack段,只有(3)
將code段放在了開頭,所以能夠正確執行。

回到頂部

實驗任務7
編寫code段中的程式碼,將a段和b段中的資料依次相加,將結果存到c段。
···
assume cs:code
a segment
db 1,2,3,4,5,6,7,8
a ends

b segment
db 1,2,3,4,5,6,7,8
b ends

c1 segment ; 在整合軟體環境中,請將此處的段名稱由c→改為c1或其它名稱
db 8 dup(0)
c1 ends

code segment
start:
mov ax,a
mov ds,ax
mov bx,0
mov cx,8

s: mov ax,ds:[bx]
add ax,ds:[bx+16]
mov ds:[bx+32],ax
inc bx
loop s
mov ah,4ch
int 21h
code ends
end start
···

檢視邏輯段c中的資料
回到頂部

實驗任務8
教材「實驗5 編寫、除錯具有多個段的程式」(6)
程式如下:編寫code段中的程式碼,用push指令將a段中前8個字型資料逆序儲存到c段中。

assume cs:code
a segment
  dw 1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fh,0ffh
a ends

b segment
  dw 8 dup(0)
b ends

code segment
start: 
	mov ax,a
	mov ds,ax
	mov bx,0

	mov cx,8
s:	push ds:[bx]
	add bx,2
	loop s

	mov ax,b
	mov ds,ax
	mov bx,0

	mov cx,8
qs:	pop ds:[bx]
	add bx,2
	loop qs

	mov ah,4ch
	int 21h  
code ends
end start
檢視邏輯段c中的資料
回到頂部

實驗總結

  • 1.學習到了單個字元列印方式,利用int 21h的二號子功能,可以實現列印字元。
  • 2.每一個數據段的空間只能是16的倍數,可以通過這個計算資料空間,結合cx的值,減去mov ah,4c00h佔用的兩個位元組進行精確的反彙編。 同時每個單獨宣告的資料段佔據不同16倍數字節。
  • 3.資料段開闢的順序與在程式碼中宣告的順序有關,先宣告的在前面,後宣告的在後面。“end start”語句的作用是確定程式執行的入口,如果 省略start會導致程式入口被機器確定在開頭,而後者往往是資料段的位置,導致程式執行出錯。
  • 4.棧具有先進後出的特點,可以用來順序或者逆序儲存資料。
回到頂部