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