1. 程式人生 > 其它 >activty在哪個棧裡面_將資料、程式碼、棧放入不同的段

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所示:

b384c102c78162e743d40291b511292c.png
圖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 

0e73c4950defdb2f1feb618a85eb0bc2.png
圖1 檢視內容
我們應該檢視 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