ARM匯編編程基礎之三-基本尋址方式與基本指令
首先,來看一看我們已經見過的2條指令:MOV pc, lr; BL addsub
本文引用地址:http://www.104case.com/article/201611/322182.htm最簡單的匯編指令格式是操作碼(例如:MOV、BL)和操作數(例如:pc, lr, addsub)。操作碼易于理解,例如MOV表示將某個值從一處傳送到另一處,BL表示跳轉到某處;而操作數則表示一處和另一處到底是哪里(是在寄存器中還是內存中),要跳轉的位置在哪里(或者是絕對地址或者是相對地址)。
操作數部分要解決的問題是:到哪里去獲得操作數?因此就有了尋址方式的分類。基本上來講,ARM共有8種尋址方式,本文我們了解其中最基本的3種尋址方式:寄存器尋址、立即數尋址、寄存器間接尋址。
1、寄存器尋址
MOV pc, lr 表示操作數來源于寄存器(pc和lr)。這種尋址方式,在指令的32位機器碼中的地址碼部分,存放的是寄存器(pc和lr)的編號,故稱之為寄存器尋址。
2、立即數尋址
MOV pc, #64 表示將常數64放入寄存器pc,其中常數64被稱為立即數。立即數尋址指令中的地址碼部分就是操作數本身,也就是說,數據就包含在指令當中,取出指令也就取出了可以立即使用的操作數(故稱為立即數)。
這里,可能大家會看出一個問題:由于立即數是位于32位機器碼中的,而32位機器碼中除了操作數外還有操作碼,這就意味著不可能用全部32bit來表示立即數。事實上,ARM機器指令中,僅用了最低的12bit來表示立即數。那么我們自然推論立即數的范圍是-2048——2047,這意味著MOV pc, #8192這樣的指令是非法的。但事實情況并非如此,MOV pc,#8192是合法且能正常運行的。真實情況是,ARM機器指令可以表示的立即數范圍是-2^31--2^31-1,只不過它只能表示這其中的2^12個數而已。ARM是這樣用12bit來表示1個立即數的:將12bit劃分為2部分——高4位和低8位,將低8位補0擴展為32位,然后循環右移X位(X = 高4位表示的無符號整數*2),例如:如果32位機器碼中低12bit為0x512,則其表示的立即數為0x04800000
這里,請大家不妨現在先思考2個問題,我們將在后續文章中予以解答:
1)、為什么ARM要這樣設計,而不是按照我們最常見的想法(即:12bit就表示-2^11 -- 2^11-1中的數)
2)、如果我們需要mov r0, #10000這樣的指令,應該怎么辦?(常數10000不能按照如上的方法進行表示)
3、寄存器間接尋址
寄存器間接尋址指令中的地址碼給出的是一個通用寄存器的編號,所需的操作數保存在寄存器指定地址的存儲單元中,即寄存器為操作數的地址指針。例如:
LDR R0, [R2]表示將R2的值作為內存地址,到該內存處取出存放的數,放到寄存器R0中
執行LDR R0, [R2]前的情況 執行LDR R0, [R2]后的情況
了解了基本的尋址方式后,我們現在來看一看最常用的匯編指令
1、單寄存器加載指令。主要有
加載字指令:LDR r0, [r1],將內存中的一個字(4個字節)加載到寄存器r0中
加載字節指令:LDRB r0, [r1],將內存中的一個字節加載到寄存器r0中
有符號數加載字節指令:LDRSB r0, [r1],這條指令與上一條指令的不同之處在于,由于加載的是一個字節,而不是一個字,所以需要確定寄存器r0的高24bit是什么。對于上一條指令,r0的高24bit補0,而本條指令,r0的高24bit補符號位,也就是補r0的bit7
2、單寄存器存儲指令。主要有
存儲字指令:STR r0, [r1],將r0中的值存儲到內存的4個字節中
存儲字節指令:STRB r0, [r1],將r0的低8bit存儲到內存的1個字節中
評論