組合語言之實驗五
(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段中的資料 不變 。
②CPU執行程式,程式返回前,CS=076C,SS=076B,DS=076A
③設程式載入後,CODE段的段地址為X,則DATA段的段地址為 X-2 ,STACK段的段地址為 X-1 。
對程式進行編譯連線
使用r命令檢視各暫存器值,並使用u命令進行反彙編。
要求CPU執行程式,程式返回前。通過反彙編,得知應該執行到001D處
通過g命令執行程式到001D處,通過d命令檢視data段中的資料
*1 對比程式執行後data段的資料和執行前的資料,發現數據不變。
因為先執行出棧操作兩次,再執行入棧操作兩次,兩次的順序相反,正好將先出棧的資料後進棧,後出棧的資料先進棧。所以data中的資料沒有發生變化。
*2 通過執行後的結果可知cs=076C,ss=076B,ds=076A
*3 通過第二小問的結構可推斷出 DATA段的段地址為 X-2 ,STACK段的段地址為 X-1 。
(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段中的資料 不變 。
②CPU執行程式,程式返回前,CS= 076CH ,SS= 076BH ,DS= 076AH 。
③設程式載入後,CODE段的段地址為X,則DATA段的段地址為 X-2 ,STACK段的段地址為 X-1 。
④對於如下定義的段:
name segment
……
name ends
如果段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為 ((N+15)/16)*16 。
編譯連線執行,進入debug除錯,反彙編,檢視data段中資料
*1 對比程式執行後data段的資料和執行前的資料,發現數據不變。
因為先執行出棧操作兩次,再執行入棧操作兩次,兩次的順序相反,正好將先出棧的資料後進棧,後出棧的資料先進棧。所以data中的資料沒有發生變化。
*2 通過執行後的結果可知cs=076C,ss=076B,ds=076A
*3 通過第二小問的結構可推斷出 DATA段的段地址為 X-2 ,STACK段的段地址為 X-1 。
*4 N分為被16整除和不被16整除。
當N被16整除時: 佔有的空間為(N/16)*16
當N不被16整除時: 佔有的空間為(N/16+1)*16,N/16得出的是可以整除的部分,還有一個餘數,餘數肯定小於16,加上一個16。
程式載入後分配空間是以16個位元組為單位的,也就是說如果不足16個位元組的也分配16個位元組。
兩種情況總結成一個通用的公式:((N+15)/16)*16
這篇文章講這個還挺詳細的,可以參考參考 https://blog.csdn.net/friendbkf/article/details/48212887
(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段中的資料 不變 。
②CPU執行程式,程式返回前,CS= 076AH ,SS= 076EH ,DS= 076DH 。
③設程式載入後,CODE段的段地址為X,則DATA段的段地址為 X+3 ,STACK段的段地址為 X+4 。
*1 對比程式執行後data段的資料和執行前的資料,發現數據不變。
因為先執行出棧操作兩次,再執行入棧操作兩次,兩次的順序相反,正好將先出棧的資料後進棧,後出棧的資料先進棧。所以data中的資料沒有發生變化。
*2 通過執行後的結果可知cs=076A,ss=076E,ds=076D
*3 通過第二小問的結構可推斷出 DATA段的段地址為 X+3 ,STACK段的段地址為 X+4 。
(4)如果將(1)、(2)、(3)題中的最後一條偽指令“end start”改為“end”(也就是說,不指明程式的入口),則哪個程式仍然可以正確執行?請說明原因。
答:第三條程式仍然可以正確執行,如果不指明入口位置,則程式從所分配的空間開始執行,前2個是資料段,只有從第3條開始是指令程式碼。
(1)(2)題是將資料段寫在前面,但是(3)題是將資料段寫在後面,將指令程式碼寫在前面。所以,第三條程式仍然可以正確執行。
(5)程式如下,編寫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
c segment ; 在整合軟體環境中,請將此處的段名稱由c→改為c1或其它名稱
db 8 dup(0)
c ends ; 改的時候要成對一起修改
code segment
start:
;?
code ends
end start
編寫後的程式碼:
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
c segment
db 0,0,0,0,0,0,0,0
c ends
code segment
start:
mov ax,a
mov ds,ax
mov ax,b
mov es,ax
mov ax,c
mov ss,ax
mov bx,0
mov cx,8
s: mov ax,[bx]
mov ss:[bx],ax
mov ax,es:[bx]
add ss:[bx],ax
inc bx
loop s
mov ax,4c00h
int 21h
code ends
end start
反彙編可知先執行到哪裡,
執行復制前,檢視a,b,c段的值
執行所有的程式碼後檢視c段的值
(6)程式如下,編寫code段中程式碼,用PUSH指令將A段中的前8個字型資料,逆序儲存到B段中。
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:
;?
code ends
end start
編寫原始碼:
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 0,0,0,0,0,0,0,0
b ends
code segment
start:
mov ax,a
mov ds,ax
mov ax,b
mov ss,ax
mov sp,10h
mov bx,0
mov cx,8
s:
push ds:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
通過u得知執行位置,檢視b段的值;
全部執行後,再檢視b段的值
發現 b 的 8 個字單元為 a 段前 8 個位元組的逆序
總結:這次實驗做的不順利,尤其是第5,6個實驗,使用d命令檢視段的值時,出現了問題,好在最後解決了。