我們在學習ARM的時候,一般都不用看匯編啟動代碼,直接使用芯片廠商提供的匯編啟動代碼,但是要想深入了解ARM內部原理,就必須掌握一定的匯編知識。
我們在前面總結了處理器架構與指令集,那么匯編和處理器架構、指令集有什么關系呢?先看下圖:
從上圖可以看出,不同的處理器架構、不同指令集合對應不同匯編指令。可以說,一種指令集就對應一種匯編指令,匯編是開發者與計算機交互的接口,
總結一下,匯編語言是指令集構架的機器碼一對一的人類可以理解的翻譯,是用人類看得懂的語言來描述指令集。否則指令集的機器碼都是一堆二進制數字,人類讀起來非常麻煩,但匯編是用類似人類語言的方式描述指令集,從而控制不同的處理器按照人們的想法去工作。
對于CPU來說,它只能識別二進制碼,那怎么能識別高級語言呢?于是人們開發了編譯器,依照如下順序,將高級語言翻譯成二進制碼:
可以說,匯編語言就是高級語言和二進制機器碼的橋梁。
本文針對ARM架構的芯片講解其相關的指令集。
1 工具
工欲善其事,必先利其器,在學習ARM匯編之前,我們先準備好學習軟件。這里推薦使用的是VisUAL。VisUAL是一款ARM匯編模擬器,支持Windows、Mac OS X和Linux系統。
下載地址:https://salmanarif.bitbucket.io/visual/downloads.html
使用方法:https://salmanarif.bitbucket.io/visual/user_guide/index.html
【注】下載VisUAL需要VPN,如果沒有VPN請自行參看后文提示獲取。
VisUAL模擬的ARM板子如下圖所示:
它沒有模擬外設,僅僅模擬了CPU、ROM、RAM。紅色區域是ROM,不能讀不能寫,只能運行其中的程序。ROM區域本來可以讀的,這是VisUAL的局限。RAM區域可讀可寫。
VisUAL 支持一小部分 ARM UAL 指令。這些主要是算術、邏輯、加載/存儲和分支指令。下面給出了指令語法的簡短摘要。有關詳細信息和示例,請移步VisUAL關官網。
Summary | Opcode | Syntax |
---|---|---|
Move | MOV | MOV{S}{cond} dest, op1 {, SHIFT_op #expression} |
Move Negated | MVN | MVN{S}{cond} dest, op1 {, SHIFT_op #expression} |
Address Load | ADR | ADR{S}{cond} dest, expression |
LDR Psuedo-Instruction | LDR | LDR{S}{cond} dest, =expression |
Add | ADD | ADD{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Add with Carry | ADC | ADC{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Subtract | SUB | SUB{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Subtract with Carry | SBC | SBC{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Reverse Subtract | RSB | RSB{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Reverse Subtract with Carry | RSC | RSC{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Bitwise And | AND | AND{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Bitwise Exclusive Or | EOR | EOR{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Bitwise Clear | BIC | BIC{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Bitwise Or | ORR | ORR{S}{cond} dest, op1, op2 {, SHIFT_op #expression} |
Logical Shift Left | LSL | LSL{S}{cond} dest, op1, op2 |
Logical Shift Right | LSR | LSR{S}{cond} dest, op1, op2 |
Arithmetic Shift Right | ASR | ASR{S}{cond} dest, op1, op2 |
Rotate Right | ROR | ROR{S}{cond} dest, op1, op2 |
Rotate Right and Extend | RRX | RRX{S}{cond} op1, op2 |
Compare | CMP | CMP{cond} op1, op2 {, SHIFT_op #expression} |
Compare Negated | CMN | CMN{cond} op1, op2 {, SHIFT_op #expression} |
Test Bit(s) Set | TST | TST{cond} op1, op2 {, SHIFT_op #expression} |
Test Equals | TEQ | TEQ{cond} op1, op2 {, SHIFT_op #expression} |
Load Register | LDR | LDR{B}{cond} dest, [source {, OFFSET}] Offset addressing |
**LDR{B}{cond} dest, [source, | ||
OFFSET]! Pre-indexed addressing** | ||
**LDR{B}{cond} dest, [source], | ||
OFFSET Post-indexed addressing** | ||
Store Register | STR | STR{B}{cond} source, [dest {, OFFSET}] Offset addressing |
**STR{B}{cond} source, [dest, | ||
OFFSET]! Pre-indexed addressing** | ||
**STR{B}{cond} source, [dest], | ||
OFFSET Post-indexed addressing** | ||
Load Multiple Registers | LDM[dir] | LDM[dir]{cond} source, {list of registers} |
Store Multiple Registers | STM[dir] | STM[dir]{cond} dest, {list of registers} |
Branch | B | B{cond} target |
Branch with Link | BL | BL{cond} target |
Declare Word(s) in Memory | DCD | name DCD value_1, value_2, ... value_N |
Declare Constant | EQU | name equ expression |
Declare Empty Word(s) in Memory | FILL | {name} FILL N |
N must be a multiple of 4 | ||
Stop Emulation | END | END{cond} |
1.1 VisUAL設置
VisUAL設置基本不需要什么設置,界面也很簡單,常用的有設置背景、編碼字體與顏色。設置方式如下:
值得注意的是,設置字體大小需要點擊回車才能生效。
1.2 VisUAL使用
首選在編輯區寫好你要模擬的匯編代碼,點擊運行按鈕就可進行調試。
值得一提的是,VisUAL可以回退運行,在運行完一條指令后,還可以回退到上一條指令,非常的實用。
當代碼運行錯誤,會提示錯誤信息,點擊[Reset],根據提示修改錯誤的代碼。
根據提示修改代碼后,點擊[Execute],運行結果如下:
運行成功后,不僅可以看到寄存器的情況,還可以快速查內存情況。以上指令的含義后文會詳細講解。
當然啦,VisUAL還提供了內存分析工具,使用功能方法如下。
好了,關于的VisUAL工具的介紹就這些了,后面會結合ARM的具體匯編指令進一步使用VisUAL工具。
2 ARM匯編編程簡介
首先,我們先看一個簡單的匯編程序:
area ff,code,readonly;聲明代碼段
code32;聲明為32位ARM指令
entry;聲明程序入口
start
;b指令
;1.b跳轉范圍+_32Mb+標號
;b start
;b stop
;2.bl子函數調用
;會把預取指令的地址保存在lr(r14)
;3.bx子函數返回
mov r0,#9
mov r1,#15
mov r5,#9
bl func
;int func(int a,int b)
stop
b stop
func
mov r5,#1
loop
cmp r0,r1
beq stop1
subgt r0,r0,r1
sublt r1,r1,r0
b loop
stop1
bx lr
end
可以看出,ARM匯編程序用“;”號進行注釋。
當然啦,看不懂上面的示例不要緊,后面會在詳細介紹。。
2.1 匯編語言程序格式
一個完整的ARM匯編由兩部分組成:聲明,實際代碼段兩部分組成。
1、聲明
在一個程序之前先要進行聲明:
A.聲明代碼段:
用AREA指令定義一個段,說明所定義段的相關屬性。(說明段的名字,段的屬性)
B.聲明ARM指令:
用CODE32或CODE16來聲明程序為32位ARM指令或是16位Thumb指令。
C.聲明程序入口:
用ENTRY指令標識程序的入口點。
注:這3個聲明缺一不可。在程序完成后要用END 指令聲明程序結束。每一個匯編程序段都必須有一條END指令,指示代碼段的結束。
2、段
A.在ARM匯編語言程序中,以程序段為單位組織代碼。段是相對獨立的指令或數據序列,具有特定的名稱。
B.段的分類
__代碼__段:代碼段的內容為執行代碼
數據段 :數據段存放代碼運行時需要用到的數據。
注:一個匯編程序至少有一個代碼段。如果程序較長時,可以分割為多個代碼段和數據段。多個段在程序編譯連接時最終形成一個可執行的映像文件。
C.段具有以下的屬性
- READONLY
- READWRITE
2.2 匯編語言的語句格式
[LABEL] OPERATION [OPERAND] [;COMMENT]
標號域 操作助記符域 操作數域 注釋域
1.標號域(LABLE)
A.標號域用來表示指令的地址、變量、過程名、數據的地址和常量。
B.標號是可以自己起名的標識符,語句標號可以是大小寫字母混合,通常以字母開頭,由字母、數字、下劃線等組成。
C.語句標號不能與寄存器名、指令助記符、偽指令(操作)助記符、變量名同名。
D.語句標號必須在一行的開頭書寫,不能留空格。
2.操作助記符域(OPERATION)
A.操作助記符域可以為指令、偽操作、宏指令或偽指令的助記符。
B.ARM匯編器對大小寫敏感,在匯編語言程序設計中,每一條指令的助記符可以全部用大寫、或全部用小寫,但不允許在一條指令中大、小寫混用。
C.所有的指令都不能在行的開頭書寫,必須在指令的前面有空格,然后再書寫指令。
D.指令助記符和后面的操作數或操作寄存器之間必須有空格,不可以在這之間使用逗號。
3.操作數域(OPERAND)
操作數域表示操作的對象,操作數可以是常量、變量、標號、寄存器名或表達式,不同對象之間必須用逗號“,”分開。
2.3 ARM指令集格式
基本格式是操作碼,后跟可選條件碼,可選S (set flags),如下所示
Operation{cond}{S} Rd, Rn, Operand2
1.其中<>中的項是必須的,{}中的項是可選的。
2.opcode 表示指令助記符。
- cond:表示執行條件。
- S:表示是否影響CPSR寄存器的值。
- Rd:表示目標寄存器。
- Rn:表示第一個操作數的寄存器。
- operand2:表示第2個操作數。
3.“operand2”具有如下的形式:
A.#immed_8r:常數表達式
Eg:
MOV R0,#1
ADD R0,R1,#0X0F
B.Rm:寄存器形式。
即在寄存器方式下,操作數即為寄存器的數值。
Eg:
MOV PC,R0
ADD R1,R1,R2
C.Rm,shift:寄存器移位方式。
將寄存器的移位結果作為操作數,當Rm值保持不變。
- ASR #n:表示算術右移n位。
- LSR #n:表示邏輯右移n位。
- ROR #n:表示循環右移n位。
- RRX #n:帶擴展的循環右移n位。
- LSL #n:邏輯左移n位。
4.使用條件碼“cond”可以實現高效的邏輯操作,提高代碼的效率。
- 所有的ARM指令都可以條件執行。
- Thumb指令只有B(跳轉)指令具有條件執行功能。
注:如果執行中不表明條件碼,默認為無條件(AL)執行。
2.4 匯編程序中常用的符號
在匯編語言程序設計中,經常使用各種符號表示變量、常量和地址
A.符號由大小寫字母、數字以及下劃線組成。
B.符號區分大小寫,同名的大、小寫符號會被編譯器認為是兩個不同的符號。
C.符號在其作用范圍內必須唯一,即在其作用范圍內不可有同名的符號。
D.自定義的符號名不能與系統的保留字相同。
【注】符號名不應與指令或偽指令同名。
1.程序中的變量
- ARM匯編程序所支持的變量有數字變量,邏輯變量和字符串變量
- 在ARM匯編程序設計中,可使用GBLA,GBLL,GBLS偽定義聲明全局變量,使用LCLA,LCLL,LCLS聲明局部變量,并可使用SETA,SETL和SETS對其經行初始化。
2.程序中的常量
ARM匯編程序所支持常量有數字常量,邏輯常量和字符串常量。
3.程序中的變量代換
程序中的變量可通過代換操作取的一個常量。代換操作符為”$”。使用示例:
LCLS S1
LCLS S2;定義局部字符串變量S1和S2
S1 SETS “Test!”
S2 SETS “This is a $ S1”;S2的值為“This is a Test
審核編輯:湯梓紅
-
處理器
+關注
關注
68文章
19259瀏覽量
229651 -
芯片
+關注
關注
455文章
50714瀏覽量
423138 -
ARM
+關注
關注
134文章
9084瀏覽量
367382 -
嵌入式
+關注
關注
5082文章
19104瀏覽量
304804 -
匯編
+關注
關注
2文章
214瀏覽量
25927
發布評論請先 登錄
相關推薦
評論