activty在哪個棧裡面_將資料、程式碼、棧放入不同的段
技術標籤:activty在哪個棧裡面
1.前言
前面,我們是將資料、程式碼、棧放入同一個段中,但這樣會出現兩個問題:
① 把它們放到一個段中使程式顯得混亂;
② 前面程式中處理的資料比較少,用到的棧空間也小,加上沒有多長的程式碼,放到一個段裡面沒有問題. 但如果資料、棧和程式碼需要的空間超過64KB,就不能放在一個段中(一個段的容量大於64KB,是我們在學習中所用的8086模式的限制,並不是所有的處理器都這樣).
所以,應該考慮用多個段來存放資料、程式碼、棧.
2. 資料、程式碼、棧在不同的段中
下面是程式1的作用,是將資料段中的資料進行逆序存放.
程式1:
assume cs:code data segment dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H ; 0H ~ fH data ends stack segment dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 0H ~ 1fH stack ends code segment start: mov ax, data mov ds, ax mov ax, stack mov ss, ax mov sp, 20H mov bx, 0 mov cx, 8 s0: push [bx] add bx, 2 loop s0 mov bx, 0 mov cx, 8 s1: pop [bx] add bx, 2 loop s1 mov ax, 4c00H int 21H code ends end start
3.實驗
實驗1:
assume cs:code data segment dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H ; 0H ~ fH data ends stack segment dw 0, 0, 0, 0, 0, 0, 0, 0 ; 0H ~ fH stack ends code segment start: mov ax, stack mov ss, ax mov sp, 10H 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段中的資料為多少?
0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H
② CPU 執行程式,程式返回前,cs = 076CH,ss = 076BH,ds = 076AH . (注意,這裡的值,不是唯一的,但段暫存器之間相差的數值是確定的)
③ 設程式載入後,code段的段地址為X,
則data段的段地址為 X - 2, stack段的段地址為 X - 1 .
分析:cs - ds = 076CH - 076AH = 2
cs - ss = 076A - 076BH = 1
注:段地址數值相差1,實體地址就相差16,相當於16個個位元組.
對於第③問,個人覺得題目表達的不夠準確,上面對第三問的解答是針對CPU執行程式,程式返回前,cs,ss,ds的段地址相差的數值,而非程式載入後(程式還沒有執行,只是載入進了記憶體),cs,ss,ds的值,程式載入進記憶體後,各暫存器的值,應該如圖1所示:
載入完程式:ds = 075AH,ss = 0769H,cs = 076CH
這裡需要額外強調一下,程式載入進記憶體後,ds = 075AH,那麼按理來說,cs = 076AH才對(cs = ds + 10H),但這裡為什麼:CS = 076CH ?
其實,通過執行程式,我們才知道,在程式載入進記憶體後,其實系統已經為data段和stack段分配了儲存空間,其中data段的段地址為076AH,stack段的段地址為076BH,如果我們沒有進行定義程式的入口(通過標號start 來標記),那麼 cs = 076AH(如果沒有start進行標記程式的入口,計算機會把接觸到第一個的資料,認為是程式的入口,對於計算機來說,其實根本沒有所謂的程式與資料之分,程式與資料只是我們人為定義而已,計算機只認識01).
實驗2:
assume cs:code
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, 10H
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段中的資料為多少?
0123H, 0456H, 0,0,0,0,0,0
② CPU 執行程式,程式返回前,cs = 076CH,ss = 076BH,ds = 076AH .
③ 設程式載入後,code段的段地址為X,
則data段的段地址為 X - 2, stack段的段地址為 X - 1 .
分析:cs - ds = 076CH - 076AH = 2
cs - ss = 076A - 076BH = 1
④ 對於如下定義的段:
name segment
...
name ends
如果段中的資料佔N個位元組,則程式載入後,該段實際佔有的空間為: (N/16 + 1) * 16
注:N/16:取整
實驗3:
assume cs:code
code segment
start: mov ax, stack
mov ss, ax
mov sp, 10H
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 0EFH, 0EFH
stack ends
end start
通過上面的程式,回答下面的問題:
① CPU執行程式,程式返回前,data段中的資料為多少?
0123H, 0456H, 0,0,0,0,0,0
② CPU 執行程式,程式返回前,cs = 076AH,ss = 076EH,ds = 076DH .
③ 設程式載入後,code段的段地址為X,
則data段的段地址為 X + 3, stack段的段地址為 X + 4 .
實驗4:
如果將(1)、(2)、(3)題中的最後一條偽指令"end start"改為"end"(也就是說不說明程式的入口),則哪個程式仍然可以正確執行?為什麼?
解:實驗中(3)的程式可以正確執行,如果程式的位置發生了變化,並且將程式入口標識start去掉,程式就會從上往下執行.
實驗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
db 0, 0, 0, 0, 0, 0, 0, 0
c ends
code segment
?
code ends
end start
code程式碼1:
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 sp, 8
mov bx, 6
mov cx, 4
s0: mov ax, [bx]
add ax, es:[bx]
push ax
sub bx, 2
loop s0
mov ax, 4c00H
int 21H
code ends
end start
上面的程式,迴圈中進行的是字的傳送,並且把c資料段當作棧來使用,能否不使用棧呢?
code程式碼2:
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, c
mov es, ax
mov bx, 0
mov cx, 8
s0: mov ax, a
mov ds, ax
mov dx, 0
mov dl, [bx]
mov ax, b
mov ds, ax
add dl, [bx]
mov es:[bx], dl
inc bx
loop s0
mov ax, 4c00H
int 21H
code ends
end start
我們應該檢視 076a:0的內容,
最後一次迴圈:
mov ax, b
mov ds, ax
使得:ds = 076BH
a段的段地址為076aH,b段的段地址為076bH,c段的段地址為076cH,程式段code段的段地址為076dH .
實驗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 0, 0, 0, 0, 0, 0, 0, 0
b ends
code segment
?
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, 16
mov bx, 0
mov cx, 8
s0: push [bx]
add bx, 2
loop s0
mov ax, 4c00H
int 21H
code ends
end start