實驗二 多個邏輯段的匯編源程序編寫與調試
實驗任務一
任務1-1
題干
對程序task1_1.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。
點擊查看task1_1.asm
assume ds:data, cs:code, ss:stack
data segment
db 16 dup(0) ; 預留16個字節單元,初始值均為0
data ends
stack segment
db 16 dup(0) ;預留16個字節單元,初始值均為0
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 16 ; 設置棧頂
mov ah, 4ch
int 21h
code ends
end start
問題
- 在debug中將執行到line17結束、line19之前,記錄此時:寄存器(DS) = ___ , 寄存器(SS) = ___ , 寄存器(CS) = ___
- 假設程序加載后,code段的段地址是X,則,data段的段地址是____, stack的段地址是____。
答案
問題①
- 寄存器(DS)= 076A;寄存器(SS)= 076B;寄存器(CS)= 076C
問題②
- X-2;X-1
任務1-2
題干
對程序task1_2.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。
點擊查看task1_2.asm
assume ds:data, cs:code, ss:stack
data segment
db 4 dup(0) ; 預留4個字節單元,初始值均為0
data ends
stack segment
db 8 dup(0) ; 預留8個字節單元,初始值均為0
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 8 ; 設置棧頂
mov ah, 4ch
int 21h
code ends
end start
問題
- 在debug中將執行到line17結束、line19之前,記錄此時:寄存器(DS) = ___ , 寄存器(SS) = ___ , 寄存器(CS) = ___
- 假設程序加載后,code段的段地址是X,則,data段的段地址是____, stack的段地址是____。
答案
問題①
- 寄存器(DS)= 076A;寄存器(SS)= 076B;寄存器(CS)= 076C
問題②
- X-2;X-1
任務1-3
題干
對程序task1_3.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。
點擊查看task1_3.asm
assume ds:data, cs:code, ss:stack
data segment
db 20 dup(0) ; 預留20個字節單元,初始值均為0
data ends
stack segment
db 20 dup(0) ; 預留20個字節單元,初始值均為0
stack ends
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 20 ; 設置初始棧頂
mov ah, 4ch
int 21h
code ends
end start
問題
- 在debug中將執行到line17結束、line19之前,記錄此時:寄存器(DS) = ___ , 寄存器(SS) =___ , 寄存器(CS) = ___
- 假設程序加載后,code段的段地址是X,則,data段的段地址是____, stack的段地址是____。
答案
問題①
- 寄存器(DS)= 076A;寄存器(SS)= 076C;寄存器(CS)= 076E
問題②
- X-4;X-2
任務1-4
題干
對程序task1_4.asm進行匯編、連接,用debug加載、跟蹤調試,基於結果,回答問題。
點擊查看task1_4.asm
assume ds:data, cs:code, ss:stack
code segment
start:
mov ax, data
mov ds, ax
mov ax, stack
mov ss, ax
mov sp, 20
mov ah, 4ch
int 21h
code ends
data segment
db 20 dup(0)
data ends
stack segment
db 20 dup(0)
stack ends
end start
問題
- 在debug中將執行到line9結束、line11之前,記錄此時:寄存器(DS) = ___ , 寄存器(SS) = ___ , 寄存器(CS) = ___
- 假設程序加載后,code段的段地址是X,則,data段的段地址是____, stack的段地址是____。
答案
問題①
- 寄存器(DS)= 076C;寄存器(SS)= 076E;寄存器(CS)= 076A
問題②
- X+2;X+4
任務1-5
基於上述四個實驗任務的實踐、觀察,總結並回答:
- 對於如下定義的段,程序加載后,實際分配給該段的內存空間大小是 ____。
x86asm xxx segment db N dup(0) xxx ends
- 果將程序task1_1.asm, task1_2.asm, task1_3.asm, task1_4.asm中,偽指令
end start
改成end
, 哪一個程序仍然可以正確執行?結合實踐觀察得到的結論,分析、說明原因。
分析與答案
問題①
- [N/16向上取整]*16 Bytes
問題②
- 經過測試,最終只有task1_4.asm可以正常運行。這是因為在前三個任務中,由於end沒有定義程序入口點,所以系統將db指令定義的數據當做指令運行,導致CS與IP寄存器出現錯誤最終導致程序運行結果不符。若使用DEBUG工具手動定義IP寄存器,則可以正確運行這些軟件。
實驗任務二
題干
編寫一個匯編源程序,實現向內存單元b800:0f00 ~ b800:0f9f連續160字節,依次重復填充十六進制數據03 04。
解答
使用debug工具的f填充命令-f b800:0f00 0f9f 03 04
可以看到運行效果:
下面編寫相應的程序代碼:
assume cs:code
code segment
start:
mov ax, 0b800h
mov ds, ax
mov bx, 0f00h;第一次寫入點定位在b800:0f00
mov cx, 50h;80字*2=160字節
mov ax, 0403h;按字寫入,先寫入低位然后寫入高位
s: mov ds:[bx], ax
add bx, 2;調整bx寫入下一個字
loop s
mov ah, 4ch;結束程序
int 21h
code ends
end start
編譯連接運行程序:
成功運行。
注意
- 無法直接將立即數寫入數據段寄存器ds
- loop語句的循環次數由cx決定
實驗任務三
題干
已知8086匯編源程序task3.asm代碼片段如下。
點擊查看task3.asm
assume cs:code
data1 segment
db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends
data2 segment
db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers
data2 ends
data3 segment
db 16 dup(0)
data3 ends
code segment
start:
; ×××
mov ah, 4ch
int 21h
code ends
end start
要求
- 編程實現把邏輯段data1和邏輯段data2的數據依次相加,結果保存到邏輯段data3中。
- 在debug中加載、反匯編、調試。在數據項依次相加前,和相加后,分別查看三個邏輯段data1,data2, data3對應的內存空間,確認逐一相加后,結果的確保存在了邏輯段data3中。
解答
要求1
assume cs:code
data1 segment
db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends
data2 segment
db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0 ; ten numbers
data2 ends
data3 segment
db 16 dup(0)
data3 ends
code segment
start:
mov cx,0ah;十個數字,正好是0a
mov si,0
mov ax,data3
mov ds,ax
s: mov bx,data1
mov es,bx
mov al,es:[si];把data1的當前數據轉移到ax低位
mov bx,data2
mov es,bx
add al,es:[si];將棧頂的data2數據與data1相加
mov [si],al
inc si
loop s
mov ah, 4ch
int 21h
code ends
end start
要求2
已知三個數據段地址相連,且均占用16字節,故使用-d 076a:0 2f
得到三行數據正好分別為data1,2,3。
執行程序后再次查看:
可見已經成功相加並保存在data3。
實驗任務四
題干
已知8086匯編源程序task4.asm代碼片段如下。
點擊查看task4.asm
assume cs:code
data1 segment
dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends
data2 segment
dw 8 dup(?)
data2 ends
code segment
start:
; ×××
mov ah, 4ch
int 21h
code ends
end start
要求
- 補全程序,實現把邏輯段data1中的8個字數據逆序存儲到邏輯段b中。
- 匯編、連接后,在debug中加載程序,運行到line15程序退出前,使用d命令查看數據段data2對應的
內存空間,確認是否實現題目要求。
解答
要求1
assume cs:code
data1 segment
dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends
data2 segment
dw 8 dup(?)
data2 ends
code segment
start:
mov cx,08h
mov si,0
mov ax,data1
mov ds,ax
mov ax,data2
mov ss,ax;利用棧的特性實現逆序
mov sp,010h
s: mov ax,[si]
push ax
add si,2
loop s
mov ah,4ch
int 21h
code ends
end start
要求2
執行后查看空間:
可見實現了逆序復制。
實驗任務五
題干
使用任意文本編輯器,錄入匯編源程序task5.asm。
點擊查看task5.asm
assume cs:code, ds:data
data segment
db 'Nuist'
db 2, 3, 4, 5, 6
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
題目
閱讀源程序,從理論上分析源代碼的功能,尤其是line15-25,循環實現的功能是什么,逐行理解每條指令的功能。
- 對程序進行匯編、鏈接,得到可執行文件,運行並觀察結果。
- 使用debug工具對程序進行調試,執行到程序返回前,即line25執行之后、line27執行之前,觀察結果。
- 源代碼中line19的作用是?
- 修改line4里5個字節單元的值,重新匯編、鏈接、運行,觀察結果。
db 2,3,4,5,6 --> 改成: db 5 dup(2) 或 db 5 dup(5)
基於觀察,分析、猜測這里的數值作用是什么。
解答與分析
- 編譯運行。
獲得了不同彩色的NUIST字母。 - 調試運行。
首先使用u命令找到程序結尾076b:0027
,然后用-g 076b:0027
命令直接執行,獲得了與直接運行相同的結果。 - line19代碼
and al, 0dfh
的作用:
通過按位相與的方法將小寫字母轉為大寫。 - 修改line4后編譯運行,獲得全綠色的NUIST:
可見line4的作用為定義字母的顏色。
實驗任務六
題干
已知8086匯編源程序task6.asm代碼片段如下。
點擊查看task6.asm
assume cs:code, ds:data
data segment
db 'Pink Floyd '
db 'JOAN Baez '
db 'NEIL Young '
db 'Joan Lennon '
data ends
code segment
start:
; ×××
mov ah, 4ch
int 21h
code ends
end start
要求
- 補全程序,將data段中的每行第一個單詞從大寫->小寫。
- 在debug中加載程序,反匯編,執行到line13退出前,用d命令查看data段對應的內存空間,確認每行第一個單詞已經由大寫->小寫。
解答
要求1
assume cs:code, ds:data
data segment
db 'Pink Floyd '
db 'JOAN Baez '
db 'NEIL Young '
db 'Joan Lennon '
data ends
code segment
start:
mov ax,data
mov ds,ax
mov bx,0
mov cx,4
s: mov al,[bx]
or al,20H
mov [bx],al
add bx,16
loop s
mov ah, 4ch
int 21h
code ends
end start
要求2
執行后查看空間:
成功轉換。
實驗任務六
題干
問題場景描述:
Power idea公司1975年-1979年的基本情況如下:
程序task7.asm的邏輯段data中(line4-6),已經定義好了這些數據。
點擊查看task7.asm
assume cs:code, ds:data, es:table
data segment
db '1975', '1976', '1977', '1978', '1979'
dw 16, 22, 382, 1356, 2390
dw 3, 7, 9, 13, 28
data ends
table segment
db 5 dup( 16 dup(' ') ) ;
table ends
code segment
start:
mov ah, 4ch
int 21h
code ends
end start
要求
- 補全程序,實現題目要求,把年份、收入、雇員人數、人均收入,以結構化方式寫入table段中。
表格中,每行數據,在邏輯段table中占16個字節,各項數據占據字節大小分配如下。其中,數據之間用空格間隔。
- 匯編、連接后,在debug中加載、調試程序。靈活、合理使用u命令、g命令、d命令,顯示剛開始邏輯段table的數據信息,以及,結構化存入數據后,數據段table的數據信息,確認實現題目要求。
解答
要求1
assume cs:code, ds:data, es:table
data segment
db '1975', '1976', '1977', '1978', '1979'
dw 16, 22, 382, 1356, 2390
dw 3, 7, 9, 13, 28
data ends
table segment
db 5 dup( 16 dup(' ') )
table ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov cx,5
mov bx,0
mov si,0
s1:
mov ax,[si]
mov es:[bx],ax
mov ax,[si+2]
mov es:[bx+2],ax
add bx,16
add si,4
loop s1
mov cx,5
mov bx,5
mov si,20
s2:
mov ax,[si]
mov es:[bx],ax
mov ax,0h
mov es:[bx+2],ax
add bx,16
add si,2
loop s2
mov cx,5
mov bx,10
mov si,30
s3:
mov ax,[si]
mov es:[bx],ax
add bx,16
add si,2
loop s3
mov cx,5
mov si,5
s4:
mov ax,es:[si]
mov ax,es:[si+2]
mov ax,es:[si+5]
div bx
mov es:[si+8],ax
add si,16
loop s4
mov ah, 4ch
int 21h
code ends
end start
要求2
- 編譯調試運行。
查看TABLE段原始信息:
- 使用g命令運行到結尾。
- 再次查看TABLE段,可見已經序列化地存放了信息。
實驗總結
疑難點
實驗七中若是從源變址寄存器(SI)中取值,則默認段寄存器為寄存器DS,若使用ES寄存器則必須指明。
問題
實驗五中調試運行時,若使用p命令單步調試,最后會只顯示UIST四個字母。未查明原因。