arm彙編程式設計(示例)
一、arm的認知及基本概念
(一).arm的基本概念
1. 什麼是arm
arm是一家英國電子公司的名字,全名是Advanced RISC Machine
這家企業設計了大量高效能、廉價、耗能低的RISC(精簡指令集)處理器,ARM公司只設計晶片而不生產,它將
技術授權給世界上許多公司和廠商。目前採用arm技術知識產權核心的微處理器,即通常所說的arm微處理器
所以arm也是對一類微處理器的通稱。
arm指令集體系版本號(軟體)為V1 ~ V7 目前V1 ~ V3已很少見。從V4版不再與以前的版本相容。
arm的CPU系列(硬體)主要有 ARM7 ~ ARM11
2. 典型的嵌入式處理器
arm 佔市場79.5% ARM
mips 佔市場13.9% MIPS
microSPARC 佔市場3.1% SUN
PowerPc 佔市場2.8% IBM
其它 佔市場0.8%
3. arm的應用範圍:
工業控制:如機床、自動控制等
無線通訊:如手機
網路應用:如
電子產品:如音視訊播放噐、機頂盒、遊戲機、數碼相機、印表機
其它各領域:如軍事、醫療、機器人、智慧家居等
4.計算機體系結構
見圖:馮.諾依曼計算機體系圖
馮.諾依曼體系結構
處理器使用同一個儲存器,經由同一個匯流排傳輸
完成一條指令需要3個步驟:即取指令->指令譯碼->執行指令
指令和資料共享同一匯流排的結構
哈佛體系結構
將程式指令儲存和資料儲存分開
中央處理器首先到程式指令儲存器中讀取程式指令。解碼後到資料地址,再到相應的資料儲存器讀取資料,然後執行指令
程式指令儲存與資料儲存分開,可以使指令和資料有不同的資料寬度。
5.複雜指令集與精簡指令集
CISC 複雜指令集:採用馮.諾依曼體系結構。資料線和指令線分時複用(只能通過一輛車)。
儲存器操作指令多 彙編程式相對簡單 指令結束後響應中斷 CPU電路豐富 面積大功耗大
RISC 精簡指令集:採用哈佛體系結構。資料線和指令線分離(同時能通過多輛車)。
對儲存器操作有限 彙編程式佔空間大 在適當地方響應中斷 CPU電路較少 體積小功耗低
ARM採用RISC精簡指令集
Thumb是ARM體系結構中一種16位的指令集。
從ARMv4T之後,的ARM處理器有一種16-bit指令模式,叫做Thumb,較短的指令碼提供整體更佳的編碼密度,更有效地使用有限的記憶體頻寬。所有 ARM9 和後來的家族,包括 XScale 都納入了 Thumb 技術。
即ARM有兩種指令集:RISC、Thumb
6. arm的思想
1) arm體系的總思想:
在不犧牲效能的同時,儘量簡化處理器。同時從體系結構上靈活支援處理器擴充套件。採用RISC結構。RISC處理器簡化了處理器結構,減少複雜功能指令的同時,提高了處理器速度。
ARM及MIPS都是典型的RISC處理器
2) arm的流水線結構
arm處理器使用流水線來增加處理器指令流的速度,這樣可以使幾個操作同時進行。並使處理和儲存器系統連續操作。
arm處理器分為三級:取指->譯碼->執行
取指:指令從儲存器中取出
譯碼:對指令使用的暫存器進行譯碼
執行:從暫存器組中讀取暫存器,執行移位和ALU操作,暫存器被寫回到暫存器組中
3) ARM處理器支援的型別
位元組 8位
半字 16位
字 32位
**所有資料操作都以字為單位
**ARM指令的長度剛好是一個字,Thumb指令長度剛好是半個字
4) ARM處理器狀態
ARM處理器核心使用ARM結構,該結構包含32位的ARM指令集和16位Thumb指令集,因此ARM有兩種操作狀態
ARM狀態:32位
Thumb狀態:16位
5) 處理器模式
ARM處理器共有7種執行模式:
使用者: 正常程式工作模式,不能直接切換到其它模式
系統: 用於支援作業系統的特權任務,可以直接切換到其它模式
快中斷:支援高速資料傳輸及通道處理,FIQ異常響應時進入此模式
中斷: 用於通用中斷處理,IRQ異常響應時進入此模式
管理: 作業系統保護程式碼,系統復位和軟體中斷響應時進入此模式
中止: 用於支援虛擬記憶體或儲存器保護,用於MMU
未定義:支援硬體協處理器的軟體模擬,未定義指令異常響應時進入此模式。
(二)、經典平臺硬體組成
見圖:arm硬體組成圖
開發板一般是由一塊組成的,有核心器件和外圍器件介面等,但是有的是由兩塊板子組成,主版和核心板,主版上主要是外圍介面,外圍器件等,核心板上主要是核心器件,還有一些晶振電路等
1.核心板(天嵌 2440)
CPU處理器 S3C2440AL,主頻400MHz(最高可達533MHz)
SDRAM記憶體 板載64MB SDRAM(標準配置), 32bit資料匯流排SDRAM時鐘頻率高達100MHz(支援執行133MHz)
Nand Flash 板載64MB Nand Flash或256MB Nand Flash(標準配置)
Nor Flash 板載2MB Nor Flash(最高可升級到8MB)
CorePower 專業1.25V核心電壓供電
Power 核心板採用3.3V供電
Powerled 核心板電源指示燈
核心板介面 介面型號為DC-2.0雙列直插
SDRAM:隨機儲存器,普遍使用的記憶體。用作主存。
NOR Flash和 NAND Flash是現在市場上兩種主要的非易失快閃記憶體。
NOR的特點是晶片內執行,應用程式可以直接在flash 快閃記憶體內執行,不必再把程式碼讀到系統RAM中。
NAND結構能提供極高的單元密度,可以達到高儲存密度,並且寫入和擦除的速度也很快。
2.主機板
電源
並口線
復位
RTC電源
RS232電平轉換DB9插座
音訊IIS,AC97
按鍵、PS/2與IC介面
數碼管
觸控式螢幕
乙太網卡
主USB HUB 1轉4
3.暫存器
見圖:ARM模組和核心框圖
暫存器是中央處理器內的組成部份。
暫存器是有限存貯容量的高速存貯部件,用來暫存指令、資料和位址。在中央處理器的控制部件中,包含的暫存器有指令暫存器(IR)和程式計數器(PC)。在中央處理器的算術及邏輯部件中,包含的暫存器有累加器(ACC)。
IR 用於儲存指令
PC 用於儲存程式執行的地址(即當前指令在記憶體中的位置)
暫存器是由一個指令的輸出或輸入可以直接索引到的暫存器群組。所有的計算機指令都是進入暫存器後被直接讀取
ARM的彙編程式設計,本質上就是針對CPU暫存器的程式設計。
//*******重點 需要背訟*************************************************
ARM暫存器分為2類:普通暫存器和狀態暫存器
(1)通用暫存器和計數器:共32個,15個通用暫存器
R0 -R7 未備份暫存器
R0(a1) R1(a1) R2(a3) R3(a4) R4(v1) R5(v2) R6(v3) R7(v4)
R8 -R12 備份暫存器
R8(v5) R9 (SB,v6) R10(SL,v7) R11(EP,v8) R12(IP) 資料暫存器
R15(PC) 程式計數器 它的值是當前正在執行的指令在記憶體中的位置。
當指令執行結束後,CPU會自動將PC值加上一個單位,PC值指向下一條即將執行的指令的地址
如果通過彙編指令對PC暫存器賦值,就會完成一次程式的跳轉(如從子函式跳轉回主函式內)
R14(LR) 連結暫存器 存放子程式的返回地址
例如:在主函式內,如果呼叫子函式,程式會進入到子函式內執行。當子函式執行完畢後,需要回到
主函式內,所以,在子函式呼叫前需要將這個地址先儲存起來,否則無法找到這個地址。
LR用於儲存這個地址,這個地址也稱為子程式返回地址。當子函式結束後,再將LR內的地址賦給PC即可。
如果子程式再呼叫孫程式,LR如何儲存地址呢?
先把當前LR內的值壓入記憶體的棧區,然後LR再儲存孫程式的返回地址。當孫程式執行完後通過PC跳轉到
子程式內,此時將棧區內的子程式返回地址取出儲存在LR內。當子程式執行完後,再通過PC跳轉到主函式內。
R13(SP) 棧指標暫存器 用於存放堆疊的棧頂地址。
SP相當於指標變數,儲存的是棧頂的地址,出棧時,從SP指向的記憶體中取出資料,入棧時將新的記憶體地址
壓入棧頂,而SP相當於連結串列的頭指標(head)。
原則上說R0-R12可以儲存任何資料。其中R0-R7用來臨時儲存資料,R8-R12 系統沒有用來做任何特殊用途,常用於中斷
而在彙編與C語言的互動中,定製了ATPCS標準
暫存器:R4-R11用來儲存區域性變數
引數: 引數小於等於4,用R0-R3儲存引數,引數多於4,剩餘的傳入堆疊
函式返回:結果為32位整數,通過R0返回
結果為64位整數,通過R0,R1返回
對於位數更多的結果,通過記憶體傳遞
(2)狀態暫存器:
狀態暫存器用於儲存程式的當前狀態
CPSR 當前程式狀態暫存器
一個暫存器為32位,每一位資料代表不同的狀態。分為三個部分(條件程式碼標誌位、控制位、保留區位)
31 32 29 28 .... 7 6 5 4 3 2 1 0
N Z C V I F T M4 M3 M2 M1 M0
其中N Z C V稱為條件標誌位(即儲存的是條件的運算結果,真和假)
N=1 表示運算結果為負數,N=0 表示運算結果為正數。
Z=1 表示運算結果為0, Z=0 表示運算結果為非零。
C=1 表示運算結果產生了進位。
V=1 運算結果的符號位發生了溢位。
這4個位的組合,代表了各種條件,如下:
0000 EQ Z置位 相等/等於0
0001 NE Z清0 不等
0010 CS/HS C置位 進位/無符號高於或等於
0011 CC/LO C清0 無進位/無符號低於
0100 MI N置位 負數
0101 PL N清0 非負數
0110 VS V置位 溢位
0111 VC V清0 無溢位
1000 HI C置位且Z清0 無符號高於
1001 LS C清0或Z置位 無符號低於或等於
1010 GE N等於V 有符號大於或等於
1011 LT N不等於V 有符號小於
1100 GT Z清0且N等於V 有符號大於
1101 LE Z置位或N不等於V 有符號小於或等於
1110 AL 任何狀態 總是(always)
1111 NV 無 從不(never)
IFT 稱為控制位
I I=1 禁用IRO中斷
F F=1 禁用FIQ中斷
T 表示CPU當前的狀態,1 代表正在Thumb指令集狀態,0表示正在ARM指令集狀態。
M0至M4表示中斷型別(控制位內的模式位)
0b10000 User 使用者中斷
0b10001 FIQ 快速中斷
0b10010 IRQ 音效卡、調變解調器等外部裝置產生的中斷
0b10011 Supervisor 管理程式或監控程式產生的中斷
0b10111 Abort 異常中斷
0b11011 Undefined 未定義中斷
0b11111 System 系統中斷
SPSR 儲存的程式狀態暫存器,結構與CPSR完全一樣,用來儲存CPSR的值。以便出現異常時恢復CPSR的值
(3)流水線對pc值的影響
CPU內部的組成部分:指令暫存器,指令譯碼器,指令執行單元(包括ALU和通用暫存器組)
CPU執行指令的步驟:取指->譯碼->執行
取指:將指令從記憶體或指令cache中取入指令暫存器
譯碼: 指令譯碼器對指令暫存器中的指令進行譯碼操作,辨識add,或是sub等操作
執行:指令執行單元根據譯碼的結果進行運算並儲存結果
流水線操作:併發多條流水線(以3條為例)
1 取指 譯碼 執行
2 取指 譯碼 執行
3 取指 譯碼 執行
提高時間效率
(三)、學習內容
1.彙編(對裸板機的控制,以及驅動程式控制)
2.核心移植(uboot移植、核心編譯、檔案系統移植、應用程式移植)
3.驅動程式編寫
//^^^^^^^^^^^^^^^^^^^^^^^^^^ 下午 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
(四)、ADS的使用
ADS是彙編或C語言編譯除錯工具
可生成的檔案:.axf 含除錯資訊的可執行ELF檔案
.bin 可燒寫的二進位制映像檔案
.hex 可燒寫的十六進位制映像檔案
ADS配置
在磁碟中新建一個目錄 D:\arm,用來儲存所寫的程式碼
點選目錄:File->new,建立一個可執行的ARM映象工程
ARM Executable Image 生成ELF格式映像(bin)
ARM Object Library 生成armar格式目標庫檔案
Empty Project 建立不包含任何庫或原始檔的工程
Makefile Importer Wizard 用於Vc
Thumb ARM Interworking Image 用於ARM 和thumb指令混合程式碼生成的ELF映像
Thumb Executable image 用thumb指令生成ELF格式映像
Thumb Object Library 用於Thumb指令的程式碼生成的armar格式檔案
選 ARM Executable Image,工程檔名2440ART
加原始檔
project -> Add Files
新建
填加已有
生成目標的配置
2440ART.mcp內雙擊
TargetSettins: post-linker選擇ArM fromELF
Language Settins:Architecture or Processor選擇相應的編譯器ARM920T
Arm Linker:output 內RO 0x30000000
options內Image entry point 設為0x30000000
layout 內Object 2440init.o Section Init
Listings 內Image map
Arm fromELF: output format內 Plain binary
output filename內***.bin
編譯
make
除錯 AXD是偵錯程式
設定,debug ->開啟AXD除錯介面,選擇option->config target 選項
選ARMUL(模擬偵錯程式),然後選擇確定.進入除錯介面.
ARMUL是虛擬除錯環境(虛擬開發板)
如果用開發板真實環境除錯,則需要使用JTAG連開發板後,在此處選H-JTAG
用file-<lode image項,載入剛才編譯所的的 .axf除錯檔案.
execute->run to cousor 項.使程式進入使用者主程式
可以用F8來一條一條執行語句,也可用F10,可以設定斷點.
(五).組合語言基本結構
例:
AREA Init,CODE,READONLY ;AREA定義程式碼段,段名Init;程式碼段,只讀
ENTRY ;偽操作,第一條指令的入口
Start ;標號,一段程式碼的開始,用於標記,無意義,必須頂格
MOV r0,#10 ;將10存入r0暫存器,整型常量前面用#號
MOV r1,#3 ;將3存入r1暫存器,r0和r1相當於兩個變數,只是名稱固定,在暫存器的儲存空間內
ADD r0,r0,r1 ;將r0內資料與r1內資料相加,相加後資料放在r0內
;Stop ;停止標號,下面的程式碼用於停止執行程式
; MOV r0,#0x18 ;軟體異常中斷響應
; LDR r1,=0x20026 ;ADP停止執行,應用退出
; SWI 0x123456 ;ARM半主機軟體中斷
END
1).基本概念
(2)暫存器:如 R0、R1等
ARM的彙編程式設計,本質上就是針對CPU暫存器的程式設計。
(3)指令:即操作碼,直接控制CPU,如MOV
包括跳轉指令、資料處理指令、乘法指令、PSR訪問指令、載入或儲存指令、資料交換指令、移位指令等
(4)偽操作:作用於編譯器,大多用於定義和控制。如AREA
包括符號定義、資料定義、控制等
(5)標號:僅是一種標識。在跳轉語句中,可以指向要跳轉到的標識號位置
在ARM 彙編中,標號代表一個地址,段內標號的地址在彙編時確定,段外標號的地址值在連線時確定
(6)符號:即標號(代表地址)、變數名、數字常量名等。符號的命名規則如下:
a. 符號由大小寫字母、數字以及下劃線組成;
b. 除區域性標號以數字開頭外,其它的符號不能以數字開頭;
c. 符號區分大小寫,且所有字元都是有意義的;
d. 符號在其作用域範圍你必須是唯一的;
e. 符號不能與系統內部或系統預定義的符號同名;
f. 符號不要與指令助記符、偽指令同名。
2).段定義
在組合語言中,以相對獨立的指令或資料序列的程式段組成程式程式碼
段的劃分:資料段、程式碼段。一個彙編程式至少有一個程式碼段
(1)程式碼段
上面的例子為程式碼段。
AREA 定義一個段,並說明所定義段的相關屬性,CODE 用以指明為程式碼段
ENTRY 標識程式的入口點。END為程式結束。
(2)資料段
AREA DATAAREA,DATA,BIINIT,ALLGN=2
DISPBUF SPACE 200
RCVBUF SPACE 200
DATA用以指明為資料段,
SPACE分配200位元組的儲存單元並初始化為0
指令和偽操作在後面詳細描述
3).組合語言結構
[標號] [指令或偽操作]
所有標號必須在一行的頂格書寫,其後不加冒號
所有指令均不能頂格寫
指令助記符大小寫敏感,不能大小寫混合,只能全部大寫或全部小寫
;為註釋
@程式碼行註釋,同;
#整行註釋或直接運算元字首
\為換行符
ENTRY 為程式的入口
END 為程式的結束
//************************************* arm體系結構 第二天***************************************
二、ARM的定址方式
最簡單的彙編指令格式是操作碼和運算元
如:MOV r0,#10
操作碼:即CPU指令 如MOV ADD
運算元:即表示資料是在暫存器中還是在記憶體中,是絕對地址還是相對地址
運算元部分要解決的問題是,到哪裡去獲取運算元,獲取運算元的方式就是定址方式。
ARM每一條指令都是32位機器碼,對應CPU的位數
ARM指令格式:
在32位中分為7個位域,每個位域分別儲存不同意義的編碼(二進位制數)
31 ~ 28 27~25 24 ~ 21 20 19~16 15~12 11 ~ 0
-----------------------------------------------------------
| Cond | 001 | Opcode | S | Rn | Rd | Operand2 |
-----------------------------------------------------------
對應輸入的一條指令為:
<Opcode>{<cond>}{s} <Rd>,<Rn>,<Operand2>
Opcode:指令操作碼 用 4個位儲存,如MOV,ADD 每一個操作碼和運算元最終都是以二進位制形式存在
Cond :指令的條件碼 用 4個位來儲,可省略
如:ADD r0,r0,#1 ;計算r0加1後的值,再寫入到r0內
ADDEQ r0,r0,#1 ;只有在CPSR暫存器條件標誌位滿足指定條件時,才計算r0加1後的值,再寫入到r0內
其中條件助記符如下:
EQ 相等
NE 不相等
MI 負數
VS 溢位
PL 正數或零
HI 無符號大於
LS 無符號小於或等於
CS 無符號大於或等於
CC 無符號小於
GT 有符號大於
GE 有符號大於或等於
LE 有符號小於或等於
LT 有符號小於
AL 無條件執行
S :決定指令的操作是否影響CPSR的值,用一個位儲存,省略則表示為0值,否則為1值
如SUBS R0,R0,#1 ;R0減1,結果放入R0,同時響影CPSR的值
SUB R0,R0,#1 ;R0減1,結果放入R0,不影響CPSR的值
Rd :目標暫存器編碼 用4位儲存
Rn :第1個運算元的暫存器編碼 用4位儲存
Operand2: 第2個運算元 用12位儲存
定址方式:是根據指令中給出的地址碼欄位來實現尋找真實運算元地址的方式,共8種定址方式:
暫存器定址、立即定址、暫存器間接定址、基址定址、多暫存器定址、堆疊定址、相對定址、暫存器移位定址
//*******定址方式是重點 需要理解背訟*************************************************
1.立即定址
運算元是常量,用#表示常量。例
MOV R0,#0xFF000 ;指令省略了第1個運算元暫存器。將立即數0xFF000(第2運算元)裝入R0暫存器
SUB R0,R0,#64 ;R0減64,結果放入R0
#表示立即數 0x或&表示16進位制數 否則表示十進位制數
立即數定址指令中的地址碼就是運算元本身,可以立即使用的運算元。
其中,#0xFF000和#64都是立即數。該立即數位於32位機器碼中,佔低位的12位。也就是說在ARM指令中以12位儲存一個數據
那麼,32位的資料(long或float)如何儲存?
32位的資料以一種特殊的方式來處理
其中:高4位表示的無符號整數
低8位補0擴充套件為32位,然後迴圈右移x位來代表一個數。x=高4位整數*2
所以,不是每一個32位數都是合法的立即數,只有能通過上述構造得到的才是合法的立好數。如:
合法立即數:0xff,0x104,0xff0
不合法立即數:ox101,0x102,0xff1
2.暫存器定址
運算元的值在暫存器中,指令執行時直接取出暫存器值來操作
例:MOV R1,R2 ;將R2的值存入R1 在第1個運算元暫存器的位置存放