<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 嵌入式Linux+ARMARM體系結構與編程(ARM匯編指令)

嵌入式Linux+ARMARM體系結構與編程(ARM匯編指令)

作者: 時(shí)間:2016-11-09 來(lái)源:網(wǎng)絡(luò ) 收藏
自己的一些簡(jiǎn)單的總結,也是最常用的ARM匯編指令,之后也會(huì )不斷的補充完善。

1.匯編系統預定義的段名

本文引用地址:http://dyxdggzs.com/article/201611/317792.htm

.text @代碼段
.data @初始化數據段
.bss @未初始化數據段
需要注意的是,源程序中.bss段應該在.text之前。

2.定義入口點(diǎn)
編程序的缺省入口是 start標號,用戶(hù)也可以在連接腳本文件中用ENTRY標志指明其它入口點(diǎn)。

.text

.global _start

_start:

3 .word用法

word expression就是在當前位置放一個(gè)word型的值,這個(gè)值就是expression
舉例來(lái)說(shuō),

_rWTCON:

.word 0x15300000
就是在當前地址,即_rWTCON處放一個(gè)值0x15300000

4.equ賦值操作,相當于c語(yǔ)言的宏定義

.equ MEM_CTRL_BASE, 0x48000000 //注意要加,號

5. 邏輯指令

AND―――――邏輯"與"操作指令

指令格式:
AND{cond}{S} Rd,Rn,operand2
AND指令將操作數operand2 與Rn 的值按位邏輯"與",結果存放到目的寄存器Rd 中。若設置S,則根據運算結果影響N、Z位,在計算第二操作數時(shí),更新C位,不影響V位(指令ORR、EOR、BIC 對標志位的影響同AND 指令)。
指令示例:
ANDS R1,R1,R2 ;R1=R1&R2,并根據運算的結果更新標志位
AND R0,R0,#0x0F ;R0=R0&0x0F,取出R0最低4位數據。
ORR―――――邏輯"或"操作指令
指令格式:ORR{cond}{S} Rd,Rn,operand2 ORR指令將操作數operand2 與Rn 的值按位邏輯"或",結果存放到目的寄存器Rd 中。指令示例:
ORRS R1,R1,R2 ;R1=R1|R2,并根據運算的結果更新標志位
ORR R0,R0,#0x0F ;R0=R0|0x0F,將R0最低4位置1,其余位不變。
BIC―――――位清除指令
指令格式:
BIC{cond}{S} Rd,Rn,operand2
BIC指令將Rn 的值與操作數operand2 的反碼按位邏輯"與",結果存放到目的寄存器Rd 中。
指令示例:BIC R0,R0,#0x0F ;將R0最低4位清零,其余位不變。
CMP―――――比較指令
指令格式:
CMP{cond} Rn,operand2
CMP指令用Rn的值減去操作數operand2 ,并將結果的狀態(tài)(Rn 與operand2比較是大、小、相等)反映在CPSR中,以便后面的指令根據條件標志決定程序的走向。CMP指令與SUBS指令完成的操作一樣,只是CMP指令只減,不存結果。
指令示例:
cmp R0,R1 ;比較R0,R1
beq stop ;R0=R1跳到stop
blt less ;R0
Less:...
Stop:...

參考:

http://blog.csdn.net/denlee/article/details/2501182

嵌入式開(kāi)發(fā)中,匯編程序常常用于非常關(guān)鍵的地方,比如系統啟動(dòng)時(shí)的初始化,進(jìn)出中斷時(shí)的環(huán)境保存、恢復,對性能要求非??量痰暮瘮档?。

1、相對跳轉指令:b、bl
不同之處在于:bl指令除了跳轉之外,還將返回地址(bl的下一條指令的地址)保存在lr寄存器中。
跳轉范圍:當前指令的前后32M。
它們是與位置無(wú)關(guān)的指令。
示例:
b fun1
......
fun1:
bl fun2
......
fun2:
......


2、數據傳送指令:mov,地址讀取偽指令:ldr
mov指令可以把一個(gè)寄存器的值賦給另一個(gè)寄存器,或者把一個(gè)常數賦給寄存器。
例:
mov r1, r2
mov r1, #4096
mov指令傳送的常數必須能用立即數來(lái)表示。
當不知道一個(gè)數能否用立即數來(lái)表示時(shí),可以使用ldr命令來(lái)賦值。ldr是偽指令,它不是真實(shí)存在的指令,編譯器會(huì )把它擴展成真正的指令:如果該常數能用立即數來(lái)表示,則使用mov指令;否則編譯時(shí)將該常數保存在某個(gè)位置,使用內存讀取指令把它讀出來(lái)。
例:
ldr r1, =4097
ldr本意為“大范圍的地址讀取偽指令”,以下是獲得代碼的絕對地址:
例:
ldr r1, =label
label:
......


3、內存訪(fǎng)問(wèn)指令:ldr、str、ldm、stm
ldr指令既可能是大范圍的地址讀取偽指令,也可能是內存訪(fǎng)問(wèn)指令。當它的第二個(gè)參數前面有“ = ”時(shí),表示偽指令,否則表示內存訪(fǎng)問(wèn)指令。
ldr指令是從內存中讀取數據到寄存器,str指令把寄存器的值存儲到內存中,它們操作的數據都是32位的。
例:
ldr r1, [r2, #4] // 將地址為r2+4的內存單元數據讀取到r1中
ldr r1, [r2] // 將地址為r2的內存單元數據讀取到r1中
ldr r1, [r2], #4 // 將地址為r2的內存單元數據讀取到r1中,然后r2=r2+4
str r1, [r2, #4] // 將r1的數據保存到地址為r2+4的內存單元中
str r1, [r2] // 將r1的數據保存到地址為r2的內存單元中
str r1, [r2], #4 // 將r1的數據保存到地址為r2的內存單元中,然后r2=r2+4
ldm和stm屬于批量?jì)却嬖L(fǎng)問(wèn)指令,只用一條指令就可以讀寫(xiě)多個(gè)數據。格式為:
ldm {cond} { ! } { ^ }
stm {cond} { ! } { ^ }
其中,{cond}表示指令的執行條件有:

條件碼(cond)

助記符

含義

cpsr中條件標志位

0000

eq

相等

Z = 1

0001

ne

不相等

Z = 0

0010

cs/hs

無(wú)符號數大于/等于

C = 1

0011

cc/lo

無(wú)符號數小于

C = 0

0100

mi

負數

N = 1

0101

pl

非負數

N = 0

0110

vs

上溢出

V = 1

0111

vc

沒(méi)有上溢出

V = 0

1000

hi

無(wú)符號數大于

C = 1或Z = 0

1001

ls

無(wú)符號數小于等于

C = 0或Z = 1

1010

ge

帶符號數大于等于

N = 1, V = 1或N = 0, V = 0

1011

lt

帶符號數小于

N = 1, V = 0或N = 0, V = 1

1100

gt

帶符號數大于

Z = 0且N = V

1101

le

帶符號數小于/等于

Z = 1或N! = V

1110

al

無(wú)條件執行

-

1111

nv

從不執行

-

大多數ARM指令都可以條件執行,即根據cpsr寄存器中的條件標志位決定是否執行該指令:如果條件不滿(mǎn)足,該指令相當于一條nop指令。
每條ARM指令包含4位的條件碼域,這表明可以定義16個(gè)執行條件。
cpsr條件標志位N、Z、C、V分別表示Negative、Zero、Carry、oVerflow。

表示地址變化模式,有4種方式:
ia (Increment After) :事后遞增方式。
ib (Increment Before) :事先遞增方式。
da (Decrement After) :事后遞減方式。
db (Decrement Before):事先遞減方式。
中保存內存的地址,如果后面加上感嘆號,指令執行后,rn的值會(huì )更新,等于下一個(gè)內存單元的地址。
表示寄存器列表,對于ldm指令,從所對應的內存塊中取出數據,寫(xiě)入這些寄存器;對于stm指令,把這些寄存器的值寫(xiě)入所對應的內存塊中。
{^}有兩種含義:
如果中有pc寄存器,它表示指令執行后,spsr寄存器的值將自動(dòng)到cpsr寄存器中——這常用于從中斷處理函數中返回;
如果中沒(méi)有pc寄存器,{^}表示操作的是用戶(hù)模式下的寄存器,而不是當前特權模式的寄存器。
例:
HandleIRQ: @中斷入口函數
sub lr, lr, #4 @計算返回地址
stmdb sp!, { r0 - r12, lr } @保存使用的寄存器
@r0 - r12, lr被保存在sp表示的內存中
@“!”使得指令執行后sp = sp - 14 * 4

ldr lr, =int_return @設置調用IRQ_Handle函數后的返回地址
ldr pc, =IRQ_Handle @調用中斷分發(fā)函數
int_return:
ldmia sp!, { r0 - r12, pc }^ @中斷返回,“^”表示將spsr的值到cpsr
@于是從irq模式返回被中斷的工作模式
@“!”使得指令執行后sp = sp + 14 * 4


4、加減指令:add、sub
例:
add r1, r2, #1 // r1 = r2 + 1
sub r1, r2, #1 // r1 = r2 - 1


5、程序狀態(tài)寄存器的訪(fǎng)問(wèn)指令:msr、mrs
ARM處理器有一個(gè)程序狀態(tài)寄存器(cpsr),它用來(lái)控制處理器的工作模式、設置中斷的總開(kāi)關(guān)。
例:
msr cpsr, r0 // r0到cpsr中
mrs r0, cpsr // cpsr到r0中

6、其他偽指令
.extern : 定義一個(gè)外部符號(可以是變量也可以是函數)
.text : 表示現在的語(yǔ)句都屬于代碼段
.global : 將本文件中的某個(gè)程序標號定義為全局的


ARM-THUMB子程序調用規則:ATPCS
為了使C語(yǔ)言程序和匯編程序之間能夠互相調用,必須為子程序間的調用制定規則,在A(yíng)RM處理器中,這個(gè)規則被稱(chēng)為ATPCS:ARM程序和THUMB程序中子程序調用的規則?;镜腁TPCS規則包括寄存器使用規則、數據棧使用規則、參數傳遞規則。

1、寄存器使用規則
子程序間通過(guò)寄存器r0 ~ r3來(lái)傳遞參數,這時(shí)可以使用它們的別名a1 ~ a4。被調用的子程序返回前無(wú)需恢復r0 ~ r3的內容。
在子程序中,使用r4 ~ r11來(lái)保存局部變量,這時(shí)可以使用它們的別名v1 ~ v8。如果在子程序中使用了它們的某些寄存器,子程序進(jìn)入時(shí)要保存這些寄存器的值,在返回前恢復它們;對于子程序中沒(méi)有使用到的寄存器,則不必進(jìn)行這些操作。在THUMB程序中,通常只能使用寄存器r4 ~ r7來(lái)保存局部變量。
寄存器r12用作子程序間scratch寄存器,別名為ip。
寄存器r13用作數據棧指針,別名為sp。在子程序中寄存器r13不能用作其他用途。它的值在進(jìn)入、退出子程序時(shí)必須相等。
寄存器r14稱(chēng)為連接寄存器,別名為lr。它用于保存子程序的返回地址。如果在子程序中保存了返回地址(比如將lr值保存到數據棧中),r14可以用作其他用途。
寄存器r15是程序計數器,別名為pc。它不能用作其他用途。

寄存器

別名

使用規則

r15

pc

程序計數器

r14

lr

連接寄存器

r13

sp

數據棧指針

r12

ip

子 程序內部調用的scratch寄存器

r11

v8

ARM狀態(tài)局部變量寄存器8

r10

v7、s1

ARM狀態(tài)局部變量寄存器7、在支持數據棧檢查的ATPCS中為數據棧限制指針

r9

v6、sb

ARM狀態(tài)局部變量寄存器6、在支持RWPI的ATPCS中為靜態(tài)基址寄存器

r8

v5

ARM狀態(tài)局部變量寄存器5

r7

v4、wr

ARM狀態(tài)局部變量寄存器4、THUMB狀態(tài)工作寄存器

r6

v3

ARM狀態(tài)局部變量寄存器3

r5

v2

ARM狀態(tài)局部變量寄存器2

r4

v1

ARM狀態(tài)局部變量寄存器1

r3

a4

參數/結果/scratch寄存器4

r2

a3

參數/結果/scratch寄存器3

r1

a2

參數/結果/scratch寄存器2

r0

a1

參數/結果/scratch寄存器1


2、數據棧使用規則
數據棧有兩個(gè)增長(cháng)方向:向內存地址減小的方向增長(cháng)時(shí),稱(chēng)為DESCENDING棧;向內存地址增加的方向增長(cháng)時(shí),稱(chēng)為ASCENDING棧。
所謂數據棧的增長(cháng)就是移動(dòng)棧指針。當棧指針指向棧頂元素(最后一個(gè)入棧的數據)時(shí),稱(chēng)為FULL棧;當棧指針指向棧頂元素(最后一個(gè)入棧的數據)相鄰的一個(gè)空的數據單元時(shí),稱(chēng)為EMPTY棧。
則數據??梢苑譃?種:
FD:Full Descending 滿(mǎn)遞減
ED:Empty Descending 空遞減
FA :Full Ascending 滿(mǎn)遞增
EA:Empty Ascending 空遞增
ATPCS規定數據棧為FD類(lèi)型,并且對數據棧的操作是8字節對齊的。使用stmdb / ldmia批量?jì)却嬖L(fǎng)問(wèn)指令來(lái)操作FD數據棧。
使用stmdb命令往數據棧中保存內容時(shí),先遞減sp指針,再保存數據,使用ldmia命令從數據棧中恢復數據時(shí),先獲得數據,再遞增sp指針,sp指針總是指向棧頂元素,這剛好是FD棧的定義。

3、參數傳遞規則
一般地,當參數個(gè)數不超過(guò)4個(gè)時(shí),使用r0 ~ r3這4個(gè)寄存器來(lái)傳遞參數;如果參數個(gè)數超過(guò)4個(gè),剩余的參數通過(guò)數據棧來(lái)傳遞。
對于一般的返回結果,通常使用r0 ~ r3來(lái)傳遞。
例:
假設CopyCode2SDRAM函數是用C語(yǔ)言實(shí)現的,它的數據原型如下:
int CopyCode2SDRAM( unsigned char *buf, unsigned long start_addr, int size )
在匯編代碼中,使用下面的代碼調用它,并判斷返回值:
ldr r0, =0x30000000 @1. 目標地址 = 0x30000000,這是SDRAM的起始地址
mov r1, #0 @2. 源地址 = 0
mov r2, #16*1024 @3. 長(cháng)度 = 16K
bl CopyCode2SDRAM @調用C函數CopyCode2SDRAM
cmp a0, #0 @判斷函數返回值



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>