朱老師ARM裸機學習筆記(六):ARM彙編

彙編指令和僞彙編指令

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

ARM彙編的特點

ARM彙編的特點1:LDR/STR架構

ARM採用RISC架構,CPU本身不能直接讀取內存(CISC結構的可以直接讀取內存),而需要先將內存中內容載入CPU中通用寄存器才能被CPU執行。
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:條件執行後綴

這裏寫圖片描述
如果後綴條件滿足才執行。

例如:
mov r0, r1 @r0 = r1
moveq r0,r1 @ if(eq) r0 =r1

條件後綴執行注意:條件後綴是否成立,不是取決於本句代碼,而是取決於這句代碼之前的代碼運行後的結果。

ARM彙編的特點4:多級指令流水線

S5PV210使用13級流水線。PC指向正被取值的指令,而非正在執行的指令。

數據處理指令

數據傳輸指令

mov (move)

mov r1, r0    @兩個寄存器之間數據傳遞  r1 = r0
mov 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內容存入內存。

棧類型

空棧:棧指針指向空位,每次存入數據後,sp+4
滿棧:棧指針指向滿位,每次存入數據時,先sp+4然後再存入數據
增棧:棧指針移動時向地址增加的方向移動
減棧:棧指針移動時向地址減小的方向移動
因此有四種棧類型:空增棧,空減棧,滿增棧,滿減棧。

八種後綴

後綴 意義
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加載的地址和鏈接時給定的地址有關,由鏈接腳本決定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章