所謂尋址方式就是處理器根據指令中給出的地址信息來尋找物理地址的方式。
ARM處理器的尋址方式
目前ARM處理器支持9種尋址方式,分別是立即數尋址、寄存器尋址、寄存器偏移尋址、寄存器間接尋址、基址變址尋址、多寄存器尋址、相對尋址、堆棧尋址和塊拷貝尋址。
1. 立即數尋址
也叫立即尋址,是一種特殊的尋址方式,操作數本身包含在指令中,只要取出指令也就取到了操作數。這個操作數叫做立即數,對應的尋址方式叫做立即尋址。例如:
MOV R0,#64 ;R0 ← 64
ADD R0, R0, #1 ; R0 ← R0 + 1
SUB R0, R0, #0X3D ; R0 ← R0 – 0X3D
在立即數尋址中,要求立即數以“#”爲前綴,對於以十六進制表示的立即數,還要求在“#”後加上“0X”或“&”或”0x“。
在ARM處理器中,立即數必須對應8位位圖格式,即立即數是一個在16位或32位的寄存器中的8bit常數,經循環移動偶數位得到。合法的立即數必須能夠找到得到它的那個常數,否則這個立即數就是非法的。
例如:0X80是合法的,它可以通過0X80向左或向右移動0位得到,由於8位的常數都可以由其自身移動0位得到,因此8位的立即數都是合法的。
0X03F8也是合法的,把它寫成二進制形式爲:0011 1111 1000,可以看出如果使用0XFE這個8位的常數在16位寄存器中循環左移2位就可以得到0X03F8。
判斷一個立即數是否合法可以用以下的辦法:即對於這個立即數進行循左移或右移操作,看看經過移動偶數位後,是否可以得到一個不大於0XFF的立即數(即不超過8位的立即數),如果可以得到,這個立即數就是合法的,否則就是非法的。象0X1010、0X1FA、0X1FF都是不合法的。
2. 寄存器尋址
寄存器尋址就是利用寄存器中的數值作爲操作數,也稱爲寄存器直接尋址。
例如:ADD R0,R1, R2 ;R0 ← R1 + R2
該指令的執行效果是將寄存器R1和R2的內容相加,其結果存放在寄存器R0中。
這種尋址方式是各類微處理器經常採用的一種方式,也是執行效率較高的尋址方式。
3. 寄存器間接尋址
寄存器間接尋址就是把寄存器中的值作爲地址,再通過這個地址去取得操作數,操作數本身存放在存儲器中。
例如:
LDR R0,[R1]
;R0 ←[R1],以寄存器R1的值作爲操作數的地址,把取得操作數傳送到R0中
ADD R0,R1,[R2]
;R0 ←R1 + [R2],以寄存器R2的值作爲操作數的地址,取得操作數後與R1相加,結果存入寄存器R0中。
4. 寄存器偏移尋址
這是ARM指令集特有的尋址方式,它是在寄存器尋址得到操作數後再進行移位操作,得到最終的操作數。
例如:
MOV R0,R2,LSL #3 ;R0 ← R2 * 8 ,R2的值左移3位,結果賦給R0。
MOV R0,R2,LSL R1 ;R2的值左移R1位,結果放入R0。
可採用的移位操作如下:
LSL:邏輯左移(Logical Shift Left),寄存器中字的低端空出的位補0。
LSR:邏輯右移(Logical Shift Right),寄存器中字的高端空出的位補0。
ASL:算術左移(Arithmetic Shift Left),和邏輯左移LSL相同。
ASR:算術右移(Arithmetic Shift Right),移位過程中符號位不變,即如果源操作數是正數,則字的高端空出的位補0,否則補1。
ROR:循環右移(Rotate Right),由字的低端移出的位填入字的高端空出的位。
RRX:帶擴展的循環右移(Rotate Right eXtended),操作數右移一位,高端空出的位用進位標誌C的值來填充,低端移出的位填入進位標誌位。
5. 寄存器基址變址尋址
寄存器基址變址尋址又稱爲基址變址尋址,它是在寄存器間接尋址的基礎上擴展來的。它將寄存器(該寄存器一般稱作基址寄存器)中的值與指令中給出的地址偏移量相加,從而得到一個地址,通過這個地址取得操作數。
例如:
LDR R0,[R1,#4]
;R0 ←[R1 + 4],將R1的內容加上4形成操作數的地址,取得的操作數存入寄存器R0中。
LDR R0,[R1,#4]!
;R0 ←[R1 + 4]、R1 ←R1 + 4,將R1的內容加上4形成操作數的地址,取得的操作數存入寄存器R0中,然後,R1的內容自增4個字節。其中!表示指令執行完畢把最後的數據地址寫到R1。
LDR R0,[R1,R2]
;R0 ←[R1 + R2],將寄存器R1的內容加上寄存器R2的內容形成操作數的地址,取得的操作數存入寄存器R0中。
STR R0, [R1,#-4]
;R0→[R1 -4],將R1中的數值減4作爲地址,把R0中的數據存放到這個地址中。
LDR R0,[R1],#4 ;R0 ←[R1]、R1 ←R1+4
6. 多寄存器尋址
這種尋址方式可以一次完成多個寄存器值的傳送。例如:
LDMIA R0,{R1,R2,R3,R4}
LDM:Load Data from Memory to Register.
;R1←[R0],R2←[R0+4],R3←[R0+8],R4←[R0+12]
該指令的後綴IA表示在每次執行完加載/存儲操作後,R0按字長度增加,因此,指令可將連續存儲單元的值傳送到R1~R4。
LDMIA R0,{R1-R4} ;功能同上。
使用多寄存器尋址指令時,寄存器子集的順序如果由小到大的順序排列,可以使用“-”連接,否則,用“,”分隔書寫。
7. 相對尋址
相對尋址是一種特殊的基址尋址,特殊性是它把程序計數器PC中的當前值作爲基地址,語句中的地址標號作爲偏移量,將兩者相加之後得到操作數的地址。
BL NEXT ;相對尋址,跳轉到NEXT處執行。
……
……
NEXT
……
8. 堆棧尋址
堆棧是一種數據結構,按先進後出(First In Last Out,FILO)的方式工作,使用堆棧指針(Stack Pointer, SP)指示當前的操作位置,堆棧指針總是指向棧頂。
根據堆棧的生成方式不同,可以把堆棧分爲遞增堆棧和遞減堆棧兩種類型。如下圖所示:
l 遞增堆棧:向堆棧寫入數據時,堆棧由低地址向高地址生長。
l 遞減堆棧:向堆棧寫入數據時,堆棧由高地址向低地址生長。
同時,根據堆棧指針(SP)指向的位置,又可以把堆棧分爲滿堆棧(Full Stack)和空堆棧(Empty Stack)兩種類型。
l 滿堆棧(Full Stack):堆棧指針指向最後壓入堆棧的數據。滿堆棧在向堆棧存放數據時的操作是先移動SP指針,然後存放數據。在從堆棧取數據時,先取出數據,隨後移動SP指針。這樣保證了SP一直指向有效的數據。
l 空堆棧(Empty Stack):堆棧指針SP指向下一個將要放入數據的空位置。空堆棧在向堆棧存放數據時的操作是先放數據,然後移動SP指針。在從堆棧取數據時,是先移動指針,再取數據。這種操作方式保證了堆棧指針一直指向一個空地址(沒有有效數據的地址)。
上述兩種堆棧類型的組合,可以得到四種基本的堆棧類型,即:
- 滿遞增堆棧(FA):堆棧指針指向最後壓入的數據,且由低地址向高地址生長。
- 滿遞減堆棧(FD):堆棧指針指向最後壓入的數據,且由高地址向低地址生長。
- 空遞增堆棧(EA):堆棧指針指向下一個將要壓入數據的地址,且由低地址向高地址生長。
- 空遞減堆棧(ED):堆棧指針指向下一個將要壓入數據的地址,且由高地址向低地址生長。
堆棧尋址舉例如下:
STMFD SP!,{R1-R7, LR}
STM: Store Data From register to Stack (Memory).
;將R1-R7, LR壓入堆棧。滿遞減堆棧。
LDMED SP!,{R1-R7, LR}
;將堆棧中的數據取回到R1-R7, LR寄存器。空遞減堆棧。
9. 塊拷貝尋址
塊拷貝尋址用於寄存器數據的批量複製,它實現從由基址寄存器所指示的一片連續存儲器到寄存器列表所指示的多個寄存器傳送數據。塊拷貝尋址與堆棧尋址有所類似。兩者的區別在於:堆棧尋址中數據的存取是面向堆棧的,塊拷貝尋址中數據的存取是面向寄存器指向的存儲單元的。
在塊拷貝尋址方式中,基址寄存器傳送一個數據後有4種增長方式,即:
- IA:每次傳送後地址增加4;(Increment After Operating)
- IB:每次傳送前的地址增加4;(Increment Before Operating)
- DA:每次傳送後地址減少4;(Decrement After Operating)
- DB:每次傳送前地址減少4。(Decrement Before Operating)
對於32位的ARM指令,每次地址的增加和減少的單位都是4 個字節單位。
例如:
STMIA R0!,{R1—R7}
;將R1-R7的數據保存到R0指向的存儲器中,存儲器指針在保存第一個值之後增加4,向上增長。R0作爲基址寄存器。
STMIB R0!,{R1—R7}
;將R1-R7的數據保存到存儲器中,存儲器指針在保存第一個值之前增加4,向上增長。R0作爲基址寄存器。
STMDA R0!,{R1—R7}
;將R1-R7的數據保存到R0指向的存儲器中,存儲器指針在保存第一個值之後減少4,向下減少。R0作爲基址寄存器。
STMDB R0!,{R1—R7}
;將R1-R7的數據保存到存儲器中,存儲器指針在保存第一個值之前減少4,向下減少。R0作爲基址寄存器。
ARM指令中{!},爲可選後綴,若選用該後綴,則當數據傳送完畢之後,將最後的地址寫入基址寄存器,否則基址寄存器的內容不改變。
基址寄存器不允許爲R15,寄存器列表可以爲R0~R15的任意組合。
{^}爲可選後綴,當指令爲LDM且寄存器列表中包含R15,選用該後綴時表示:除了正常的數據傳送之外,還將SPSR複製到CPSR。同時,該後綴還表示傳入或傳出的是用戶模式下的寄存器,而不是當前模式下的寄存器。