ldm/stm與棧的處理工具
1.爲何須要多寄存器訪問指令?學習
ldr/str每週期只能訪問4字節內存,若是須要批量讀取、寫入內存時太慢,解決方案是 stm/ldm指針
ldm(load register mutiple)code
stm(store register mutipleip
舉例:stmia sp, {r0 - r12}內存
將r0存入sp指向的內存處(假設爲0x30001000);而後地址+4(即指向0x30001004), 將r1存入該地址;而後地址再+4(指向0x30001008),將r2存入該地址······直 到r12內容放入(0x3001030),指令完成。ci
一個訪存週期同時完成13個寄存器的讀寫編譯器
1.1 8種後綴string
(1)ia(increase after)先傳輸,再地址+4io
(2)ib(increase before)先地址+4,再傳輸
(3)da(decrease after)先傳輸,再地址-4
(4)db(decrease before)先地址-4,再傳輸
(5)fd(full decrease)滿遞減堆棧
(6)ed(empty decrease)空遞減堆棧
(7)fa 滿遞增堆棧
(8)ea空遞增堆棧
1.2 四種棧
(1)空棧:棧指針指向空位,每次存入時能夠直接存入而後棧指針移動一格;而取出 時須要先移動一格才能取出
(2)滿棧:棧指針指向棧中最後一格數據,每次存入時須要先移動棧指針一格再存入; 取出時能夠直接取出,而後再移動棧指針
(3)增棧:棧指針移動時向地址增長的方向移動的棧
(4)減棧:棧指針移動時向地址減少的方向移動的棧
1.3 !的做用
ldmia r0, {r2 - r3}
ldmia r0!, {r2 - r3}
感嘆號的做用就是r0的值在ldm過程當中發生的增長或者減小最後寫回到r0去,也就是 說ldm時會改變r0的值。
1.4 ^的做用
ldmfd sp!, {r0 - r6, pc}
ldmfd sp!, {r0 - r6, pc}^
^的做用:在目標寄存器中有pc時,會同時將spsr寫入到cpsr,通常用於從異常 模式返回。
謹記:操做棧時使用相同的後綴就不會出錯,無論是滿棧仍是空棧、增棧仍是減棧
ARM彙編僞指令
2.1僞指令的意義
(1)僞指令不是指令,僞指令和指令的根本區別是通過編譯後會不會生成機器碼。
(2)僞指令的意義在於指導編譯過程。
(3)僞指令是和具體的編譯器相關的,咱們使用gnu工具鏈,所以學習gnu環境下的 彙編僞指令。
2.2gnu彙編中的一些符號
(1)@ 用來作註釋。能夠在行首也能夠在代碼後面同一行直接跟,和C語言中//相似
(2)# 作註釋,通常放在行首,表示這一行都是註釋而不是代碼。
(3):以冒號結尾的是標號
(4). 點號在gnu彙編中表示當前指令的地址
(5)# 當即數前面要加#或$,表示這是個當即數
2.3經常使用gnu僞指令
.global _start 給_start外部連接屬性
.section .text 指定當前段爲代碼段
.ascii .byte .short .long .word
.quad .float .string 定義數據
.align 4 以16字節對齊
.balignl 16 0xabcdefgh @ 16字節對齊填充
.equ 相似於C中宏定義
列:_bss_start:
.word _bss_start
int _bss_start;
IRQ_STACK_START:
.word 0x0badc0de
等價於 unsigned int IRQ_STACK_START = 0x0badc0de;
.align 4 @ 16字節對齊
.align 2 @ 4字節對齊
2.4偶爾會用到的gnu僞指令
.end @標識文件結束
.include @ 頭文件包含
.arm / .code32 @聲明如下爲arm指令
.thumb / .code16 @聲明如下爲thubm指令
2.5最重要的幾個僞指令
ldr 大範圍的地址加載指令
adr 小範圍的地址加載指令
adrl 中等範圍的地址加載指令
nop 空操做
ARM中有一個ldr指令,還有一個ldr僞指令
通常都使用ldr僞指令而不用ldr指令
2.6 adr與ldr
adr編譯時會被1條sub或add指令替代,而ldr編譯時會被一條mov指令替代或者文 字池方式處理;
adr老是以PC爲基準來表示地址,所以指令自己和運行地址有關,能夠用來檢測程序 當前的運行地址在哪裏
ldr加載的地址和連接時給定的地址有關,由連接腳本決定。