本書選擇當前嵌入式系統領域里具有代表性的ARM CortexA8處理器和嵌入式Linux操作系統作為分析對象,從嵌入式系統的發展歷史和特點出發,對A8嵌入式處理器的體系結構、存儲系統、中斷系統、ARM指令集和S5PV210微處理器進行詳細介紹。在此基礎上,闡述ARMlinux內核、Linux文件系統、Linux移植及調試方法、驅動程序的設計等內容;選擇Qt圖形界面程序和SQLite數據庫這兩個有代表性的嵌入式應用軟件進行介紹; 介紹傳統嵌入式系統的設計方法和引入了“協同設計”概念的嵌入式系統設計方法,并介紹三個嵌入式系統應用案例以增強讀者的理解。 本書可以作為高等學校計算機、電子、電信類專業的教材,也可以作為嵌入式開發相關人員的參考用書。
(1)以ARM Cortex-A8處理器架構作為系統核心處理器架構,從作者自身從事的科研項目和實踐活動出發,選擇了具有一定實用價值、包含交叉學科知識且反映嵌入式系統與物聯網技術結合的三個項目實例。這些實例不僅從理論上深化拓展嵌入式系統設計方法和理念,也從實踐角度提出“碰到問題如何運用所學知識解決問題”的觀點,促進學生學以致用思想的升華。(2)本書增加Qt和SQLite數據庫相關知識,以滿足日益增長的嵌入式系統UI設計與數據處理需求,更能滿足智能移動平臺開發的需要。(3)本書配套教學課件、習題和源代碼。
目錄
第1章嵌入式系統概述
1.1嵌入式系統簡介
1.1.1嵌入式系統的產生
1.1.2嵌入式系統的定義、特點和分類
1.1.3嵌入式系統的兩種應用模式
1.1.4嵌入式系統的典型組成
1.2嵌入式微處理器
1.2.1嵌入式微處理器簡介
1.2.2主流嵌入式微處理器
1.3嵌入式操作系統
1.3.1嵌入式Linux
1.3.2Windows CE
1.3.3Symbian
1.3.4Android
1.3.5μC/OSⅡ
1.3.6VxWorks
1.4嵌入式系統的應用領域和發展趨勢
1.4.1嵌入式系統的應用領域
1.4.2嵌入式系統的發展趨勢
1.5本章小結
習題
第2章ARM處理器體系結構
2.1ARM處理器概述
2.1.1ARM處理器簡介
2.1.2ARM體系結構發展
2.1.3ARM處理器系列主要產品
2.1.4ARM開發工具簡介
2.2CortexA8處理器架構
2.3CortexA8處理器工作模式和狀態
2.3.1CortexA8處理器工作模式
2.3.2CortexA8處理器狀態
嵌入式系統設計與應用——基于ARM CortexA8和Linux
2.4CortexA8存儲器管理
2.4.1ARM的基本數據類型
2.4.2浮點數據類型
2.4.3大/小端存儲模式
2.4.4寄存器組
2.4.5CortexA8存儲系統
2.5CortexA8異常處理
2.5.1異常向量和優先級
2.5.2異常響應過程
2.5.3異常返回過程
2.5.4CortexA8處理器S5PC100中斷機制
2.6本章小結
習題
第3章ARM指令集
3.1ARM指令集概述
3.1.1指令格式
3.1.2指令的條件碼
3.2ARM指令的尋址方式
3.2.1立即尋址
3.2.2寄存器尋址
3.2.3寄存器間接尋址
3.2.4寄存器移位尋址
3.2.5變址尋址
3.2.6多寄存器尋址
3.2.7相對尋址
3.2.8堆棧尋址
3.2.9塊復制尋址
3.3ARM指令簡介
3.3.1跳轉指令
3.3.2數據處理指令
3.3.3程序狀態寄存器處理指令
3.3.4加載/存儲指令
3.3.5協處理器指令
3.3.6異常產生指令
3.4Thumb指令簡介
3.5ARM匯編語言編程簡介
3.5.1偽操作
3.5.2偽指令
3.5.3匯編語句格式
3.5.4匯編語言的程序結構
3.6C語言與匯編語言的混合編程
3.6.1C程序中內嵌匯編
3.6.2匯編中訪問C語言程序變量
3.6.3ARM中的匯編和C語言相互調用
3.7本章小結
習題
第4章S5PV210微處理器與接口
4.1基于S5PV210微處理器的硬件平臺體系結構
4.1.1S5PV210處理器簡介
4.1.2S5PV210內部各模塊介紹
4.2存儲系統
4.2.1S5PV210的地址空間
4.2.2S5PV210啟動流程
4.3時鐘系統
4.3.1S5PV210時鐘概述
4.3.2S5PV210的時鐘結構
4.4GPIO接口
4.4.1GPIO概述
4.4.2GPIO寄存器
4.4.3GPIO操作步驟
4.4.4一個LED燈的例子
4.5串行通信接口
4.5.1串行通信方式
4.5.2RS232C串行接口
4.5.3S5PV210的異步串行通信
4.5.4S5PV210的UART寄存器
4.5.5UART通信示例
4.6A/D轉換器
4.7本章小結
習題
第5章ARMLinux內核
5.1ARMLinux概述
5.1.1GNU/Linux操作系統的基本體系結構
5.1.2ARMLinux內核版本及特點
5.1.3ARMLinux內核的主要架構及功能
5.1.4Linux內核源碼目錄結構
5.2ARMLinux進程管理
5.2.1進程的表示和切換
5.2.2進程、線程和內核線程
5.2.3進程描述符task_struct的幾個特殊字段
5.2.4do_fork()函數
5.2.5進程的創建
5.2.6線程和內核線程的創建
5.2.7進程的執行——exec函數族
5.2.8進程的終止
5.2.9進程的調度
5.3ARMLinux內存管理
5.3.1ARMLinux內存管理概述
5.3.2ARMLinux虛擬存儲空間及分布
5.3.3進程空間描述
5.3.4物理內存管理
5.3.5基于slab分配器的管理技術
5.3.6內核非連續內存分配(vmalloc)
5.3.7頁面回收簡述
5.4ARM_Linux模塊
5.4.1LKM的編寫和編譯
5.4.2LKM版本差異比較
5.4.3模塊的加載與卸載
5.4.4工具集moduleinittools
5.5ARMLinux中斷管理
5.5.1ARM_Linux中斷的一些基本概念
5.5.2內核異常向量表的初始化
5.5.3Linux中斷處理
5.5.4內核版本2.6.38后的中斷處理系統的一些改變——通用中斷
子系統
5.6ARMLinux系統調用
5.7本章小結
習題
第6章Linux文件系統
6.1Linux文件系統概述
6.2ext2文件系統格式
6.2.1ext2文件系統
6.2.2目錄結構
6.3ext3和ext4文件系統
6.3.1ext3文件系統
6.3.2ex4文件系統
6.4嵌入式文件系統JFFS2
6.4.1嵌入式文件系統
6.4.2JFFS2嵌入式文件系統
6.5YAFFS與YAFFS2文件系統簡介
6.5.1YAFFS文件系統
6.5.2YAFFS2文件系統簡介
6.6根文件系統
6.6.1根文件系統概述
6.6.2根文件系統的制作工具——BusyBox
6.6.3YAFFS2文件系統的創建
6.7本章小結
習題
第7章嵌入式Linux系統移植及調試
7.1BootLoader基本概念與典型結構
7.1.1BootLoader基本概念
7.1.2BootLoader的操作模式
7.1.3BootLoader的典型結構
7.1.4常見的BootLoader
7.2UBoot
7.2.1UBoot概述
7.2.2UBoot啟動的一般流程
7.2.3UBoot環境變量
7.2.4UBoot命令
7.3交叉開發環境的建立
7.4交叉編譯工具鏈
7.4.1交叉編譯工具鏈概述
7.4.2工具鏈的構建方法
7.4.3交叉編譯工具鏈的主要工具
7.4.4Makefile
7.5嵌入式Linux系統移植過程
7.5.1UBoot移植
7.5.2內核的配置、編譯和移植
7.6GDB調試器
7.7遠程調試
7.7.1遠程調試工具的構成
7.7.2通信協議——RSP
7.7.3遠程調試的實現方法及設置
7.7.4遠程調試應用實例方法
7.8內核調試
7.8.1printk()
7.8.2KDB
7.8.3Kprobes
7.8.4KGDB
7.9本章小結
習題
第8章設備驅動程序設計
8.1設備驅動程序開發概述
8.1.1Linux設備驅動程序分類
8.1.2驅動程序的處理過程
8.1.3設備驅動程序框架
8.1.4驅動程序的加載
8.2內核設備模型
8.2.1設備模型功能
8.2.2sysfs
8.2.3sysfs的實現機制kobject
8.2.4設備模型的組織——platform總線
8.3字符設備驅動設計框架
8.3.1字符設備的重要數據結構
8.3.2字符設備驅動框架
8.4GPIO驅動概述
8.4.1gpiolib關鍵數據結構
8.4.2GPIO的申請和注冊
8.5I2C總線驅動設計
8.5.1I2C總線概述
8.5.2I2C驅動程序框架
8.5.3關鍵數據結構
8.5.4I2C核心接口函數
8.5.5I2C設備驅動的通用方法
8.6塊設備驅動程序設計概述
8.6.1塊設備驅動整體框架
8.6.2關鍵數據結構
8.6.3塊設備的請求隊列操作
8.7嵌入式網絡設備驅動設計
8.7.1網絡設備驅動程序框架
8.7.2網絡設備驅動程序關鍵數據結構
8.7.3網絡設備驅動程序設計方法概述
8.8網絡設備驅動程序示例——網卡DM9000驅動程序分析
8.9本章小結
習題
第9章Qt圖形界面應用程序開發基礎
9.1Qt簡介
9.2Qt 5概述
9.2.1Qt 5簡介
9.2.2通過“幫助”菜單了解Qt 5的組成——模塊
9.2.3Linux下Qt開發環境的安裝與集成
9.2.3Qt Creator功能和特性
9.3信號和插槽機制
9.4Qt程序設計
9.4.1helloworld程序
9.4.2多窗口應用程序
9.5Qt數據庫應用
9.5.1數據庫驅動
9.5.2Qt與SQLite數據庫的連接
9.5.3SQL模型
9.6本章小結
習題
第10章SQLite數據庫
10.1SQLite數據庫概述
10.1.1基于Linux平臺的嵌入式數據庫概述
10.1.2SQLite的特點
10.1.3SQLite的體系結構
10.2SQLite安裝
10.3SQLite的常用命令
10.4SQLite的數據類型
10.5SQLite的API函數
10.5.1核心C API函數
10.5.2擴充C API函數
10.6本章小結
習題
第11章嵌入式系統的開發設計案例
11.1嵌入式系統設計方法介紹
11.1.1傳統的嵌入式系統設計方法
11.1.2“協同設計”概念的嵌入式系統設計方法
11.2基于ARM的嵌入式Web服務器設計實例
11.2.1系統環境搭建
11.2.2Web服務器原理
11.2.3嵌入式Web服務器設計
11.3物聯網網關設計實例
11.3.1背景介紹——環境監測系統平臺整體架構
11.3.2網關節點硬件設計方案
11.3.3系統軟件設計
11.3.4數據庫建設
11.4智能無人值守實驗室監控系統設計實例
11.4.1系統總體框架
11.4.2學生選課預約
11.4.3門禁系統
11.4.4ZigBee網絡的網絡拓撲及路由協議
11.4.5Qt的使用
11.5本章小結
參考文獻
第3章ARM指令集
在嵌入式系統開發中,目前最常用的編程語言是匯編語言和C語言。在較復雜的嵌入式軟件中,由于C語言編寫程序較方便,結構清晰,而且有大量支持庫,所以大部分代碼采用C語言編寫,特別是基于操作系統的應用程序設計。但是在系統初始化、BootLoader、中斷處理等,對時間和效率要求較嚴格的地方仍舊要使用匯編語言來編寫相應代碼塊。本章將介紹ARM指令集指令及匯編語言的相關知識。3.1ARM指令集概述ARM處理器的指令集主要有: ARM指令集,是ARM處理器的原生32位指令集,所有指令長度都是32位,以字對齊(4字節邊界對齊)方式存儲; 該指令集效率高,但是代碼密度較低。 Thumb指令集是16位指令集,2字節邊界對齊,是ARM指令集的子集; 在具有較高代碼密度的同時,仍然保持ARM的大多數性能優勢。 Thumb2指令集是對Thumb指令集的擴展,提供了幾乎與ARM指令集相同的功能,同時具有16位和32位指令,既繼承了Thumb指令集的高代碼密度,又能實現ARM指令集的高性能; 2字節邊界對齊,16位和32位指令可自由混合。 Thumb2EE指令集是Thumb2指令集的一個變體,用于動態產生的代碼; 不能與ARM指令集和Thumb指令集交織在一起。除了上面介紹的指令集外,ARM處理器還有針對協處理器的擴展指令集,如普通協處理器指令、NEON和VFP擴展指令集、無線MMX技術擴展指令集等。3.1.1指令格式ARM指令集的指令基本格式如下:
< opcode > {< cond >} { S } < Rd >, < Rn >, < shift_operand >
指令中“< >”內的項是必需的,“{ }”內的項是可選的。各個項目的具體含義如表31所示。
表31ARM指令格式
符號說明
opcode操作碼,即指令助記符,如MOV、SUB、LDR等cond條件碼,描述指令執行的條件S可選后綴,指令后加上S,指令執行成功完成后自動更新CPSR寄存器中的條件標志位Rd目的寄存器Rn存放第1個操作數的寄存器shift_operand第2個操作數,可以是寄存器、立即數等3.1.2指令的條件碼ARM指令集中幾乎每條指令都可以是條件執行的,由cond可選條件碼來決定,位于ARM指令的較高4位[31∶28],可以使用的條件碼如表32所示。每種條件碼的助記符由兩個英文符號表示,在指令助記符的后面和指令同時執行。根據程序狀態寄存器CPSR中的條件標志位[31∶28]判斷當前條件是否滿足,若滿足則執行指令。若指令中有后綴S,則根據執行結果更新程序狀態寄存器CPSR中的條件標志位[31∶28]。
表32ARM指令條件碼
指令條件碼助記符CPSR條件標志位值含義
0000EQZ=1相等0001NEZ=0不相等0010CS/HSC=1無符號數大于或等于0011CC/LOC=0無符號數小于0100MIN=1負數0101PLN=0正數或零0110VSV=1溢出0111VCV=0沒有溢出1000HIC=1,Z=0無符號數大于1001LSC=0,Z=1無符號數小于或等于1010GEN=V有符號數大于或等于1011LTN!=V有符號數小于1100GTZ=0,N=V有符號數大于1101LEZ=1,N!=V有符號數小于或等于1110AL任何無條件執行(指令默認條件) 1111NV任何從不執行(不要執行)3.2ARM指令的尋址方式尋址方式是指處理器根據指令中給出的地址信息,找出操作數所存放的物理地址,實現對操作數的訪問。根據指令中給出的操作數的不同形式,ARM指令系統支持的尋址方式有: 立即尋址、寄存器尋址、寄存器間接尋址、寄存器移位尋址、變址尋址、多寄存器尋址、堆棧尋址、塊復制尋址和相對尋址等。3.2.1立即尋址立即尋址也叫立即數尋址,指令的操作碼字段后面的地址碼部分不是操作數地址而是操作數本身,包含在指令的32位編碼中。立即數前要加前綴“#”。示例:
ADD R0,R0,#1; R0 ← R0 1
MOVR0,#0x00ff; R0 ← 0x00ff
3.2.2寄存器尋址寄存器尋址是指將操作數放在寄存器中,指令中地址碼部分給出寄存器編號。這是各類微處理器常用的一種有較高執行效率的尋址方式。示例:
ADD R0,R1,R2; R0 ← R1 R2
MOVR0,R1; R0 ← R1
3.2.3寄存器間接尋址操作數存放在存儲器中,并將所存放的存儲單元地址放入某一通用寄存器中,在指令中的地址碼部分給出該通用寄存器的編號。示例:
LDRR0,[R1]; R0 ← [R1]
該指令將寄存器R1中存放的值0xA0000008作為存儲器地址,將該存儲單元中的數據0x00000003傳送到寄存器R0中,尋址示意圖如圖31所示。
圖31寄存器間接尋址方式示意圖
3.2.4寄存器移位尋址該指令中,寄存器的值在被送到ALU之前,先進行移位操作。移位的方式由助記符給出,移位的位數可由立即數或寄存器直接尋址方式表示。可以采用的移位操作有: LSL: 邏輯左移,寄存器值低端空出的位補0。 LSR: 邏輯右移,寄存器值高端空出的位補0。 ASR: 算術右移,算術移位操作對象是有符號數,位移過程中要保障操作數的符號不變,若操作數是正數,高端空出位補0; 若操作數是負數,高端空出位補1。 ROR: 循環右移,從低端移出的位填入高端空出的位中。 RRX: 帶擴展的循環右移,操作數右移1位,高端空出的位用C標志位填充。示例:
MOV R0,R1, LSL #2; R0 ← R1中的數左移2位
ADDR0, R1, R2, LSR #3; R0 ←R1 R2中的數右移3位
3.2.5變址尋址變址尋址方式是將某個寄存器(基址寄存器)的值與指令中給出的偏移量相加,形成操作數的有效地址,再根據該有效地址訪問存儲器。該尋址方式常用于訪問在基址附近的存儲單元。示例:
LDRR0,[R1, #2]; R0 ← [R1 2]
該指令將R1寄存器的值0xA0000008加上位移量2,形成操作數的有效地址,將該有效地址單元中的數據傳送到寄存器R0中。3.2.6多寄存器尋址多寄存器尋址方式可以在一條指令中傳送多個寄存器的值,一條指令最多可以傳送16個通用寄存器的值。連續的寄存器之間用“”連接,不連續的中間用“,”分隔。示例:
LDMIAR0!,{R1R3, R5}; R1 ← [R0]
; R2 ← [R0 4]
; R3 ← [R0 8]
; R5 ← [R0 12]
該指令將R0寄存器的值0xA0000004作為操作數地址,將存儲器中該地址開始的連續單元中的數據傳送到寄存器R1、R2、R3、R5中,尋址示意圖如圖32所示。
圖32多寄存器尋址方式示意圖
3.2.7相對尋址相對尋址方式就是以PC寄存器為基址寄存器,以指令中的地址標號為偏移量,兩者相加形成操作數的有效地址。偏移量指出的是當前指令和地址標號之間的相對位置。子程序調用指令即是相對尋址方式。示例:
BLADDR1; 跳轉到子程序ADDR1處執行
…
ADDR1:
…
MOVPC,LR; 從子程序返回
3.2.8堆棧尋址堆棧是按“先進后出”或“后進先出”方式進行存取的存儲區。堆棧尋址是隱含的,使用一個叫做堆棧指針的專門寄存器,指示當前堆棧的棧頂。根據堆棧的生成方式不同,分為遞增堆棧和遞減堆棧。當堆棧向高地址方向生長時,叫做遞增堆棧(向上生長); 當堆棧向低地址方向生長時,叫做遞減堆棧(向下生長)。堆棧指針指向壓入堆棧的數據時,稱為滿堆棧; 堆棧指針指向下一個將要放入數據的空位置時,稱為空堆棧。這樣就有四種類型的堆棧工作方式: 滿遞增堆棧(FA)、滿遞減堆棧(FD)、空遞增堆棧(EA)、空遞減堆棧(ED)。示例:
STMFD SP!,{R1R3, LR}; 將寄存器R1~R3和LR壓入堆棧,滿遞減堆棧
LDMFDSP!,{R1R3, LR}; 將堆棧數據出棧,放入寄存器R1~R3和LR
3.2.9塊復制尋址塊復制尋址方式是多寄存器傳送指令LDM/STM的尋址方式。LDM/STM指令可以將存儲器中的一個數據塊復制到多個寄存器中,或將多個寄存器中的值復制到存儲器中。尋址操作中使用的寄存器可以是R0~R15這16個寄存器的所有或子集。根據基地址的增長方向是向上還是向下,以及地址的增減與指令操作的先后順序(操作先進行還是地址先增減)的關系,有四種尋址方式: IB(Increment Before): 地址先增加再完成操作,如STMIB、LDMIB。 IA(Increment After): 先完成操作再地址增加,如STMIA、LDMIA。 DB(Decrement Before): 地址先減少再完成操作,如STMDB、LDMDB。 DA(Decrement After): 先完成操作再地址減少,如STMDA、LDMDA。3.3ARM指令簡介ARM指令集主要有: 跳轉指令、數據處理指令、程序狀態寄存器處理指令、加載/存儲指令、協處理器指令和異常產生指令六大類。ARM指令集是加載/存儲型的,指令的操作數都存儲在寄存器中,處理結果直接放入到目的寄存器中。采用專門的加載/存儲指令來訪問系統存儲器。本節介紹ARM指令集中常用指令的用法和使用要點。3.3.1跳轉指令跳轉指令用于實現程序流程的跳轉。在ARM程序中有兩種方式可以實現程序流程的跳轉: 直接向程序計數器PC中寫入跳轉地址,可以實現4GB地址空間內的任意跳轉。例如:
LDRPC, [PC, # 0x00FF]; PC ← [PC 8 0x00FF]
使用專門的跳轉指令。ARM指令集中的跳轉指令可以完成從當前指令向前或向后的32MB地址空間的跳轉。跳轉指令有: 1. B指令
B{條件}目標地址
跳轉指令B是最簡單的跳轉指令,跳轉到給定的目標地址,從那里繼續執行。示例:
BWAITA; 無條件跳轉到標號WAITA處執行
B0x1234; 跳轉到地址0x1234處
2. BL指令
BL{條件}目標地址
用于子程序調用,在跳轉之前,將下一條指令的地址復制到鏈接寄存器R14(LR)中,然后跳轉到指定地址執行。示例:
BLFUNC1; 將當前PC值保存到R14中,然后跳轉到標號FUNC1處執行
3. BLX指令
BLX{條件}目標地址
BLX指令從ARM指令集跳轉到指定地址執行,并將處理器的工作狀態由ARM狀態切換到Thumb狀態,同時將PC值保存到鏈接寄存器R14中。示例:
BLX FUNC1; 將當前PC值保存到R14中,然后跳轉到標號FUNC1處執行,
; 并切換到Thumb狀態
BLX R0; 將當前PC值保存到R14中,然后跳轉R0中的地址處執行,
; 并切換到Thumb狀態
4. BX指令
BX{條件}目標地址
帶狀態切換的跳轉指令,跳轉到指定地址執行。若目標地址寄存器的位[0]為1,處理器的工作狀態切換為Thumb狀態,同時將CPSR中的T標志位置1,目標地址寄存器的位[31∶1]復制到PC中; 若目標地址寄存器的位[0]為0,處理器的工作狀態切換為ARM狀態,同時將CPSR中的T標志位清0,目標地址寄存器的位[31∶1]復制到PC中。示例:
BXR0; 跳轉R0中的地址處執行,如果R0[0]=1,切換到Thumb狀態
3.3.2數據處理指令數據處理指令主要完成寄存器中數據的各種運算操作。數據處理指令的使用原則: 所有操作數都是32位,可以是寄存器或立即數。 如果數據操作有結果,結果也為32位,放在目的寄存器中。 指令使用“兩操作數”或“三操作數”方式,即每一個操作數寄存器和目的寄存器分別指定。 數據處理指令只能對寄存器的內容進行操作。指令后都可以選擇S后綴來影響標志位。比較指令不需要后綴S,這些指令執行后都會影響標志位。1. MOV指令
MOV{條件}{S}目的寄存器,源操作數
MOV指令將一個立即數、一個寄存器或被移位的寄存器傳送到目的寄存器中。后綴S表示指令的操作是否影響標志位。如果目的寄存器是寄存器PC可以實現程序流程的跳轉,寄存器PC作為目的寄存器且后綴S被設置,則在跳轉的同時,將當前處理器工作模式下的SPSR值復制到CPSR中。示例:
MOVR0, #0x01; 將立即數0x01裝入到R0
MOVR0, R1; 將寄存器R1的值傳送到R0
MOVSR0, R1, LSL #3; 將寄存器R1的值左移3位后傳送到R0,并影響標志位
MOVPC, LR; 將鏈接寄存器LR的值傳送到PC中,用于子程序返回
2. MVN指令
MVN{條件}{S}目的寄存器,源操作數
MVN指令將一個立即數、一個寄存器或被移位的寄存器的值先按位求反,再傳送到目的寄存器中。后綴S表示是否影響標志位。示例:
MVNR0, #0x0FF; 將立即數0xFF按位求反后裝入R0,操作后R0=0xFFFFFF00
MVNR0, R1; 將寄存器R1的值按位求反后傳送到R0
3. ADD指令
ADD{條件}{S}目的寄存器,操作數1,操作數2
ADD指令將兩個操作數相加后,結果放入目的寄存器中。同時根據操作的結果影響標志位。示例:
ADDR0, R0, #1; R0 = R0 1
ADDR0, R1, R2; R0 = R1 R2
ADDR0, R1, R2, LSL #3; R0 = R1 (R2
4. SUB指令
SUB{條件}{S}目的寄存器,操作數1,操作數2
SUB指令用于把操作數1減去操作數2,將結果放入目的寄存器中。同時根據操作的結果影響標志位。示例:
SUBR0, R0, #1; R0 = R0 - 1
SUBR0, R1, R2; R0 = R1- R2
SUBR0, R1, R2, LSL #3; R0 = R1 - (R2
5. RSB指令
RSB{條件}{S}目的寄存器,操作數1,操作數2
RSB指令稱為逆向減法指令,用于把操作數2減去操作數1,將結果放入目的寄存器中。同時根據操作的結果影響標志位。示例:
RSBR0, R0, #0xFFFF; R0 = 0xFFFF- R0
RSBR0, R1, R2; R0 = R2 - R1
6. ADC指令
ADC{條件}{S}目的寄存器,操作數1,操作數2
ADC指令將兩個操作數相加后,再加上CPSR中的C標志位的值,將結果放入目的寄存器中。同時根據操作的結果影響標志位。示例:
ADDSR0, R0, R2
ADCR1, R1, R3; 用于64位數據加法,(R1,R0)=(R1,R0) (R3,R2)
7. SBC指令
SBC{條件}{S}目的寄存器,操作數1,操作數2
SBC指令用于操作數1減去操作數2,再減去CPSR中的C標志位值的反碼,將結果放入目的寄存器中。同時根據操作的結果影響標志位。示例:
SUBSR0, R0, R2
SBCR1, R1, R3; 用于64位數據減法,(R1,R0)=(R1,R0)-(R3,R2)
8. RSC指令
RSC{條件}{S}目的寄存器,操作數1,操作數2
RSC指令用于操作數2減去操作數1,再減去CPSR中的C標志位值的反碼,將結果放入目的寄存器中。同時根據操作的結果影響標志位。示例:
RSBSR2, R0, #0
RSCR3, R1, #0; 用于求64位數據的負數
RSCR0, R1, R2; R0 = R2 - R1-!C
9. AND指令
AND{條件}{S}目的寄存器,操作數1,操作數2
AND指令實現兩個操作數的邏輯與操作,將結果放入目的寄存器中。同時根據操作的結果影響標志位。常用于將操作數某些位清0。示例:
ANDR0, R1, R2; R0 = R1 & R2
ANDR0, R0, #3; R0的位0和位1不變,其余位清0
10. ORR指令
ORR{條件}{S}目的寄存器,操作數1,操作數2
ORR指令實現兩個操作數的邏輯或操作,將結果放入目的寄存器中。同時根據操作的結果影響標志位。常用于將操作數某些位置1。示例:
ORRR0, R0, #3; R0的位0和位1置1,其余位不變
11. EOR指令
EOR{條件}{S}目的寄存器,操作數1,操作數2
EOR指令實現兩個操作數的邏輯異或操作,將結果放入目的寄存器中。同時根據操作的結果影響標志位。常用于將操作數某些位置取反。示例:
EORR0, R0, #0F; R0的低4位取反
12. BIC指令
BIC{條件}{S}目的寄存器,操作數1,操作數2
BIC指令用于清除操作數1的某些位,將結果放入目的寄存器中。同時根據操作的結果影響標志位。操作數2為32位掩碼,掩碼中設置了哪些位則清除操作數1中這些位。示例:
BICR0, R0, #0F; 將R1的低4位清0,其他位不變
13. CMP指令
CMP{條件}操作數1,操作數2
CMP指令用于把一個寄存器的值減去另一個寄存器的值或立即數,根據結果設置CPSR中的標志位,但不保存結果。示例:
CMPR1, R0; 將R1的值減去R0的值,并根據結果設置CPSR的標志位
CMPR1, #0x200; 將R1的值減去0x200,并根據結果設置CPSR的標志位
14. CMN指令
CMN{條件}操作數1,操作數2
CMN指令用于把一個寄存器的值減去另一個寄存器或立即數取反的值,根據結果設置CPSR中的標志位,但不保存結果。該指令實際完成兩個操作數的加法。示例:
CMNR1, R0; 將R1的值和R0的值相加,并根據結果設置CPSR的標志位
CMNR1, #0x200; 將R1的值和立即數0x200相加,并根據結果設置CPSR的標志位
15. TST指令TST{條件}操作數1,操作數2
TST指令用于把一個寄存器的值和另一個寄存器的值或立即數進行按位與運算,根據結果設置CPSR中的標志位,但不保存結果。該指令常用于檢測特定位的值。示例:
TSTR1, #0x0F; 檢測R1的低4為是否為0
16. TEQ指令
TEQ{條件}操作數1,操作數2
TST指令用于把一個寄存器的值和另一個寄存器的值或立即數進行按位異或運算,根據結果設置CPSR中的標志位,但不保存結果。該指令常用于檢測兩個操作數是否相等。示例:
TEQR1, R2; 將R1的值和R2的值進行異或運算,并根據結果設置CPSR的標志位
3.3.3程序狀態寄存器處理指令MRS指令和MSR指令用于在狀態寄存器和通用寄存器間傳輸數據。狀態寄存器的值要通過“讀取→修改→寫回”三個步驟操作來實現,可先用MRS指令將狀態寄存器的值復制到通用寄存器中,修改后再通過MSR指令把通用寄存器的值寫回狀態寄存器。示例:
MRSR0, CPSR; 將CPSR的值復制到R0中
ORRR0, R0, #C0; R0的位6和位7置1,即屏蔽外部中斷和快速中斷
MSRCPSR, R0; 將R0值寫回到CPSR中
MRS指令和MSR指令的格式如下:
MRS{條件}通用寄存器, 程序狀態寄存器(CPSR或SPSR)
MSR{條件}程序狀態寄存器(CPSR或SPSR)_, 操作數
其中,MSR指令中的可用于設置程序狀態寄存器中需要操作的位: 位[31∶24]為條件標志位域,用f表示。 位[23∶16]為狀態位域,用s表示。 位[15∶8]為擴展位域,用x表示。 位[7∶0]為控制位域,用c表示。示例:
MSRCPSR_cxsf, R3
3.3.4加載/存儲指令加載/存儲指令用于在寄存器和存儲器之間傳輸數據,Load指令用于將存儲器中的數據傳輸到寄存器中,Store指令用于將寄存器中的數據保存到存儲器中。1. LDR指令
LDR{條件}目的寄存器,
LDR指令將一個32位字數據傳輸到目的寄存器中。如果目的寄存器是PC,從存儲器中讀出的數據將作為目的地址,以實現程序流程的跳轉。示例:
LDRR1, [R0, #0x12]; 將存儲器地址為R0 0x12的字數據寫入R1
LDRR1, [R0, R2]; 將存儲器地址為(R0 R2)的字數據寫入R1
2. STR指令
STR{條件}源寄存器,
STR指令用于從源寄存器中將一個32位字數據寫入存儲器中。示例:
STRR1, [R0, #0x12]; 將R1中的字數據寫入以R0 0x12為地址的存儲器中
STRR1, [R0], #0x12; 將R1中的字數據寫入以R0 0x12為地址的存儲器中,
; 并將新地址R0 0x12寫入R0
3. LDM和STM指令
LDM(或STM){條件}{類型}基址寄存器{!},寄存器列表{∧}
LDM指令和STM指令實現一組寄存器和一