轉自新浪微博,有一定的補充和修改
作者: shmilylff
Windows彙編語言程序設計——操作數的尋址方式
==============================操作數的尋址方式
==============================
尋址方式就是在彙編語言程序中如何表示操作數的各種方法,其最終的目的是找到所要操作的數據的地址。
尋址方式一般有如下七種:
1.立即尋址
立即(Immediate)尋址,就是在指令中使用的操作數是常數,這個常數就包含在指令中。以下幾條指令都是立即尋址的例子:MOV AL,0
MOV AX,190
MOV EAX,-1
MOV EAX,0FFFFFFFFH
這些指令碼中,都包含了立即數,如0,190,-1,0FFFFFFFFH。
2.寄存器尋址
寄存器(Register)尋址方式的操作數在CPU內部的寄存器中。使用寄存器尋址,CPU不用訪問內存就可以取得或修改操作數。MOV BL,80 //目標操作數BL是寄存器尋址
MOV EAX,EBX //源操作數EBX和目標操作數EAX都是寄存器尋址
3.直接尋址(CPU尋找內存中的操作數)
除了立即尋址和寄存器尋址方式外,其他的幾種尋址方式的操作數都在內存單元中,尋址方式要說明的是CPU如何確定內存操作數的地址,然後CPU再對該內存單元中的操作數進行處理。直接尋址(Direct)尋址就是指令中直接給出了操作數的地址。指令中使用變量時,就是直接尋址。
MOV EAX,dVal
MOV dVal,EBX
MOV EAX,[4000H] //直接給出內存所在地址
在翻譯成機器指令後,變量是用它的地址而不是它的名字來表示的。地址外面加一對方括號,表示取這個地址中的內容。00401010 A1 11 40 40 00 MOV EAX,[00404011]
00401015 89 1D 11 40 40 00 MOV [00404011],EBX
CPU在執行指令的時候,可以直接從指令碼中取出地址,而不必經過計算或其他操作,所以叫做直接尋址。
4.寄存器間接尋址
採用寄存器間接(Indirect)尋址方式的操作數的地址放在寄存器中。
MOV ESI,00404011H //將內存地址保存到寄存器中MOV EAX,[ESI]
注意,MOV EAX,ESI和MOV EAX,[ESI]的區別。
在8086/8088/80286等16位的CPU中,只有4個寄存器能用做寄存器間接尋址:BX,BP,SI,DI。因此,寄存器間接尋址只能是下列之一:[BX],[BP],[SI],[DI]。而在80386及以後的32位CPU中,下面8個寄存器能用做寄存器間接尋址:EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP。
5.寄存器相對尋址
寄存器相對尋址方式的操作數,其地址是寄存器和一個立即數相加後得到的結果。寄存器的內容不直接作爲操作數的地址,寄存器的內容再加上一個“相對量”(displacement)後,就得到內存的地址。MOV ESI,0040200AH
MOV EDI,[ESI+4]
相對量也可以是一個負數:
MOV EDI,[ESI-4]
6.基址變址尋址
基址變址尋址方式的操作數,其地址是兩個寄存器相加後得到的結果。這裏的兩個寄存器分別稱爲基址寄存器(Base Register)和變址寄存器(Index Register)。MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[EBX+ESI]
在8086/8088/80286等16位的CPU中,基址寄存器有兩個:BX和BP,變址寄存器也有兩個:SI和DI。因此,基址變址寄存器只能是4種組合
之一:[BX+SI],[BX+DI],[BP+SI]和[BP+DI]。而在80386及以後的32位CPU中,基址寄存器有8個:EAX,EBX,ECX,EDX,ESI,EDI,EBP和ESP,變址寄存器有7個:EAX,EBX,ECX,EDX,ESI,EDI和EBP。ESP只能作爲基址寄存器,而不能作爲變址寄存器。
7.基址變址相對尋址
基址變址相對尋址方式的操作數,其地址是兩個寄存器以及一個立即數相加後得到的結果。“基址變址相對”的3個元素代表:基址寄存器(base register)、變址寄存器(index register)和相對量(displacement)。MOV ESI,0040200AH
MOV EBX,4
MOV EDI,[EBX+ESI+4]
相對量爲0的基址變址相對尋址就是基址變址尋址。
尋址方式小結:
內存操作數的地址又稱爲有效地址(EA Effective Address)。立即尋址和寄存器尋址中,操作數是立即數和寄存器,沒有有效地址。段超越:
內存操作數的地址由兩個部分指定:段基址和有效地址(又稱偏移地址)。尋址方式中確定操作數的有效地址後,還要依靠段寄存器一起來確定操作數的內存地址。
在沒有指定段寄存器的情況下,如果在尋址方式的有效地址中使用了ESP和EBP寄存器,那麼使用SS段寄存器。對所有其他情況,使用DS段寄存器。
例如,下面指令中的內存操作數在SS段中:
MOV EAX,[EBP+8]
MOV EBX,[ESP-4]
例如,下面指令中的內存操作數在DS段中:
MOV EAX,[EBX+8]
MOV EBX,[ESI-4]
MOV EAX,[0040200AH]
使用段超越前綴可以改變在尋址方式中默認使用的段寄存器,明確地指定操作數位於哪一個段中。
MOV EAX,CS:[EDI]
MOV EBX,ES:[ESP-4]
MOV DS:[EBP],ECX
CS段寄存器只能用來讀取數據,因此,只能作爲源操作數的段前綴。
在Windows 32位環境中,FS段中保存的是系統使用的一些信息,如果要訪問這個段的內存時,必須明確指出段寄存器爲FS。
在Windows 32位環境中,CS,DS,ES,SS在內存中指向同一個段,其大小爲4GB。所以,程序中一般不需要使用段超越前綴
來指定操作數的段寄存器。