彙編偽指令assume cs:code,ds:data,ss:stack的含義
王爽的彙編教程中,下面一段彙編原始檔,大意是把0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h這8個數,透過入棧出棧的方法逆序排列回原來的記憶體位置。assumecs:code,ds:data,ss:。。。 王爽的彙編教程中,下面一段彙編原始檔,大意是把0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h這8個數,透過入棧出棧的方法逆序排列回原來的記憶體位置。
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,0,0,0,0,0,0,0,0
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,20h
mov ax,data
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop s0
mov ax,4cooh
int 21h
code ends
end start
那麼問題來了。
問題①:開頭的偽指令assume cs:code,ds:data,ss:stack作用既然不是把cs、ds、ss三個指標指向三個段,那寫它有什麼用?
問題②:ds,ss指標都透過mov ax,data mov ds,ax和mov ax,stack mov ss,ax被手動指向的正確的程式碼段。唯獨cs指標沒有標明指向,程式是如何把cs指標指向正確的程式碼段的。 展開
問題①:
你的程式中,可以用十個八個段,比如段名 D1,D2,D3,D4,D5,D6,……
8086/8088 CPU的設計,是任一時刻,只能透過4個段暫存器最多同時訪問4個段。
那麼問題來了:
某個段(比如D5段)與哪個段暫存器關聯、用哪個段暫存器訪問呢?
assume偽指令就是用來解決這個問題的。
你 assume ES:D5 以後,就將程式中的D5段與ES段暫存器綁定了,彙編程式能知道,訪問D5段中的變數,要用ES作為段暫存器。
問題②:
DOS作業系統的程式裝入功能,是這樣設計的:
裝入exe檔案時,根據exe檔案頭中的資訊,將CS:IP指向裝入後記憶體中程式的入口(第一條執行指令),也就是說,要在裝入程式時設定CS, IP兩個暫存器。
對於其它3個段暫存器,DOS裝入功能的處理,是將它們指向DOS作業系統為管理程式記憶體而建立的程式段字首PSP的段地址。
那麼問題來了:
程式執行後,要訪問程式中的某個段裡的資料,怎麼辦呢?
答案當然就是需要你自己在程式中加入將段地址傳送到段暫存器的指令啦。
最後提一下,assume是給彙編程式在彙編翻譯源程式時用的,段暫存器(CS除外)要自己設定初值是DOS作業系統的功能要求你程式這麼做的。
追問:
“assume ES:D5 以後,就將程式中的D5段與ES段暫存器綁定了”
這個“繫結”的意思是:如果用其他段暫存器比如DS:[bx]訪問D5段,程式就會報錯嗎?
追答:
舉個例子吧:
假設,在D5段中有一個變數x02,你程式中某處有一條指令 mov ax, x02
若沒有assume,彙編這條mov指令時,彙編程式會報錯。因為不知道用哪個段暫存器。
有assume,彙編結果是 mov ax, es:[(x02的偏移地址)],因為你assume告訴了彙編程式這個段用的是es這個段暫存器