通過上一節的例子我們瞭解到,訪問內存時在指令中可以用多種方式表示內存地址,比如可以用數組基地址、元素長度和下標三個量來表示,增加了定址的靈活性。本節介紹x86常用的幾種定址方式(Addressing Mode)。內存定址在指令中可以表示成如下的通用格式:
ADDRESS_OR_OFFSET(%BASE_OR_OFFSET,%INDEX,MULTIPLIER)
它所表示的地址可以這樣計算出來:
FINAL ADDRESS = ADDRESS_OR_OFFSET + BASE_OR_OFFSET + MULTIPLIER * INDEX
其中ADDRESS_OR_OFFSET和MULTIPLIER必須是常數,BASE_OR_OFFSET和INDEX必須是寄存器。在有些定址方式中會省略這4項中的某些項,相當於這些項是0。
直接定址(Direct Addressing Mode)。只使用ADDRESS_OR_OFFSET定址,例如movl ADDRESS, %eax
把ADDRESS地址處的32位數傳送到eax
寄存器。
變址定址(Indexed Addressing Mode) 。上一節的movl data_items(,%edi,4), %eax
就屬於這種定址方式,用於訪問數組元素比較方便。
間接定址(Indirect Addressing Mode)。只使用BASE_OR_OFFSET定址,例如movl (%eax), %ebx
,把eax
寄存器的值看作地址,把內存中這個地址處的32位數傳送到ebx
寄存器。注意和movl %eax, %ebx
區分開。
基址定址(Base Pointer Addressing Mode)。只使用ADDRESS_OR_OFFSET和BASE_OR_OFFSET定址,例如movl 4(%eax), %ebx
,用於訪問結構體成員比較方便,例如一個結構體的基地址保存在eax
寄存器中,其中一個成員在結構體內的偏移量是4位元組,要把這個成員讀上來就可以用這條指令。
立即數定址(Immediate Mode)。就是指令中有一個操作數是立即數,例如movl $12, %eax
中的$12
,這其實跟定址沒什麼關係,但也算作一種定址方式。
寄存器定址(Register Addressing Mode)。就是指令中有一個操作數是寄存器,例如movl $12, %eax
中的%eax
,這跟內存定址沒什麼關係,但也算作一種定址方式。在彙編程序中寄存器用助記符來表示,在機器指令中則要用幾個Bit表示寄存器的編號,這幾個Bit也可以看作寄存器的地址,但是和內存地址不在一個地址空間。