第一節 可編程器件的編程原理 1. 可編程器件的特點 1 . CPU在固定頻率的時鐘控制下節奏運行 2 . CPU可以通過匯流排讀取外部存儲設備中的二進位指令集,然後解碼執行 3 . 這些可以被CPU解碼執行的二進位指令集是CPU設計的時候確定的,是CPU的設計者(ARM公司)定義的,本質上是一串由1 ...
第一節 可編程器件的編程原理
1. 可編程器件的特點
- 1 . CPU在固定頻率的時鐘控制下節奏運行
- 2 . CPU可以通過匯流排讀取外部存儲設備中的二進位指令集,然後解碼執行
- 3 . 這些可以被CPU解碼執行的二進位指令集是CPU設計的時候確定的,是CPU的設計者(ARM公司)定義的,本質上是一串由1和0組成的數字。這就是CPU的彙編指令集
2. 從源代碼到cpu執行過程
第二節 指令集對cpu的意義
1. 彙編語言與C等高級語言的差異
- 彙編無移植性,c語言有一定可移植性,jave等更高級的語言移植性更強
- 彙編語言效率最高,C次之,jave等更高級語言效率更低
- 彙編不適合完成大型複雜的項目,更高級語言更適合完成更大,更複雜的項目
2. 彙編語言的本質
- 彙編的實質是機器指令(機器碼)的助記符,是一種低級符號語言
- 機器指令集是一款CPU的編程特征,是這款CPU的設計者制定的。CPU的內部電路設計就是為了實現這些指令集的功能。機器指令集就好像CPU的API介面一樣
- 彙編器的工作是把助記符(如MOV類似人的姓名)翻譯成(101001類似身份證號碼)
3. 彙編語言的發展過程
- 純機器碼編碼
- 彙編語言編程
- c語言編程
- c++語言編程
- jave,c#等語言編程
- 腳本語言編程
4. 總結
- 彙編語言就是CPU的機器指令集的助記符,是一款CPU的本質特征
- 不同CPU的機器指令集設計不同,因此彙編程式不能在不同CPU之間相互移植
- 使用彙編編程可以充分發揮CPU的設計特點,所以彙編編程效率最高,因此在操作系統內核中效率極其重要處都需要用彙編處理
第三節 RISC和CISC的區別
1. CISC
complex instruction set computer複雜指令集CPU
CISC體系的設計理念是用最少的指令來完成任務(譬如計算乘法只需要一條MUL指令即可),因此CISC的CPU本身設計複雜,工藝複雜,但好處是編譯器好設計。CISC出現較早,至今Intel還一直採用CISC設計
2. RISC
Reduced Instruction Set computer精簡指令集CPU
RISC的設計理念是讓軟體來完成具體的任務,CPU本身僅提供基本功能指令集。因此RISC CPU的指令集中只有很少的指令,這種設計相對於CISC,CPU的設計和工藝簡單了,但是編譯器的設計變難了
3.CPU設計方式發展
早期簡單CPU,指令和功能都很有限
CISC時代--CPU功能擴展依賴於指令集的擴展,實質是CPU內部組合邏輯電路的擴展
RISC年代--CPU僅提供基礎功能指令(譬如記憶體與寄存器通信指令,基本運算與判斷指令等),功能擴展由使用CPU的人利用基礎構架來靈活實現
4.RISC與CISC指令數對比
一般典型CISC CPU指令在300條左右
ARM CPU常用指令30條左右
5.發展趨勢
沒有純粹的RISC或CISC,發展方向是RISC和CISC結合,形成一種介於2者之間的CPU類型
第四節 統一編址&獨立編址&哈佛結構&馮諾伊曼結構
1. 統一編址&獨立編址
什麼是IO?什麼是記憶體?
記憶體就是程式的運行場所,記憶體和CPU之間通過匯流排連接,CPU通過一定的地址來訪問具體記憶體單元
IO(input and output)是輸入輸出介面,是CPU和其他外部設備(如串口,LCD,觸摸屏,LED等)之間通信的道路。一般的,IO就是只CPU的各種內部和外部外設
記憶體的訪問方式
記憶體通過CPU的數據匯流排來定址定位,然後通過CPU數據匯流排來讀寫
CPU的地址匯流排的位數是CPU設計時確定的,因此一款CPU所能定址的範圍是一定的,而記憶體是需要占用CPU的定址空間
記憶體與CPU的這種匯流排式連接方式是一種直接連接,優點是效率高訪問塊,缺點是資源有限,擴展性差
IO的訪問方式(通過訪問寄存器來操作IO)
IO指的是與CPU連接的各種外設
CPU訪問各種外設有2種方式,一種是類似於訪問記憶體的方式,即把外設的寄存器當做一個記憶體地址來讀寫,從而以訪問記憶體相同的方式來操作外設,叫IO與記憶體統一編址方式(RISC,如ARM);另一種是使用專用的CPU指令來訪問某種特定外設,叫IO與記憶體獨立編址(CISC)
記憶體與IO訪問方式的對比
由於記憶體訪問頻率高,因此採用匯流排式連接,直接地址訪問,效率最高
IO與記憶體統一編址方式,優勢是IO當做記憶體來訪問,編程簡單;缺點是IO也需要占用一定的CPU地址空間,而CPU的地址空間是有限資源
IO與記憶體獨立編址方式,優勢是不占用CPU地址空間;缺點是CPU設計變複雜了
2. 馮諾伊曼結構與哈佛結構
程式和數據
程式運行是兩大核心元素:程式代碼+數據
程式是我們寫好的源代碼經過編譯,彙編之後得到的機器碼,這些機器碼可以拿給CPU去解碼執行,CPU不會去修改程式,所以程式是只讀的
數據是程式運行過程中定義和產生的變數的值,是可以讀寫的,程式運行實際就是為了改寫數據的值
什麼是馮諾伊曼結構?什麼是哈佛結構?
程式和數據都放在記憶體中,且不彼此分離的結構稱為馮諾伊曼結構,譬如Intel的CPU均採用馮諾伊曼結構
程式和記憶體分開獨立放在不同的記憶體塊中,彼此完全分離的結構稱為哈佛結構。譬如大部分單片機(MCS51,ARM9等)均採用哈佛結構
馮諾伊曼結構與哈佛結構對比
馮諾伊曼結構中程式和數據不區分的放在一起,因此安全域穩定性(病毒)是個問題,好處是處理器來簡單
哈佛結構中程式(一般放在ROM,flash中)和數據(一般放在RAM中)獨立分開存放,因此好處是安全和穩定性高,缺點是軟體處理複雜一些(需要統一規劃鏈接地址等)
第五節 軟體編程式控制制硬體的關鍵---寄存器
1. 什麼是寄存器
- 寄存器屬於CPU外設的硬體組成部分
- CPU可以像訪問記憶體一樣訪問寄存器
- 寄存器是CPU的硬體設計者制定的,目的是留作外設被編程的"活動開關"
- 正如彙編指令集是CPU的編程介面API一樣,寄存器是外設硬體的軟體編程介面API。使用軟體編程式控制制某一硬體,其實就是編程讀寫該硬體的寄存器
- 編程操作寄存器類似於訪問記憶體
- 寄存器總每個bit位都有特定含義,因此編程操作需要位操作
- 單個寄存器的位寬一般和CPU的位寬一樣,以實現最佳訪問效率
2. 兩類寄存器
- SoC中有2類寄存器:通用寄存器(和CPU綁定)和SFR(功能已經在設計CPU時就已經確定好了,不能再改變,已經事先和某個外設綁定好了)
- 通用寄存器(ARM中有37個)是CPU的組成部分,CPU的很多活動都需要通用寄存器的支持和參與
- SFR(special function register特殊功能寄存器)不在CPU中,而存在於CPU的外設中,我們通過訪問外設的SFR來編程操控這個外設,這就是硬體編程式控制控制的方法
第六節 ARM體繫結構總結
1. ARM是RISC架構
[ ] 常用的ARM彙編指令只有二三十條
[ ] ARM是低功耗CPU
[ ] ARM的架構非常適合單片機,嵌入式,尤其是物聯網領域;而伺服器等高校性能領域目前主導還是Intel
2. ARM是統一編址的(IO與記憶體)
[ ] 大部分ARM(M3 M4 M7 M0 ARM9 ARM11 A8 A9等)都是32位架構
[ ] 32位ARM CPU支持的記憶體少於4G,通過CPU地址匯流排來訪問
[ ] SoC中的各種內部外設通過各自的SFR編程訪問,這些SFR的訪問方式類似於訪問普通記憶體,這叫IO與記憶體統一編址
3. ARM是哈佛結構的
常見的ARM(ARM7除外(已淘汰))都是哈佛結構的
哈佛結構保證了ARM CPU運行的穩定性和安全性,因此ARM適用於嵌入式領域
哈佛結構也決定了ARM裸機程式(使用實地址即物理地址的地址叫裸機程式)的鏈接比較麻煩,必須使用複雜的鏈接腳本告知鏈接器如何組織程式;對於OS之上的應用(工作在虛擬地址之中)則不需考慮這麼多
第七節 S5PV210的地址映射詳解
1. 什麼是地址映射(一般叫記憶體映射)
S5PV210屬於ARM Cortex-A8架構,32位CPU,CPU設計時就有32根地址線&32根數據線
32根地址線決定了CPU的地址空間為4G,那麼這4G空間如何分配使用?這個問題就是地址映射問題(硬編碼,不能修改)
2. 一些專用術語
- ROM:read only memory 只讀存儲器(不能直接通過地址匯流排和數據匯流排寫)
- RAM:ramdom access memory 隨機訪問存儲器
- IROM:internal rom 內部ROM,指的是集成到SoC內部的ROM(記憶體條有兩個IROM&IRAM,目的是映射和轉換。底下是上面的映射,很靈活)
- IRAM:internal ram 內部RAM,指的是集成到SoC內部的RAM
- DRAM:dynamic ram 動態RAM(外部接的記憶體就是平時我們插入的記憶體條)
- SRAM:static ram 靜態RAM,容量小,價格高,優點是不需要軟體初始化直接上電就能用
- SROM:接網卡
第八節 CPU和外部存儲器的介面
1.記憶體與外存的區別
記憶體就是內部存儲器,是用來運行程式的,即RAMDRAM,SRAM,DDR),通過地址匯流排訪問
外存就是外部存儲器,是用來存儲東西的,即ROM(硬碟,flash(Nand,iNand...U盤,SSD),光碟)
CPU連接記憶體和外存的連接方式不同。記憶體需要直接地址訪問,所以是通過地址匯流排和數據匯流排的匯流排式訪問方式連接到(好處是直接訪問,隨機訪問;壞處是占用CPU的地址空間,大小受限);外存是通過CPU的外存介面來連接到(好處是不占用CPU的地址空間,壞處是訪問速度沒有匯流排式快,訪問時序較複雜)
2. SoC常用外部存儲器
Flash類(電子式)
- NorFlash(匯流排式訪問,接到SROMC Bank,優點是可以直接匯流排訪問,一般用來啟動,太貴,已很少使用,但很可靠)
- NandFlash(分為SLC和MLC,已漸漸淘汰)
- eMMC/iNand/moviNand(iNand是SanDisk公司出廠的eMMC,moviNand是三星出廠的eMMC)
- oneNAND(oneNand是三星出的一種Nand,只有三星使用)
- eSSD(e即embeded嵌入式)
- SD卡/TF卡/MMC卡
硬碟類
SATA硬碟(機械式訪問,磁存儲原理,SATA是介面)
3. X210開發板支持的外部存儲器
X210有2個版本,Nand版和iNand版,分別使用NandFlash和iNand位外部存儲器。我們使用的是iNand版本,板載4GBiNand
S5PV210共支持4個SD/MMC通道,其中通道0和2依次用作啟動。X210開發板中SD/MMC0通道用於連接板載MMC,因此外部啟動時SD/MMC2通道(註意通道3不能啟動)
第九節 S5PV210的啟動過程詳解
1. S5PV210 的啟動過程
第一步:CPU上電後先從內部iROM中讀取預先設置的代碼,執行。這一段iROM代碼做了一些基本的初始化(CPU時鐘,關看門狗...)(這一段iROM代碼是三星出廠前設置的,三星不知道我們板子上將來接的是什麼樣的DRAM,因此這一段iROM是不能負責初始化外接的DRAM,因此這一段代碼只能初始化SoC內部的東西);然後這一段代碼會判斷我們選擇的啟動模式(我們通過硬體跳線可以更改板子的啟動模式),然後從相應的外部存儲器去讀取第一部分啟動代碼(BL1,大小為16KB)到內部SRAM
第二步:從SRAM去運行上一步讀取來的BL1(16KB),然後執行。BL1負責初始化NandFlash,然後將BL2讀取到iRAM(80KB).
第三步:從iRAM運行BL2,BL2初始化DRAM,然後將OS讀取到DRAM中,然後啟動OS,啟動過程結束
思路:因為啟動代碼的大小是不定的,所以兩步啟動不合適
三星的解決方案是:把啟動代碼分為2半(BL1和BL2),這兩部分協同工作來完成啟動
2. BL0(iROM)做了什麼
- 關看門狗
- 初始化指令cache
- 初始化棧
- 初始化堆
- 初始化塊設備複製函數device copy function
- 設置SoC時鐘系統
- 複製BL1到內部的iRAM(16KB)
- 檢查BL1的校驗和
- 跳轉到BL1去執行
3. S5PV210的所有啟動
- 先1st,通過OMpin選擇啟動介質
- 再2nd啟動,從SD2
- 再Uart啟動
- 再USB啟動
4. 其他
記憶體:
SRAM:靜態記憶體,特點是容量小,價格高,優點是不需要軟體初始化直接上電就能用 DRAM:動態記憶體,特點是容量大,價格低,缺點是上電後不能直接使用,需要軟體初始化後才可以使用
單片機中:記憶體需求量小,而且希望開發儘量簡單,適合全部用SRAM
嵌入式系統:記憶體需求量大,而且沒有NorFlash等可啟動介質
PC機中:記憶體需求量大,而且軟體複雜,不在乎DRAM的初始化開銷,適合全部用DRAM
2 . 外存:
NorFlash:特點是容量小,價格低,優點是可以和CPU直接匯流排式相連,CPU上電後可以直接讀取,所以一般用啟動介質
NandFlash(跟硬碟一樣):特點是容量大,價格低,缺點是不能匯流排式訪問,也就是說不能上電CPU直接讀取,需要CPU先運行一些初始化軟體,然後通過時序介面讀寫
所以一般PC機都是:很少容量的BIOS(NorFlash) + 很大容量的硬碟(類似NandFlash) + 大容量的DRAM
一般的單片機:很少容量的NorFlash + 很少容量的SRAM
嵌入式系統:因為NorFlash很貴,現在很多嵌入式系統傾向於不同NorFlash,直接用:外接的大容量Nand + 外接大容量DRAM + SoC內置SRAM
3 . S5PV210啟動方式是:外接的大容量Nand + 外接大容量DRAM + SoC內置SRAM
實際上,210內置了一塊96KB的SRAM(叫iRAM),同時還有一塊內置的64KB大小的NorFlash
第十節 如何在開發板上選擇不同的啟動方式
體驗從SD0的eMMC啟動
開發板預設從eMMC啟動,內部預先燒錄了Android從SD2啟動
可以使用外置SD卡從SD2通道啟動,但這需要先破壞板載的eMMC中的android鏡像。破壞方法見《X210V3開發板立即教程》2.5.2節USB調試模式
第十一節 ARM的編程模式和7種工作模式
1. ARM的基本設定
- ARM採用的是32位架構
ARM約定:
Byte: 8 bits Halfword:16 bits (2 byte) Word: 32 bits (4 byte)
大部分ARM core提供
ARM指令集(32 bit) Thumb指令集(16 bit) Thumb2指令集(16 & 32 bit)
4.Jazelle cores 支持 jave bytecode
2. ARM處理器工作模式
ARM處理器共有7種基本工作模式
用戶模式 User:非特權模式,大部分任務執行在這種模式 異常模式 FIQ:當一個高優先順序(fast)中斷產生時將會進入這種模式 IRQ:當一個低優先順序(normal)中斷產生是將會進入這種模式 Supervisor(管理模式):當複位或軟中斷指令執行時將會進入這種模式 Abort:當存取異常時將會進入這種模式 Undef:當執行未定義指令時將會進入這種模式 系統模式 System:使用和User模式相同寄存器集的特權模式
註意:
- 除User(用戶模式)是Normal(普通模式)外,其他6種都是Privilege(特權模式)
- Privilege中除sys模式外,其餘5種為異常模式
- 各種模式的切換,可以是程式員通過代碼主動切換(通過寫CPSP寄存器);也可以是CPU在某些情況下自動切換
- 各種模式下許可權和可以訪問的寄存器不同
2. CPU為什麼設計這些模式
- CPU是硬體,OS是軟體,軟體的設計要依賴硬體的特性,硬體的設計要考慮軟體需要,便於實現軟體特性
- 操作系統有安全級別要求,因此CPU設計多種模式是為了方便操作系統的多種角色安全等級需要
第十二節 ARM的37個寄存器(不是SFG)詳解
1. 概述
ARM總共有37個寄存器,但是每種模式下最多只能看到18個寄存器,其他寄存器雖然名字相同但是在當前模式下不可見。
37個寄存器中30個為"通用”型,1個固定用作PC,一個固定用作CPSR,5個固定用作5中異常模式下的SPSR
對r14這個名字來說,在ARM中共有6個名叫r14(又叫sp)的寄存器,但是在每種特定處理器模式下,只有一個r14是當前可見的,其他的r14必須切換到它的對應模式下才能看到。這種設計叫影子寄存器(banked register)
2. CPSR程式狀態寄存器
Mode位(0 - 4)
處理器模式位
T Bit(5)
僅ARM xT架構支持 T = 0:處理器處於ARM狀態 T = 1:處理器處於Thumb狀態
中斷禁止位(6 - 7)
I = 1:禁止IRQ F = 1:禁止FIQ
J位(24)
僅ARM 5TE/J架構支持 J = 1:處理器處於Jazelle狀態
Q位(27)
僅ARM 5TE/J架構支持 指示飽和狀態
條件位(28 - 31)
N = Negative result from ALU Z = Zero result from ALU C = ALU operation Carried out V = ALU operation overflowed
3. PC(r15)程式控制寄存器
- PC(Program control register)為程式指針,PC指向哪裡,CPU就會執行哪條指令(所以程式跳轉是就是把目標地址代碼放到PC中)
- 整個CPU中只有一個PC(CPSR也只有一個,但SPSR有5個)
第十二節 ARM的異常處理方式簡單介紹
1. 什麼是異常
正常工作之外的流程都叫異常
異常會打斷正在執行的工作,並且一般我慢希望異常處理完成後繼續回來執行原來的工作
中斷是異常的一種
2. 異常向量表
所有的CPU都有異常向量表,這是CPU設計時就設定好的,是硬體決定的
當異常發生時,CPU會自動動作(PC跳轉到宜昌向量處處理異常,有時伴有一些輔助動作)
異常向量表是應將想軟體提供的處理異常的支持
3. ARM的異常處理機制
當異常產生時
拷貝CPSR到SPSR_<mode> 設置適當的CPSR位: 改變處理器狀態進入ARM態 改變處理器模式進入相應的異常模式 設置中斷禁止位禁止相應中斷 保存返回地址到LR_<mode> 設置PC為相應的異常向量
返回時,異常處理需要
從SPSR_<mode>恢復CPSR 從LR_<mode>恢復PC Note:這些操作只能在ARM態執行
第十三節 ARM的彙編指令集
1. 指令與偽指令的概念
(彙編)指令是CPU機器指令的助記符,經過編譯後會得到一串10組成的機器碼,可以由CPU讀取執行
(彙編)偽指令本質上不是指令(只是和指令一起寫在代碼中),他是編譯器環境提供的,目的是用來指導編譯過程,經過編譯後偽指令最終不會生成機器碼
2. 兩種不同風格的ARM指令
ARM官方的ARM彙編風格:指令一般用大寫,Windows中IDE開發環境(如ADS,MDK等)常用。如:LDR R0,[R1]
GNU風格的ARM彙編:指令一般用小寫字母,linux中常用。如ldr r0,[r1]
3. ARM彙編的特點
LDR/STR架構
ARM採用RISC架構,CPU本身不能直接讀取記憶體,而需要先講記憶體中的內容載入入CPU中通用寄存器中才能被CPU處理
ldr(load register)指令將記憶體內容載入入通用寄存器
str(store register)指令將寄存器內容存入記憶體空間中
ldr/str組合用來實現ARM CPU和記憶體數據交換
8種定址方式
> * 寄存器定址 mov r1,r2
> * 立即定址 mov r0,#0xFF00
> * 寄存器移位定址 mov r0,r1,lsl #3
> * 寄存器間接定址 ldr r1,[r2]
> * 基址變址定址 ldr r1,[r2,#4]
> * 多寄存器定址 ldmia r1!,{r2-r7,r12}
> * 堆棧定址 stmfd sp!,{r2-r7,lr}
> * 相對定址 beq flag
指令尾碼
同一指令經常附帶不同尾碼,變成不同的指令。經常使用的尾碼有
> * B(Byte) 功能不變,操作長度變為8位
> * H(Half word) 功能不變,長度變為16位
> * S(Signed) 功能不變,操作數變為有符號
> * 如ldr ldrb ldrh ldrsb ldrsh
> * S(S標誌) 功能不變,影響CPSR標誌位
> * 如mov movs
條件執行尾碼
條件尾碼是否成立,不是取決於本句代碼,而是取決於這句代碼之前的代碼運行後的結果
條件尾碼決定了本句代碼是否被執行,而不會影響上一句和下一句代碼是否被執行
moveq r0,r1 @類似於c語言中的if (eq) {r0= r1;}
操作碼 | 條件碼助記符 | 標誌 | 含義 |
---|---|---|---|
0000 | EQ | Z = 1 | 相等 |
0001 | NE | Z = 0 | 不相等 |
0010 | CS/HS | C = 1 | 無符號數大於或等於 |
0011 | CC/LO | C = 0 | 無符號數小於 |
0100 | MI | N = 1 | 負數 |
0101 | Pl | N = 0 | 正數或零 |
0110 | VS | V = 1 | 溢出 |
0111 | VC | V = 0 | 沒有溢出 |
1000 | HI | C = 1,Z = 0 | 無符號數大於 |
1001 | LS | C = 0,Z = 1 | 無符號數小於或等於 |
1010 | GE | N = V | 有符號數大於或等於 |
1011 | LT | N != V | 有符號數小於 |
1100 | GT | Z = 0,N = V | 有符號數大於 |
1101 | LE | Z = 1,N != V | 有符號數小於或等於 |
1110 | AL | 任意 | 無條件執行(指令預設條件) |
1111 | NV | 任意 | 從不執行(不要使用) |
多級指令流水線
為了增加處理器指令流的速度,ARM使用多級流水線, S5PV210使用13級流水線,ARM11為8級
允許多個操作同時處理,而非順序執行
PC指向正被取值的指令,而非正在指向的指令
4. 常用的ARM指令
數據處理指令
數據傳輸指令 mov mvn
算術指令 add sub rsb adc sbc rsc
邏輯指令 and orr eor bic
比較指令 cmp cmn tst teq
乘法指令 mvl mla umull umlal smull smlal
前導零計數 clz
註意
1 . mvn和mov用法一樣,區別是mov是原封不動的傳遞,而mvn是按位取反後傳遞
mov r1,r2 @兩個寄存器之間數據傳遞
mov r1,#0 @將立即數傳給寄存器
2 . and orr(邏輯或) eor(邏輯異或) bic(位清除指令)
bic r0,r0,#0x1f @將r0中的數的bit0到bit4清零後賦值給r0 0x1f = 0x0000 001f = 0x0000 ```` 11111
3 . 比較指令用來不叫2個寄存器中的數
cmp r0,r1 @比較r0,r1的數是否相等
cmn r0,r1 @讓r0和r1中的數相加
tst r0,#0xf @測試r0的bit0-bit3是否相等
註意:比較指令不用後加s尾碼就可以影響spcr中的標誌位
4 . sub r2,r0,r1 (r2 = r0 -r1)
cpsr訪問指令
CPSR寄存器比較特殊,需要專門的指令訪問,這就是mrs和msr
mrs & msr(更強)
mrs用來讀psr,msr用來寫psr
註意cpsr和spsr的區別和聯繫:
cpsr是程式狀態寄存器,整個SoC中只有1個;而spsr有5個,分別在5中異常模式下,作用是當從普通模式進入一場模式時,用來保存之前普通模式下的cpsr,以在返回普通模式時恢複原來的cpsr
跳轉(分支)指令
b & bl & bx
b 直接跳轉
bl branch and link,跳轉前把返回地址放入lr中,以便返回,以便於函數調用
bx 跳轉同時切換到ARM模式,一般用於異常處理的跳轉(現在已經不用)
訪存指令
ldr/str & ldm/stm &swp
單個字/半字/位元組訪問ldr/str
多字批量訪問 ldm/stm
swp r1,r2,[r0] @記憶體與寄存器交換內容
swp r1,r1,[r0]
軟中斷指令
swi(software interrupt)
軟中斷指令用來實現操作系統中系統調用
5. ARM彙編中的立即數(標誌符號#)
合法立即數和非法立即數
ARM指令都是32位,除了指令標記和操作標記外,本身只能附帶很少位數的立即數。因此立即數有合法與非法之分
合法立即數:經過任意位數的移位後非零部分可以用8位表示的幾位合法立即數
合法:0xf000 000f,0x00ff 0000
6. ARM的協處理器指令
什麼是協處理器
SoC內部另一處理核心,協助主CPU實現某些功能,被主CPU調用執行一定任務
ARM設計上支持多達16個協處理器,但是一般SoC只實現其中的CP15(coprocessor)
協處理器和MMU,cache,TLB等處理有關,功能上和操作系統1的虛擬地址映射,cache管理等有關
協處理器cp15操作指令
mcr & mrc
mrc用於讀取cp15中的寄存器
mcr用於寫入cp15中的寄存器
MRC & MCR的使用方法
- [ ] mcr{
- [ ] opcode_1:對於cp15永遠為0
- [ ] Rd:ARM的普通寄存器
- [ ] Crn:cp15的寄存器,合法值是c0-c15
- [ ] Crm:cp15的寄存器,一般均設為c0
- [ ] opcode_2:一般省略或為0
7.ARM的ldm/stm與棧處理
為什麼需要多寄存器訪問指令
- ldr/str每周期只能訪問4位元組記憶體,如果需要批量讀取,寫入記憶體時太慢,解決方案是ldm/stm
- ldm/stm:load register multiple/store register multiple
舉例(uboot的start.S 537行)
stmia sp,{r0-r12} @將r0存入sp指向的記憶體處(假設為0x3000 1000);然後地址+4(即指向0x3000 1004),將r1存入該地址;然後地址再+4(指向0x3000 1008),將r2存入該地址.....直到r12內容放入(0x300 1030),指令完成 一個存訪周期同時完成13個寄存器的讀寫 (r0-r12寄存器,sp寄存器里放了一個記憶體)
8種尾碼
- ia(increase after)先傳輸,再地址+4
- ib(increase brfore)先地址+4,再傳輸
- da(decrease after)先傳輸,再地址-4
- db
- fd(full decrease)滿遞減堆棧
- ed(empty decrease)空遞減堆棧
- fa 滿遞增堆棧
- ea 空遞增堆棧
4種棧
- 空棧:棧指針指向空位,每次存入時可以直接存入然後棧指針移動一格;而取出時需要先移動一格才能取出
- 滿棧:棧指針指向棧中最後一個數據,每次存入時需要先移動棧指針一格再存入
- 增棧:棧指針移動時向地址增加的方向移動的棧
- 減棧:棧指針移動時向地址減少的方向移動的棧
!的作用
ldmia r0,{r2 - r3}
ldmia r0 !,{r2 - r3}
!作用是r0的值在ldm過程中發生的增加或者減少最後寫回r0的值
^的作用
ldmfd sp!,{r0 - r6,pc}
ldmfd sp!,{r0 - r6,pc}^
^的作用:在目標寄存器中有PC時,會同時將spsr寫入到cpsr,一般用於從異常模式返回
8. 總結
操作棧時使用相同的尾碼就不會出錯
批量讀取或寫入記憶體時要用ldm/stm指令
常用stmfd和stmia
第十四節 ARM彙編偽指令
1. 偽指令的意義
- 偽指令不是指令,偽指令和指令的根本區別是經過編譯後會不會生成機器碼
- 偽指令的意義在於指導編譯過程
- 偽指令是和具體的編譯器相關的,我們使用gnu工具鏈,因此學習gnu環境下的彙編偽指令
2. gnu彙編中的一些符號
- [ ] @用來做註釋。可以在行首也可以在代碼後面同一行直接跟,和c語言中的//類似
- [ ] # 做註釋,一般放在行首,表示這一行都是註釋而不是代碼
- [ ] :以冒號結尾的是標號
- [ ] .點號在gnu彙編中表示當前指令的地址
- [ ] #立即數前面要加#或$,表示這個數是立即數
3. 常用gnu偽指令
- [x] .global_start @給_start外部鏈接屬性
- [x] .section.text @指定當前段為代碼段
- [x] .ascii.byte.short.long.word @定義變數(數據類型)
- [x] .quad.float.string @定義數據(與上一致·不常用)
- [x] .align 4 @以16位元組對齊(2^4)
- [x] .balignl 16 0xabcdefgh @16位元組對齊填充(b表示位填充;align表示對齊;l表示long,以4位元組為單位填充;16表示16位元組對齊,0xabcdefgh是用來填充的原料)
- [x] .equ @類似c語言中的巨集定義
4. 偶爾會用到的gnu偽指令
- [ ] .end @標誌文件結束
- [ ] .include @頭文件包含
- [ ] .arm/.code32 @聲明以下為arm指令
- [ ] .thumb/.code16 @聲明以下為thubm指令
5. 最重要的幾個偽指令
- [x] ldr @大範圍的地址載入指令
- [x] adr @小範圍的地址載入指令
- [x] adrl @中等範圍的地址載入指令
- [x] nop @空操作
ARM中有一個ldr指令,還有一個ldr偽指令
ldr指令:ldr r0,#0xff
ldr偽指令:ldr r0,=0xfff1
@涉及到合法/非法立即數,涉及到ARM文字池
一般都使用ldr偽指令而不用ldr指令
adr和ldr的區別
- adr編譯時會被一條sub或add指令替代,而ldr編譯時會被一條mov指令替代或者文字池的方式處理
- adr總是以PC為基準來表示地址,因此指令本身和運行地址有關,可以用來檢測程式當前的運行地址在哪裡
- ldr載入的地址和連接式給定的地址有關,由鏈接腳本決定
adr和ldr的差別:ldr載入的地址在連接時確定,而adr載入的地址在運行是確定;所以我們可以通過adr和lar載入的地址比較來判斷當前程式是否在鏈接時指定的地址運行(重定位)
註:參考朱老師物聯網大講堂