arm指令屬於精簡計算機指令(risc),其條數較多,較難記憶,但事物的發展都是有延續性的,尤其是自然科學,其本身就是一種積累,所以她們的發展就必然是建立在某種規律之上的!掌握和熟悉規律之後再去研究細節,往往能達到事半功倍的效果!
最近有需求,也渴望掌握arm指令集,所以決定擠出時間攻克之!
邏輯運算指令和算數運算指令算是比較簡單的,略過一遍,還好,下次看到應該可以推測出她們的意思,沒必要花太多的時間去記憶和理解!
接下來就遇到一些儲存指令了,這類指令分為讀取和儲存兩類,在這邊就先不總結了,摘抄博友的內容如下:
它們可能是能獲得的最有用的指令。其他指令都操縱暫存器,所以必須把資料從記憶體裝載暫存器並把暫存器中的資料儲存到記憶體中。
使用單一資料傳送指令(str 和 ldr)來裝載和儲存單一位元組或字的資料從/到記憶體。定址是非常靈活的。
首先讓我們檢視指令格式:
ldr rd, 《位址》 str rd, 《位址》 ldrb rd, 《位址》 strb rd, 《位址》指令格式
這些指令裝載和儲存 rd 的值從/到指定的位址。如果象後面兩個指令那樣還指定了『b』,則只裝載或儲存乙個單一的位元組;對於裝載,暫存器中高階的三個位元組被置零(zeroed)。
位址可以是乙個簡單的值、或乙個偏移量、或者是乙個被移位的偏移量。可以還可以把合成的有效位址寫回到基址暫存器(去除了對加/減操作的需要)。
各種定址方式的示例:
譯註:下文中的 rbase 是表示基址暫存器,rindex 表示變址暫存器,index 表示偏移量,偏移量為 12 位的無符號數。用移位選項表示比例因子。標準定址方式 - 用 at&t 語法表示為 disp(base, index, scale),用 intel 語法表示為 [base + index*scale + disp],中的變址(連帶比例因子)與偏移量不可兼得。
str rd, [rbase] 儲存 rd 到 rbase 所包含的有效位址。 str rd, [rbase, rindex] 儲存 rd 到 rbase + rindex 所合成的有效位址。 str rd, [rbase, #index] 儲存 rd 到 rbase + index 所合成的有效位址。 index 是乙個立即值。 例如,str rd, [r1, #16] 將把 rd 儲存到 r1+16。 str rd, [rbase, rindex]! 儲存 rd 到 rbase + rindex 所合成的有效位址, 並且把這個新位址寫回到 rbase。 str rd, [rbase, #index]! 儲存 rd 到 rbase + index 所合成的有效位址, 並且並且把這個新位址寫回到 rbase。 str rd, [rbase], rindex 儲存 rd 到 rbase 所包含的有效位址。 把 rbase + rindex 所合成的有效位址寫回 rbase。 str rd, [rbase, rindex, lsl #2] 儲存 rd 到 rbase + (rindex * 4) 所合成的有效位址。 str rd, place 儲存 rd 到 pc + place 所合成的有效位址。你當然可以在這些指令上使用條件執行。但要注意條件標誌要先於位元組標誌,所以如果你希望在結果是等於的時候裝載乙個位元組,要用的指令是
ldreqb rx,
(不是ldrbeq...
)。
如果你指定預先變址定址(這裡的基址和變址都在方括號中),用是否存在『!』來控制寫回操作。上面的第4和第5個例子中使用了這個標誌。你可以使用它來在記憶體中自動正向或反向移動。乙個字串列印例程將變成:
.loop ldrb r0, [r1, #1]! swi "os_writec" cmp r0, #0 bne loop而不是:
.loop ldrb r0, [r1] swi "os_writec" add r1, r1, #1 cmp r0, #0 bne loop對於過後變址定址『!』是無效的(這裡的變址在方括號外面,比如上面的例子6),因為寫回是暗含的。
如同你見到的那樣,變址可以被移位來實現比例縮放。除此之外,可以從基址上減去偏移量。在這種情況下,你可以使用如下**:
ldrb r0, [r1, #-1]儘管你可以儲存或裝載 pc,但你不可以用裝載或儲存指令來修改 psr。要裝載乙個被儲存的『狀態』並正確的恢復它,請使用:
ldr r0, [rbase] movs r15, r0假如你在有特權的模式下,movs 將導致 psr 的位被更改。
對 pc 使用movs
不遵從 32-bit 體系,
你需要使用mrs 和 msr來處理 psr。
依照 arm 彙編手冊:
譯註:下文所敘述內容針對的是小端位元組序配置,對大端位元組序配置在手冊中另有專門敘述。
使用多資料傳送指令(ldm 和 stm)來裝載和儲存多個字的資料從/到記憶體。
ldm/stm 的主要用途是把需要儲存的暫存器複製到棧上。如我們以前見到過的stmfd r13!,
。
指令格式是:
xxm rn, 《暫存器列表》『xx』是 ld 表示裝載,或 st 表示儲存。
再加 4 種『型別』就變成了 8 個指令:
棧 其他 ldmed ldmib 預先增加裝載 ldmfd ldmia 過後增加裝載 ldmea ldmdb 預先減少裝載 ldmfa ldmda 過後減少裝載 stmfa stmib 預先增加儲存 stmea stmia 過後增加儲存 stmfd s***b 預先減少儲存 stmed s***a 過後減少儲存指令格式
彙編器關照如何對映這些助記符。注意 ed 不同於 ib;只對於預先減少裝載是相同的。在儲存的時候,ed 是過後減少的。
fd、ed、fa、和 ea 指定是滿棧還是空棧,是公升序棧還是降序棧。乙個滿棧的棧指標指向上次寫的最後乙個資料單元,而空棧的棧指標指向第乙個空閒單元。乙個降序棧是在記憶體中反向增長(就是說,從應用程式空間結束處開始反向增長)而公升序棧在記憶體中正向增長。
其他形式簡單的描述指令的行為,意思分別是過後增加(increment after)、預先增加(increment before)、過後減少(decrement after)、預先減少(decrement before)。
risc os 使用傳統的滿降序棧。在使用符合 apcs 規定的編譯器的時候,它通常把你的棧指標設定在應用程式空間的結束處並接著使用乙個 fd (滿降序 - full descending)棧。如果你與乙個高階語言(basic 或 c)一起工作,你將別無選擇。棧指標(傳統上是 r13)指向乙個滿降序棧。你必須繼續這個格式,或則建立並管理你自己的棧(如果你是死硬派人士那麼你可能喜歡這樣做!)。
『基址』是包含開始位址的暫存器。在傳統的 risc os 下,它是棧指標 r13,但你可以使用除了 r15 之外的任何可獲得的暫存器。
如果你想把複製操作後棧頂的當前的記憶體位址儲存到棧指標中,可以暫存器按從最低到最高的編號次序與到從低端到高階的記憶體之間傳送資料。並且因為用指令中的乙個單一的位來表示是否儲存乙個暫存器,不可能指定某個暫存器兩次。它的***是不能用下面這樣的**:
stmfd r13!, ldmfd r13!,來交換兩個暫存器的內容。
提供了乙個有用的簡寫。要包含乙個範圍的暫存器,可以簡單的只寫第乙個和最後乙個,並在其間加乙個橫槓。例如r0-r3
等同與r0, r1, r2, r3
,只是更加整齊和理智而已...
在把 r15 儲存到記憶體中的時候,還儲存了 psr 位。在重新裝載 r15 的時候,除非你要求否則不恢復 psr 位。要求的方法是在暫存器列表後跟隨乙個『^』。
stmfd r13!, ... ldmfd r13!,這儲存所有的暫存器,做一些事情,接著重新裝載所有的暫存器。從 r14 裝載 pc,它由乙個 bl 或此類指令所設定。不觸及 psr 標誌。
stmfd r13!, ... ldmfd r13!, ^這儲存所有的暫存器,做一些事情,接著重新裝載所有的暫存器。從 r14 裝載 pc,它由乙個 bl 或此類指令所設定。變更 psr 標誌。
警告: 這些**不遵從 32 bit 體系。你需要使用mrs 和 msr來處理 psr,你不能使用『^』字尾。
注意在這兩個例子中,r14 被直接裝載到 pc 中。這節省了對 mov(s) r14 到 r15 中的需要。
警告: 使用 movs pc,... 不遵從 32 bit 體系。你需要使用mrs 和 msr來處理 psr。
ARM指令集和X86指令集的比較
指令的強弱是cpu的重要指標,指令集是提高微處理器效率的最有效工具之一。從現階段的主流體系結構講,指令集可分為複雜指令集 cisc 和精簡指令集 risc 兩部分。相應的,微處理隨著微指令的複雜度也可分為cisc及risc這兩類。cisc 是一種為了便於程式設計和提高記憶體訪問效率的晶元設計體系。在...
ARM的六大類指令集 載入 儲存指令
arm 微處理器支援載入 儲存指令用於在暫存器和儲存器之間傳送資料,載入指令用於將儲存器中的資料傳送到暫存器,儲存指令則完成相反的操作。常用的載入儲存指令如下 ldr 字資料載入指令 ldrb 位元組資料載入指令 ldrh 半字資料載入指令 str 字資料儲存指令 strb 位元組資料儲存指令 st...
從最簡單的例項學習ARM 指令集(一)
打算為入門arm指令集寫點初級文章,沒什麼遠大理想,純當娛樂算了。include void main 然後編譯 arm linux gnueabihf gcc test.c o test1 然後看看彙編 arm linux gnueabihf objdump d test1 每一句的含義我已經給出詳...