1. 程式人生 > >組合語言之實驗五

組合語言之實驗五

 

 

(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命令檢視段的值時,出現了問題,好在最後解決了。