三、操作數的尋址方式
操作數是指令或程序的主要處理對象。如果某條指令或某個程序不處理任何操作數,那么,該指令或程序不可能有數據處理功能。在CPU的指令系統中,除NOP(空操作指令)、HLT(停機指令)等少數指令之外,大量的指令在執行過程中都會涉及到操作數。所以,在指令中如何表達操作數或操作數所在位置就是正確運用匯編指令的一個重要因素。
在指令中,指定操作數或操作數存放位置的方法稱為尋址方式。操作數的各種尋址方式是用匯編語言進行程序設計的基礎,也是本課程學習的重點之一。
微機系統有七種基本的尋址方式:立即尋址方式、寄存器尋址方式、直接尋址方式、寄存器間接尋址方式、寄存器相對尋址方式、基址加變址尋址方式、相對基址加變址尋址方式等。其中,后五種尋址方式是確定內存單元有效地址的五種不同的計算方法,用它們可方便地實現對數組元素的訪問。
另外,在32位微機系統中,為了擴大對存儲單元的尋址能力,增加了一種新的尋址方式——32位地址的尋址方式。
為了表達方便,我們用符號“(X)”表示X的值,如:(AX)表示寄存器AX的值。
1、立即尋址方式
操作數作為指令的一部分而直接寫在指令中,這種操作數稱為立即數,這種尋址方式也就稱為立即數尋址方式。
立即數可以是8位、16位或32位,該數值緊跟在操作碼之后。如果立即數為16位或32位,那么,它將按“高高低低”的原則進行存儲。例如:
MOV AH, 80H ADD AX, 1234H MOV ECX, 123456H
MOV B1, 12H MOV W1, 3456H ADD D1, 32123456H
其中:B1、W1和D1分別是字節、字和雙字單元。
以上指令中的第二操作數都是立即數,在匯編語言中,規定:立即數不能作為指令中的第二操作數。該規定與高級語言中“賦值語句的左邊不能是常量”的規定相一致。
立即數尋址方式通常用於對通用寄存器或內存單元賦初值。圖3.1是指令“MOV AX, 4576H”存儲形式和執行示意圖。
2、寄存器尋址方式
指令所要的操作數已存儲在某寄存器中,或把目標操作數存入寄存器。把在指令中指出所使用寄存器(即:寄存器的助憶符)的尋址方式稱為寄存器尋址方式。
指令中可以引用的寄存器及其符號名稱如下:
1) 8位寄存器有:AH、AL、BH、BL、CH、CL、DH和DL等;
2) 16位寄存器有:AX、BX、CX、DX、SI、DI、SP、BP和段寄存器等;
3) 32位寄存器有:EAX、EBX、ECX、EDX、ESI、EDI、ESP和EBP等。
寄存器尋址方式是一種簡單快捷的尋址方式,源和目的操作數都可以是寄存器。
(1)源操作數是寄存器尋址方式
如:ADD VARD, EAX ADD VARW, AX MOV VARB, BH等。
其中:VARD、VARW和VARB是雙字,字和字節類型的內存變量。在第4章將會學到如何定義它們。
(2)目的操作數是寄存器尋址方式
如:ADD BH, 78h ADD AX, 1234h MOV EBX, 12345678H等。
(3)源和目的操作數都是寄存器尋址方式
如:MOV EAX, EBX MOV AX, BX MOV DH, BL等。
由於指令所需的操作數已存儲在寄存器中,或操作的結果存入寄存器,這樣,在指令執行過程中,會減少讀/寫存儲器單元的次數,所以,使用寄存器尋址方式的指令具有較快的執行速度。通常情況下,我們提倡在編寫匯編語言程序時,應盡可能地使用寄存器尋址方式,但也不要把它絕對化。
3、直接尋址方式
指令所要的操作數存放在內存中,在指令中直接給出該操作數的有效地址,這種尋址方式為直接尋址方式。
在通常情況下,操作數存放在數據段中,所以,其物理地址將由數據段寄存器DS和指令中給出的有效地址直接形成,但如果使用段超越前綴,那么,操作數可存放在其它段。
例3.1 假設有指令:MOV BX, [1234H],在執行時,(DS)=2000H,內存單元21234H的值為5213H。問該指令執行后,BX的值是什么?
解:根據直接尋址方式的尋址規則,把該指令的具體執行過程用圖3.2來表示。
從圖3.2中,可看出執行該指令要分三部分:
由於1234H是一個直接地址,它緊跟在指令的操作碼之后,隨取指令而被讀出;
訪問數據段的段寄存器是DS,所以,用DS的值和偏移量1234H相加,得存儲單元的物理地址:21234H;
取單元21234H的值5213H,並按“高高低低”的原則存入寄存器BX中。
所以,在執行該指令后,BX的值就為5213H。
由於數據段的段寄存器默認為DS,如果要指定訪問其它段內的數據,可在指令中用段前綴的方式顯式地書寫出來。
下面指令的目標操作數就是帶有段前綴的直接尋址方式。
MOV ES:[1000H], AX
直接尋址方式常用於處理內存單元的數據,其操作數是內存變量的值,該尋址方式可在64K字節的段內進行尋址。
注意:立即尋址方式和直接尋址方式的書寫格式的不同,直接尋址的地址要寫在括號“[”,“]”內。在程序中,直接地址通常用內存變量名來表示,如:MOV BX, VARW,其中,VARW是內存字變量。
試比較下列指令中源操作數的尋址方式(VARW是內存字變量):
MOV AX, 1234H MOV AX, [1234H] ; 前者是立即尋址,后者是直接尋址
MOV AX, VARW MOV AX, [VARW] ; 兩者是等效的,均為直接尋址
4、寄存器間接尋址方式
操作數在存儲器中,操作數的有效地址用SI、DI、BX和BP等四個寄存器之一來指定,稱這種尋址方式為寄存器間接尋址方式。該尋址方式物理地址的計算方法如下:
寄存器間接尋址方式讀取存儲單元的原理如圖3.3所示。
在不使用段超越前綴的情況下,有下列規定:
1) 若有效地址用SI、DI和BX等之一來指定,則其缺省的段寄存器為DS;
2) 若有效地址用BP來指定,則其缺省的段寄存器為SS(即:堆棧段)。
例3.2 假設有指令:MOV BX,[DI],在執行時,(DS)=1000H,(DI)=2345H,存儲單元12345H的內容是4354H。問執行指令后,BX的值是什么?
解:根據寄存器間接尋址方式的規則,在執行本例指令時,寄存器DI的值不是操作數,而是操作數的地址。該操作數的物理地址應由DS和DI的值形成,即:
PA=(DS)*16+DI=1000H*16+2345H=12345H。
所以,該指令的執行效果是:把從物理地址為12345H開始的一個字的值傳送給BX。
其執行過程如右圖3.4所示。
5、寄存器相對尋址方式
操作數在存儲器中,其有效地址是一個基址寄存器(BX、BP)或變址寄存器(SI、DI)的內容和指令中的8位/16位偏移量之和。其有效地址的計算公式如下式所示。
在不使用段超越前綴的情況下,有下列規定:
1) 若有效地址用SI、DI和BX等之一來指定,則其缺省的段寄存器為DS;
2) 若有效地址用BP來指定,則其缺省的段寄存器為SS。
指令中給出的8位/16位偏移量用補碼表示。在計算有效地址時,如果偏移量是8位,則進行符號擴展成16位。當所得的有效地址超過0FFFFH,則取其64K的模。
例3.3 假設指令:MOV BX, [SI+100H],在執行它時,(DS)=1000H,(SI)=2345H,內存單元12445H的內容為2715H,問該指令執行后,BX的值是什么?
解:根據寄存器相對尋址方式的規則,在執行本例指令時,源操作數的有效地址EA為:
EA=(SI)+100H=2345H+100H=2445H
該操作數的物理地址應由DS和EA的值形成,即:
PA=(DS)*16+EA=1000H*16+2445H=12445H
所以,該指令的執行效果是:把從物理地址為12445H開始的一個字的值傳送給BX。
其執行過程如圖3.5所示。
6、基址加變址尋址方式
操作數在存儲器中,其有效地址是一個基址寄存器(BX、BP)和一個變址寄存器(SI、DI)的內容之和。其有效地址的計算公式如下式所示。
在不使用段超越前綴的情況下,規定:如果有效地址中含有BP,則缺省的段寄存器為SS;否則,缺省的段寄存器為DS。
例3.4 假設指令:MOV BX, [BX+SI],在執行時,(DS)=1000H,(BX)=2100H,(SI)=0011H,內存單元12111H的內容為1234H。問該指令執行后,BX的值是什么?
解:根據基址加變址尋址方式的規則,在執行本例指令時,源操作數的有效地址EA為:
EA=(BX)+(SI)=2100H+0011H=2111H
該操作數的物理地址應由DS和EA的值形成,即:
PA=(DS)*16+EA=1000H*16+2111H=12111H
所以,該指令的執行效果是:把從物理地址為12111H開始的一個字的值傳送給BX。
其執行過程如右圖3.6所示。
7、相對基址加變址尋址方式
操作數在存儲器中,其有效地址是一個基址寄存器(BX、BP)的值、一個變址寄存器(SI、DI)的值和指令中的8位/16位偏移量之和。其有效地址的計算公式如下式所示。
在不使用段超越前綴的情況下,規定:如果有效地址中含有BP,則其缺省的段寄存器為SS;否則,其缺省的段寄存器為DS。
指令中給出的8位/16位偏移量用補碼表示。在計算有效地址時,如果偏移量是8位,則進行符號擴展成16位。當所得的有效地址超過0FFFFH,則取其64K的模。
例3.5 假設指令:MOV AX, [BX+SI+200H],在執行時,(DS)=1000H,(BX)=2100H,(SI)=0010H,內存單元12310H的內容為1234H。問該指令執行后,AX的值是什么?
解:根據相對基址加變址尋址方式的規則,在執行本例指令時,源操作數的有效地址EA為:
EA=(BX)+(SI)+200H=2100H+0010H+200H=2310H
該操作數的物理地址應由DS和EA的值形成,即:
PA=(DS)*16+EA=1000H*16+2310H=12310H
所以,該指令的執行效果是:把從物理地址為12310H開始的一個字的值傳送給AX。其執行過程如圖3.7所示。
從相對基址加變址這種尋址方式來看,由於它的可變因素較多,看起來就顯得復雜些,但正因為其可變因素多,它的靈活性也就很高。比如:
用D1[i]來訪問一維數組D1的第i個元素,它的尋址有一個自由度,用D2[i][j]來訪問二維數組D2的第i行、第j列的元素,其尋址有二個自由度。多一個可變的量,其尋址方式的靈活度也就相應提高了。
相對基址加變址尋址方式有多種等價的書寫方式,下面的書寫格式都是正確的,並且其尋址含義也是一致的。
MOV AX, [BX+SI+1000H] MOV AX, 1000H[BX+SI]
MOV AX, 1000H[BX][SI] MOV AX, 1000H[SI][BX]
但書寫格式BX [1000+SI]和SI[1000H+BX]等是錯誤的,即所用寄存器不能在“[“,”]”之外,該限制對寄存器相對尋址方式的書寫也同樣起作用。
相對基址加變址尋址方式是以上7種尋址方式中最復雜的一種尋址方式,它可變形為其它類型的存儲器尋址方式。表3.1列舉出該尋址方式與其它尋址方式之間的變形關系。
表3.1 相對基址加變址尋址方式與其它尋址方式之間的變形關系
源操作數 |
指令的變形 |
源操作數的尋址方式 |
只有偏移量 |
MOV AX, [100H] |
直接尋址方式 |
只有一個寄存器 |
MOV AX, [BX] 或 MOV AX, [SI] |
寄存器間接尋址方式 |
有一個寄存器和偏移量 |
MOV AX, [BX+100H] 或MOV AX, [SI+100H] |
寄存器相對尋址方式 |
有二個寄存器 |
MOV AX, [BX+SI] |
基址加變址尋址方式 |
有二個寄存器和偏移量 |
MOV AX, [BX+SI+100H] |
相對基址加變址尋址方式 |
8、32位地址的尋址方式
在32位微機系統中,除了支持前面的七種尋址方式外,又提供了一種更靈活、方便,但也更復雜的內存尋址方式,從而使內存地址的尋址范圍得到了進一步擴大。
在用16位寄存器來訪問存儲單元時,只能使用基地址寄存器(BX和BP)和變址寄存器(SI和DI)來作為地址偏移量的一部分,但在用32位寄存器尋址時,不存在上述限制,所有32位寄存器(EAX、EBX、ECX、EDX、ESI、EDI、EBP和ESP)都可以是地址偏移量的一個組成部分。
當用32位地址偏移量進行尋址時,內存地址的偏移量可分為三部分:一個32位基址寄存器,一個可乘1、2、4或8的32位變址寄存器,一個8位/32位的偏移常量,並且這三部分還可進行任意組合,省去其中之一或之二。
32位基址寄存器是:EAX、EBX、ECX、EDX、ESI、EDI、EBP和ESP;
32位變址寄存器是:EAX、EBX、ECX、EDX、ESI、EDI和EBP(除ESP之外)。
下面列舉幾個32位地址尋址指令:
MOV AX, [123456H]
MOV EAX, [EBX]
MOV EBX, [ECX*2]
MOV EBX, [EAX+100H]
MOV EDX, [EAX*4+200H]
MOV EBX, [EAX+EDX*2]
MOV EBX, [EAX+EDX*2+300H]
MOV AX, [ESP]
用32位地址偏移量進行尋址的有效地址計算公式歸納如右式所示。
由於32位尋址方式能使用所有的通用寄存器,所以,和該有效地址相組合的段寄存器也就有新的規定。具體規定如下:
(1)地址中寄存器的書寫順序決定該寄存器是基址寄存器,還是變址寄存器;
如:[EBX+EBP]中的EBX是基址寄存器,EBP是變址寄存器,而[EBP+EBX]中的EBP是基址寄存器,EBX是變址寄存器;
(2)默認段寄存器的選用取決於基址寄存器;
(3)基址寄存器是EBP或ESP時,默認的段寄存器是SS,否則,默認的段寄存器是DS;
(4)在指令中,如果使用段前綴的方式,那么,顯式段寄存器優先。
下面列舉幾個32位地址尋址指令及其內存操作數的段寄存器。
指令的舉例 |
訪問內存單元所用的段寄存器 |
MOV AX, [123456H] |
默認段寄存器DS |
MOV EAX, [EBX+EBP] |
默認段寄存器DS |
MOV EBX, [EBP+EBX] |
默認段寄存器SS |
MOV EBX, [EAX+100H] |
默認段寄存器DS |
MOV EDX, ES:[EAX*4+200H] |
顯式段寄存器ES |
MOV [ESP+EDX*2], AX |
默認段寄存器SS |
MOV EBX, GS:[EAX+EDX*2+300H] |
顯式段寄存器GS |
MOV AX, [ESP] |
默認段寄存器SS |