天天看點

一.ARM裸機學習之ARM彙編

四.ARM彙編 2017/10/26 22:39 彙編指令:CPU指令的助記符  僞彙編指令:本質上不是指令,是編譯器環境提供的,目的是用來指導編譯過程,經過編譯後僞指令最終不會生成機器碼

ARM彙編的特點1:LDR/STR架構 ARM采用RISC架構,CPU本身不能直接讀取記憶體(CISC結構的可以直接讀取記憶體),而需要先将記憶體中内容載入CPU中通用寄存器才能被CPU執行。  l ldr (load register) 将記憶體内容加載進入通用寄存器  str (store register) 将寄存器内容存入記憶體空間

ARM彙編的特點2:8種尋址方式

類别 示例
寄存器尋址 mov r1, r2
立即尋址 mov r0, #0xFF00}
寄存器移位尋址 mov r0, r1, lsl #3 @(r0=r1<<3)
寄存器間接尋址 ldr r1, [r2]
基址變址尋址 ldr r1,[r2,#4] @r1 = r2+4
多寄存器尋址 ldmia r1!,{r2-r7,r12}
堆棧尋址 stmfd sp!, {r1-r7,lr}
相對尋址 beq flag

ARM彙編的特點3:指令字尾 同一指令經常附帶不同字尾,變成不同的指令。經常使用的字尾有:

字尾 功能
B (byte) 功能不變,操作長度變為8位
H (half word) 功能不變,長度變為16位
S (signed) 功能不變,操作數變為有符号 如 ldr ldrb ldrh ldrsb ldrsh
S (S标志) 功能不變,影響CPSR标志位 如 mov和movs

ARM彙編的特點3:條件執行字尾

一.ARM裸機學習之ARM彙編
一.ARM裸機學習之ARM彙編

如果字尾條件滿足才執行。 例如:  mov r0, r1 @r0 = r1  moveq r0,r1 @ if(eq) r0 =r1 條件字尾執行注意:條件字尾是否成立,不是取決于本句代碼,而是取決于這句代碼之前的代碼運作後的結果。

ARM彙編的特點4:多級指令流水線 S5PV210使用13級流水線。PC指向正被取值的指令,而非正在執行的指令。 多級指令流水線與一級一條指令執行的過程比較說明 簡單來說,執行某條指令至少要通過取指、譯碼、執行三個步驟。這就好像盲人在吃飯,第一步是用筷子夾出要吃的東西(從記憶體中取出指令),第二步是把吃的東西舉到鼻子底下聞一下看看是否能吃(分析該指令),第三步是放到嘴裡吃(執行指令)。即盲人最少要浪費3秒鐘。如果CPU也采取同樣的方法,執行一條指令,那就意味着 CPU需消耗3個指令周期才能完成一個動作,可見其運作效率的低下 為了彌補這個問題,ARM采用了一種多級流水線的指令執行方式,即是利用多個時鐘周期的時間去執行多條指令,進而大大提高了代碼運作效率。 這就好像一位樂于助人的科學家,知道了盲人吃飯的故事之後,給這位盲人制作了兩隻機械手,現在盲人已經有三隻手了,那麼他會怎樣吃飯呢?當他的第一隻手把吃的送到嘴裡吃的時候(執行指令),第二隻手已經将另外的食物湊到鼻子底下聞了(分析指令),而第三隻手此時正在從盤子裡夾第三樣東西呢。從此,盲人吃飯的效率就提高了三倍。即提高了效率。

五.資料傳輸指令 mov (move) mov r1, r0 @兩個寄存器之間資料傳遞 r1 = r0mov r1, #0xFF @将立即數指派給寄存器 r1 = 0xFF mvn 用法和mov一樣,差別是mvn是按位取反後傳遞 r1 = 0xFF,執行mov r0, r1 後 r0 = 0xFF 執行mvn r0, r1 後 r0 = 0xffffff00

算術指令 add 加法指令add r2, r0, r1 @(r2 = r0+r1)  sub 減法指令sub r2, r0, r1 @(r2 = r0 - r1)  rsb 逆向減法指令  adc 帶進位加法指令  sbc 帶借位減法指令  rsc 帶借位的逆向減法指令 邏輯指令 and 邏輯與  orr 邏輯或  eor 邏輯異或  bic 位清除指令 (bic r0, r1, #0x1F @将r1中的數的bit0到bit4清零後指派給r0 0x1F = 0001 1111) 比較指令 cmp cmp r0, r1 @(r0 - r1 = 0?)  cmn cmn r0, r1 @(r0 + r1 = 0?)  tst tst r0, 0xf @測試r0的bit0-bit3是否全為0  teq teq r0,r1, @P = r0 EOR r1  比較指令不用後加S 就能影響CPSR中的标志位。 乘法指令 mvl mla umull umlal smull smlal 都不常用,這裡隻作為知識點羅列。 前導零計數 clz 傳回操作數二進制編碼中第一個1前0的個數 CPSR通路指令 mrs & msr mrs 用來讀psr (cpsr&spsr)  msr 用來寫psr mrs r0, cpsr 将cpsr的值讀入到r0中  ……………… 處理r0的值  msr cpsr, r0 将r0的值寫入到cpsr中 cpsr : 程式狀态寄存器,CPU中隻有一個,記錄程式運作狀态  spsr:CPU中有五個,分别在五種異常模式下,作用是從普通模式進入異常模式時,用來儲存之前普通模式下的cpsr的,在傳回普通模式時恢複原來的cpsr。 跳轉指令 b & bl &bx b 直接跳轉(沒打算傳回)  bl (branch and link) 跳轉前把傳回位址存在lr寄存器中,以便傳回。  bx 跳轉同時切換到ARM模式,一般用于異常處理的跳轉。 訪存指令 ldr/srt & ldm/stm & swp 單個字/半字/位元組通路 ldr/str  多字批量通路 ldm/stm  swp r1, r2, [r0] 記憶體和寄存器交換指令,将r0所指向記憶體中的資料寫入r1,并将r2中的資料寫入到r0所指向的記憶體。  swp r1, r1, [r0] 互換 軟中斷指令 swi (software interrupt) 用來實作作業系統中的系統調用。 彙編中的立即數 ARM指令都是32位,除了指令标記和操作标記外,本身隻能附帶很少位數的立即數,是以立即數有合法和非法之分。 合法立即數:經過任意位數的移位後非零部分可以用8位辨別的即為合法立即數(非零部分少于等于8位,0x000000ff 是合法立即數,0x00ff0000是合法立即數,0xf000000f循環移位之後仍然是合法立即數,0x000001ff是非法立即數)

六.協處理器以及協處理器指令 什麼是協處理器 Soc内部另一處理核心,協助CPU實作某些功能,被主CPU調用執行一定的任務。CP15 (cooperation processor)  協處理器和MMU、cache、TLB等處理有關,功能上和作業系統的虛拟位址映射、cache等的管理有關。 協處理器通路指令 mcr & mrc mrc 用于讀取CP15中的寄存器  mcr 用于寫CP15中的寄存器 Rd:ARM的普通寄存器,不能是r15/pc  Crn:cp15的寄存器,合法值為c0 - c15  Crm:cp15的寄存器,一般均為c0  mrc p15, 0, r0, c1, c0, 0  mcr p15, 0, r0, c1, c0, 0 ldm/stm與棧的處理 ldr/str每周期隻能通路4個位元組記憶體,如果需要批量讀取,寫入記憶體時太慢,這個時候就要用ldm/stm (load register mutiplt / store register mutiplt) 多寄存器通路舉例  stmia sp, {r0-r12} 将r0存入sp指向的記憶體處,然後位址+4,将r1存入記憶體,然後位址再+4……直到将r12内容存入記憶體。

  • 1
  • 2

棧類型 空棧:棧指針指向 空位 ,每次存入資料後,sp+4  滿棧:棧指針指向 滿位 ,每次存入資料時,先sp+4然後再存入資料  增棧:棧指針移動時向 位址增加的方向 移動  減棧:棧指針移動時向 位址減小的方向 移動  是以有四種棧類型:空增棧,空減棧,滿增棧,滿減棧。 八種字尾

stmia和stmfd用的最多,其他基本沒用過

字尾 意義
ia (increase after) 先傳輸,再位址+4
ib (increase before) 先位址+4,再傳輸
da (decrease after) 先傳輸,再位址-4
db (decreade before) 先位址-4,再傳輸
fd (full decrease) 滿遞減棧
ed (empty decrease) 空遞減棧
fa 滿遞增棧
ea 空遞增棧

操作棧的時候使用相同的字尾,就會避免出錯。 !的作用 ldmia r0, {r2-r3} @把r0指向的記憶體中的資料讀入到r2中,然後記憶體位址+4再将+4後位址中的資料讀入到r3中。指令執行完畢後r0中的值 不變 。  ldmia r0!, {r2-r3} @把r0指向的記憶體中的資料讀入到r2中,然後記憶體位址+4再将+4後位址中的資料讀入到r3中。指令執行完畢後r0中的值 變化 。 感歎号的作用就是r0的值在ldm過程中發生的增加或者減小最後寫會到r0中。 ^的作用 ldmfd sp!, {r0-r6, pc}  ldmfd sp!, {r0-r6, pc}^  ^:在目标寄存器中有pc時,會同時将spsr寫入到cpsr,一般用在 異常傳回 的時候。

七.GNU彙編僞指令 僞指令和指令最大的差別是經過編譯後不會生成機器碼 僞指令是和具體的編譯器相關的,我們使用gnu工具鍊,是以學習gnu環境下的彙編僞指令。 GNU彙編中的一些符号 @ 行注釋,可以在指令後邊也可以在行首  : 以冒号結束的是标号  . 點号表示目前指令的位址  立即數前面加#或者$,表示這是個立即數 常見的gnu彙編僞指令

僞指令 意義
.globl _start 給_start外部連結屬性
.section .text 指定目前為代碼段
.ascii .byte .short .long .word .quad .float .string 定義資料
.align 4 以16(2^4)位元組記憶體位址對齊
.balignl 16,0xABCDEF 16位元組對齊填充
.equ 類似于C中的宏定義
.end 彙編檔案的結束,不加無所謂
.include 頭檔案包含
.arm或者.code32 聲明以下的代碼為arm指令不是thumb指令
.thumb或者.code16 聲明以下的代碼為thumb指令
ldr 大範圍的位址加載指令
adr 小範圍的位址加載指令
adrl 中等範圍的位址加載指令
nop 空操作
  • AAAA:.word 0xAABBFF 類似于C語言的 int AAAA = 0xAABBFF;
  • .balignl 16, 0xABCDEF 對齊+填充,b表示位填充,最後的l表示long,16表示16位元組對齊,0xABCDEF表示填充的原料。 
  • 0x00000008 : .balignl 16, 0xABCDEF,
  • 0x0000000C: 0xABCDEF
  • 0x00000010: 下一條指令
  • ARM中有一個ldr指令,還有一個ldr僞指令。兩者的差別: 

ldr r0, #0xFF @ldr指令  ldr r0, =0xFF @ldr僞指令 涉及到合法/非法立即數,還涉及到ARM文字池 adr 和 ldr的差别:  - adr編譯時會被1條sub或add指令替代,而ldr編譯時會被一條mov指令替代或者文字池方式處理;  - adr總是以PC為基準來表示位址,是以指令本身和運作位址有關,可以用來檢測程式目前的運作位址在哪裡  -ldr加載的位址和連結時給定的位址有關,由連結腳本決定。

繼續閱讀