3.2 尋址方式
計算機在運行過程中需要的數(shù)據(jù)稱為操作數(shù),尋找指令中所需要的操作數(shù)或操作數(shù)地址的方式稱為尋址方式。80486微處理器指令系統(tǒng)的尋址方式包括三種類型:操作數(shù)尋址、轉(zhuǎn)移地址尋址及I/O端口尋址。
3.2.1 關(guān)于操作數(shù)的尋址方式
指令中所需要的操作數(shù)來自以下幾個方面。
① 操作數(shù)包含在指令中。在取指令的同時,操作數(shù)也隨著取出,這種操作數(shù)被稱為立即數(shù)。
② 操作數(shù)包含在CPU的某個內(nèi)部寄存器中。由于寄存器在CPU的內(nèi)部,因此取操作數(shù)也比較簡單。
③ 操作數(shù)在內(nèi)存儲器中。由于內(nèi)存儲器在CPU的外部,因此,在尋找這種操作數(shù)時需要執(zhí)行一個總線周期。首先找到該操作數(shù)在內(nèi)存中存放的地址,再從該地址中取出操作數(shù)。
在80486微機系統(tǒng)中,任何內(nèi)存單元的地址都由段基址和偏移地址(又稱偏移量)組成。其中,段基址由段寄存器提供,而偏移地址則由以下4個部分組合而成。
① 基址寄存器
② 間址寄存器(或稱變址寄存器)
③ 比例因子
④ 位移量
以上4個部分稱為偏移地址四元素。一般將這4個元素按某種計算方法組合形成的偏移地址稱為有效地址EA。有效地址的組合方式和計算方法如下:
EA=基址+(間址×比例因子)+位移量
采用16位尋址時,位移量是8位或16位,用BX和BP作為基址寄存器,SI和DI作為間址寄存器,比例因子為1。
采用32位尋址時,可使用8位和32位的位移量,32位通用寄存器都可以作為基址寄存器或間址寄存器(ESP不用于間址),并且可采用2、4或8三種不同的比例因子。
以上4個因素可優(yōu)化組合出9種存儲器尋址方式,加上立即尋址和寄存器尋址,共有11種尋址方式。
以匯編語言中的MOV傳送指令為例,其指令格式為:
MOV 目標操作數(shù),源操作數(shù);將源操作數(shù)傳送到目標操作數(shù)
1.立即數(shù)尋址(immediate addressing)
立即數(shù)尋址的特點:操作數(shù)就在指令中,跟在操作碼后面,稱為立即數(shù)。在指令格式中,立即數(shù)一般為源操作數(shù)。
注意:在匯編語言中,立即數(shù)是以常數(shù)形式出現(xiàn)的。常數(shù)可以是二進制數(shù)(后綴字母B或b)、十進制數(shù)(不用后綴字母,或用D或d)、十六進制數(shù)(后綴字母H或h,以A~F開頭時,前面要加一個0)、字符串(用單引號括起來的字符,表示對應(yīng)的ASCII碼值)。
例如:MOV AL,0FH;將8位立即數(shù)0FH傳送到AL寄存器中
MOV AX,0102H;將16位立即數(shù)0102H傳送到AX寄存器中
這兩條指令的指令碼在內(nèi)存中的存放格式及指令執(zhí)行過程如圖3.1所示。
注意:立即數(shù)尋址時,只允許源操作數(shù)為立即數(shù),而目標操作數(shù)必須是寄存器或存儲器操作數(shù),其作用是給寄存器或存儲單元賦值。
2.寄存器尋址(register addressing)
寄存器尋址的特點:指令中所需的操作數(shù)在CPU的某個寄存器中,由于存取此類操作數(shù)是在CPU內(nèi)部進行的,因此執(zhí)行速度較快。
例如:MOV AX,CX;將CX中的內(nèi)容傳送到AX中
該指令的尋址及執(zhí)行過程如圖3.2所示。
3.直接尋址(direct addressing)
直接尋址的特點:操作數(shù)一般存放在存儲器的數(shù)據(jù)段中,而操作數(shù)的有效地址EA由指令給出。
物理地址=(DS)×16+EA
例如:MOV AX,[2000H];將EA=2000H字單元中的內(nèi)容傳送到AX寄存器中
在匯編語言中,帶方括號“[ ]”的操作數(shù)稱為存儲器操作數(shù),括號中的內(nèi)容作為存儲單元的有效地址EA。存儲器操作數(shù)本身并不能表明地址的類型,而需要通過另一個寄存器操作數(shù)的類型或別的方式來確定。上例中由于目標操作數(shù)AX為字類型,源操作數(shù)也應(yīng)與之對應(yīng),因此有效地址EA=2000H為字單元。設(shè)DS=3000H,該指令的尋址及執(zhí)行過程如圖3.3所示。
物理地址=3000H×16+2000H=32000H
該指令的功能是將存儲器32000H和32001H兩個存儲單元的內(nèi)容,按照高位字節(jié)對應(yīng)高地址,低位字節(jié)對應(yīng)低地址的原則,送到AX寄存器中。
直接尋址允許用符號地址來代替數(shù)值地址,例如:MOV AX,[DATA],變量DATA為存放操作數(shù)的存儲單元的符號地址,還可寫成MOV AX,DATA。直接尋址適用于處理單個變量。
4.寄存器間接尋址(register indirect addressing)
寄存器間接尋址的特點:操作數(shù)在存儲器中,其有效地址EA存放在某個寄存器中。
注意:寄存器的使用在16位尋址和32位尋址時不一樣。
(1)16位尋址
有效地址存放在SI、DI、BX、BP中。
如果指令中指定的寄存器是BX、SI、DI,則操作數(shù)在數(shù)據(jù)段中,段基址在DS中,操作數(shù)的物理地址為:
如果指令中指定的寄存器是BP,則操作數(shù)在堆棧中,段基址在SS中,操作數(shù)的物理地址為:
物理地址=(SS)×16+(BP)
例如:MOV AX,[BP]
設(shè)SS=3000H,BP=1000H該指令尋址及執(zhí)行過程如圖3.4所示。
(2)32位尋址
8個32位通用寄存器均可作為寄存器間接尋址使用。除ESP和EBP默認段寄存器為SS外,其余6個通用寄存器均默認段寄存器為DS。
寄存器間接尋址方式用于表格處理,執(zhí)行完一條指令后,只需要修改寄存器內(nèi)容就可取出表格中的下一項。
5.基址尋址(based relative)
基址尋址的特點:操作數(shù)在存儲單元中,操作數(shù)的有效地址EA由基址寄存器的內(nèi)容和指令中給出的位移量之和算出。
(1)16位尋址
BX和BP作為基址寄存器,其中BX以DS作為默認段寄存器,BP以SS作為默認段寄存器。位移量可以是8位或16位。
EA=(BX或BP)+位移量(8或16位)
(2)32位尋址
8個32位通用寄存器均可作為基址寄存器,其中ESP、EBP以SS作為默認段寄存器,其余均以DS作為默認段寄存器。位移量為8位或32位。
EA=(基址寄存器)+位移量(8位或32位)
6.間址尋址(indexed relative)
在間址尋址中,有效地址的計算公式如下:
EA=(間址寄存器)+位移量(8位或32位)
(1)16位尋址
只有SI和DI可作為間址寄存器,默認DS為段基址寄存器。
(2)32位尋址
除ESP以外的其他7個32位的寄存器均可作為間址寄存器,EBP默認SS作為段基址寄存器,其余以DS作為段基址寄存器。
基址尋址和間址尋址適用于對一維數(shù)組的數(shù)組元素進行檢索操作。通常,用位移量表示數(shù)組起始地址的偏移量,基址/間址寄存器表示數(shù)組元素的下標,可通過修改下標來獲取數(shù)組元素的值。
7.比例間接尋址(proportion indirect addressing)
在比例間接尋址中,有效地址的計算公式如下:
EA=(間址寄存器)×比例因子(2,4或8)+位移量(8位或32位)
比例間接尋址方式只適用于32位尋址。
例如:MOV EAX,TABLE [ESI×4]
其中,TABLE為位移量,4是比例因子,ESI乘以4的操作在CPU內(nèi)部完成。
8.基址加間址尋址(based indexed addressing)
基址加間址尋址方式也包括16位尋址和32位尋址,有效地址的計算公式如下:
EA=(基址寄存器)+(間址寄存器)
例如:MOV AX,[BX+SI]
MOV DX,[BX+DI]
如果DS=1000H,BX=2000H,DI=0010H,則
物理地址=DS×16+BX+DI
=10000H+2000H+0010H
=12010H
其尋址及執(zhí)行過程如圖3.5所示。
注意:當基址寄存器和間址寄存器默認的段寄存器不同時,一般以基址寄存器決定的段寄存器作為段基址寄存器。
例如:MOV EAX,[EBP][ECX]
由于基址寄存器是EBP,因此默認SS為段基址寄存器。
基址加間址尋址主要用于二維數(shù)組的操作。
9.基址加比例間址尋址(based indexed proportion addressing)
在基址加比例間址尋址方式中,有效地址的計算公式如下:
EA=(基址寄存器)+(間址寄存器)×比例因子
例如:MOV EAX,[EBX] [EDI×8]
基址加比例間址尋址方式只適用于32位尋址。
10.帶位移的基址加間址尋址(based indexed relative)
在帶位移的基址加間址尋址方式中,有效地址的計算公式如下:
EA=(基址寄存器)+(間址寄存器)+位移量
帶位移的基址加間址尋址方式分為16位和32位尋址兩種情況。
例如:MOV AX,[BX+SI+MASK]
ADD EDX,[ESI][EBP+0FFF0000H]
MOV DX,RSSA [BX][SI]
(也可寫成MOV DX,RSSA [BX+SI]或MOV DX,[RSSA+BX+SI])
如果DS=3000H,BX=2000H,SI=1000H,位移量RSSA=0250H時,則
物理地址=DS×16+BX+SI+RSSA
=30000H+2000H+1000H+0250H
=33250H
其尋址及執(zhí)行過程如圖3.6所示。
注意:當基址寄存器和間址寄存器默認的段寄存器不同時,一般以基址寄存器決定的段寄存器作為段基址寄存器。
11.帶位移的基址加比例間址尋址(based indexed proportion relative)
EA=(間址寄存器)×比例因子+(基址寄存器)+位移量
這種尋址方式只有32位尋址一種情況。
例如:INC BYTE PTR [EDI×8][EDX+40H]
以上11種尋址方式可以分為兩大類。
(1)非存儲器操作尋址方式:包括立即數(shù)尋址和寄存器尋址。這類尋址方式不需要訪問存儲器,故執(zhí)行速度快。
(2)訪問存儲器操作尋址方式:后9種尋址方式屬于這一類。在進行訪問存儲器操作時,除要計算有效地址EA外,還必須確定操作數(shù)所在的段,即確定有關(guān)的段寄存器。
編寫程序時應(yīng)注意以下5點。
① 在一般情況下,指令不特別指出段寄存器。80486微處理器約定了默認的段寄存器。
② 有的指令允許段超越尋址,這時指令中應(yīng)加上超越前綴。
③ 程序只能存放在代碼段中,使用IP(EIP)作為偏移地址寄存器。
④ 堆棧操作數(shù)只能在堆棧中,使用SP或BP(ESP或EBP)作為偏移地址寄存器。
⑤ 在串操作中,目標操作數(shù)只能在附加數(shù)據(jù)段ES中,其他操作雖然也有默認段,但都是允許段超越的。
3.2.2 對程序轉(zhuǎn)移地址的尋址方式
通常,CPU執(zhí)行程序的順序是由代碼段寄存器CS和指令指針I(yè)P(EIP)的內(nèi)容所確定的。指令指針I(yè)P(EIP)具有自動加1的功能,每當BIU取完一條指令以后,IP(EIP)的內(nèi)容都會自動加1指向下一條指令,以便使程序按照指令存放的次序由低地址到高地址依次執(zhí)行。當程序中有跳轉(zhuǎn)指令時,就需要改變以上順序執(zhí)行的過程,按照指令的要求修改IP(EIP)的內(nèi)容或同時修改IP(EIP)和CS的內(nèi)容,從而將CPU引導(dǎo)到指令所規(guī)定的地址去執(zhí)行。程序轉(zhuǎn)移地址的尋址方式,尋找的是程序轉(zhuǎn)移的目標地址,而不是操作數(shù)。
在80486微機系統(tǒng)中,由于存儲器采用了分段結(jié)構(gòu),因此,對轉(zhuǎn)移地址的尋址方式分為段內(nèi)尋址和段間尋址兩類。圖3.7以16位尋址為例,展示了轉(zhuǎn)移地址的尋址方式。
1.段內(nèi)直接尋址
段內(nèi)直接尋址也稱為相對尋址。轉(zhuǎn)向的有效地址是當前IP寄存器中的內(nèi)容和指令指定的8位或16位位移量之和,如圖3.7(a)所示。
當位移量是8位時,稱為短程轉(zhuǎn)移,常在轉(zhuǎn)向的符號地址前加操作符SHORT。當位移量是16位時,稱為近程轉(zhuǎn)移,常在轉(zhuǎn)向的符號地址前加操作符NEAR PTR。
例如:JMP SHORT LOOP1
JMP NEAR PTR LOOP2
其中,LOOP1和LOOP2均為程序轉(zhuǎn)向的符號地址。
2.段內(nèi)間接尋址
段內(nèi)間接尋址方式的特點是程序轉(zhuǎn)向的有效地址存放在寄存器或存儲單元中。指令執(zhí)行時,可用寄存器或存儲單元中的內(nèi)容去更新指令指針I(yè)P值,從而正確地實現(xiàn)程序轉(zhuǎn)移,如圖3.7(b)所示。
例如:JMP BX
JMP WORD PTR[SI+2000H]
其中,WORD PTR是一個操作符,說明跟在其后的存儲器操作數(shù)所取得的轉(zhuǎn)向地址是一個字類型的有效地址,從而表明這種尋址方式是一種段內(nèi)轉(zhuǎn)移。
以上兩種尋址方式均為段內(nèi)尋址,由于轉(zhuǎn)向的目標地址與跳轉(zhuǎn)指令同在一個代碼段內(nèi),因此不需修改CS的內(nèi)容,只需要修改指令指針I(yè)P的內(nèi)容,根據(jù)指令的尋址方式求得轉(zhuǎn)向的有效地址EA并送到IP寄存器就可以了。轉(zhuǎn)向的物理地址計算公式為:
物理地址=(CS)×16+IP
3.段間直接尋址
段間直接尋址方式的特點是,在跳轉(zhuǎn)指令中直接給出轉(zhuǎn)向的段基址和偏移地址,16位的段基址用來更新CS,16位的偏移地址用來更新IP,從而完成從一個段到另一段的轉(zhuǎn)移。在這種尋址方式的指令中,常在轉(zhuǎn)向的符號地址前加上操作符FAR PTR,如圖3.7(c)所示。
例如:JMP FAR PTR LOOP3;LOOP3為轉(zhuǎn)向的符號地址
4.段間間接尋址
段間間接尋址方式的特點是,由指令尋址方式確定的連續(xù)兩個字的內(nèi)容來取代IP和CS寄存器中的原有內(nèi)容,低位字單元中的16位數(shù)據(jù)作為轉(zhuǎn)向的偏移地址用以取代IP中的內(nèi)容,高位字單元中的16位數(shù)據(jù)作為段基址用以取代CS中的內(nèi)容,從而實現(xiàn)段間程序轉(zhuǎn)移,如圖3.7(d)所示。
例如:JMP DWORD PTR [BX]其中,DWORD PTR為雙字操作符,說明后面緊跟的存儲器操作數(shù)所取得的轉(zhuǎn)向地址是一個雙字的有效地址。
以上兩種尋址方式均為段間尋址,跳轉(zhuǎn)指令和轉(zhuǎn)向地址分別在兩個不同的代碼段內(nèi),所以既需要修改IP的內(nèi)容,又需要修改CS的內(nèi)容,這樣才能實現(xiàn)段間轉(zhuǎn)移。
3.2.3 關(guān)于I/O端口的尋址方式
80486微處理器允許使用地址總線的低16位A15~A0來訪問I/O端口,共有65536(216)個端口地址,地址范圍為0000H~FFFFH。80486微處理器采取獨立編址方式,對I/O端口可采用兩種尋址方式。
1.直接尋址
端口的直接尋址方式僅適合于訪問地址范圍為00H~FFH的端口,在輸入/輸出指令中,端口地址以8位立即數(shù)的形式出現(xiàn)。
例如:IN AL,80H
表示由地址為80H的端口讀取一個字節(jié)數(shù)據(jù)到AL中。
2.間接尋址
端口的間接尋址方式適合于訪問地址范圍為0000H~FFFFH的全部端口,當端口地址為0100H~FFFFH時,必須采用間接尋址方式。在輸入/輸出指令中,端口是16位的立即數(shù)。端口間接尋址只可使用DX寄存器,16位的I/O端口地址必須預(yù)置在DX中。
例如:MOV DX,2000H
OUT DX,AX
表示將AX中的16位數(shù)據(jù)由(DX+1)和(DX)確定的2001H和2000H兩個端口輸出。