<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è) > 嵌入式系統 > 設計應用 > ARM學(xué)習b,bl指令淺析

ARM學(xué)習b,bl指令淺析

作者: 時(shí)間:2016-11-21 來(lái)源:網(wǎng)絡(luò ) 收藏
B或BL指令引起處理器轉移到“子程序名”處開(kāi)始執行。兩者的不同之處在于BL指令在轉移到子

程序執行之前,將其下一條指令的地址拷貝到R14(LR,鏈接寄存器)。由于BL指令保存了下條指令的地

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

址,因此使用指令“MOV PC ,LR”即可實(shí)現子程序的返回。而B(niǎo)指令則無(wú)法實(shí)現子程序的返回,只能實(shí)

現單純的跳轉。用戶(hù)在編程的時(shí)候,可根據具體應用選用合適的子程序調用語(yǔ)句。

AREA Init,CODE,READONLY

;該偽指令定義了一個(gè)代碼段,段名為Init,屬性只讀
ENTRY ;程序的入口點(diǎn)標識

.

.

bl delay ;調用延遲

.

.

mov pc,lr ;返回

下面的在BLOG中看到覺(jué)得講得比較詳細就拷過(guò)來(lái)了

ARM匯編指令的一些總結
ARM匯編指令很多,但是真正常用的不是很多,而且需要認真琢磨的又更少了。
比較有用的是MOV B BL LDR STR
還是通過(guò)具體匯編代碼來(lái)學(xué)習吧。
@ disable watch dog timer
mov r1, #0x53000000 //立即數尋址方式
mov r2, #0x0
str r2, [r1]
立即數尋址方式,立即數要求以“#”作前綴,對于十六進(jìn)制的數,還要求在#后面加上0x或者&。STR是

比較重要的指令了,跟它對應的是LDR。ARM指令集是加載/存儲型的,也就是說(shuō)它只處理在寄存器中的

數據。那么對于系統存儲器的訪(fǎng)問(wèn)就經(jīng)常用到STR和LDR了。STR是把寄存器上的數據傳輸到指定地址的

存儲器上。它的格式我個(gè)人認為很特殊:
STR(條件) 源寄存器,<存儲器地址>
比如 STR R0, [R1] ,意思是R0-> [R1],它把源寄存器寫(xiě)在前面,跟MOV、LDR都相反。
LDR應該是非常常見(jiàn)了。LDR就是把數據從存儲器傳輸到寄存器上。而且有個(gè)偽指令也是LDR,因此我有

個(gè)百思不得其解的問(wèn)題??催@段代碼:
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_F
ldr r2,=0x55aa // 0x55aa是個(gè)立即數啊,前面加個(gè)=干什么?
對于當中的ldr 那句,我就不明白了,如果你把=去掉,是不能通過(guò)編譯的。我查了一些資料,個(gè)人感

覺(jué)知道了原因:這個(gè)=應該表示LDR不是ARM指令,而是偽指令。作為偽指令的時(shí)候,LDR的格式如下:
LDR 寄存器, =數字常量/Label
它的作用是把一個(gè)32位的地址或者常量調入寄存器。嗬嗬,那大家可能會(huì )問(wèn),
“MOV r2,#0x55aa”也可以啊。應該是這樣的。不過(guò),LDR是偽指令啊,也就是說(shuō)編譯時(shí)編譯器會(huì )處理

它的。怎么處理的呢?——規則如下:如果該數字常量在MOV指令范圍內,匯編器會(huì )把這個(gè)指令作為MOV

。如果不在MOV范圍中,匯編器把該常量放在程序后面,用LDR來(lái)讀取,PC和該常量的偏移量不能超過(guò)

4KB。
然后說(shuō)一下跳轉指令。ARM有兩種跳轉方式。
(1) mov pc <跳轉地址〉
這種向程序計數器PC直接寫(xiě)跳轉地址,能在4GB連續空間內任意跳轉。
(2)通過(guò) B BL BLX BX 可以完成在當前指令向前或者向后32MB的地址空間的跳轉(為什么是32MB呢?

寄存器是32位的,此時(shí)的值是24位有符號數,所以32MB)。
B是最簡(jiǎn)單的跳轉指令。要注意的是,跳轉指令的實(shí)際值不是絕對地址,而是相對地址——是相對當前

PC值的一個(gè)偏移量,它的值由匯編器計算得出。
BL非常常用。它在跳轉之前會(huì )在寄存器LR(R14)中保存PC的當前內容。BL的經(jīng)典用法如下:
bl NEXT ; 跳轉到NEXT
……
NEXT
……
mov pc, lr ; 從子程序返回。
最后提一下Thumb指令。ARM體系結構還支持16位的Thumb指令集。Thumb指令集是ARM指令集的子集,它

保留了32位代碼優(yōu)勢的同時(shí)還大大節省了存儲空間。由于Thumb指令集的長(cháng)度只有16位,所以它的指令

比較多。它和ARM各有自己的應用場(chǎng)合。對于系統性能有較高要求,應使用32位存儲系統和ARM指令集;

對于系統成本和功耗有較高要求,應使用16位存儲系統和ARM指令集。
對ARM異常(Exceptions)的理解
分類(lèi):技術(shù)筆記
畢設筆記
1.對ARM異常(Exceptions)的理解
所有的系統引導程序前面中會(huì )有一段類(lèi)似的代碼,如下:
.globl _start ;系統復位位置
_start: b reset ;各個(gè)異常向量對應的跳轉代碼
ldr pc, _undefined_instruction ;未定義的指令異常
ldr pc, _software_interrupt ;軟件中斷異常
ldr pc, _prefetch_abort ;內存操作異常
ldr pc, _data_abort ;數據異常
ldr pc, _not_used ;未使用
ldr pc, _irq ;慢速中斷異常
ldr pc, _fiq ;快速中斷異常

從中我們可以看出,ARM支持7種異常。問(wèn)題時(shí)發(fā)生了異常后ARM是如何響應的呢?第一個(gè)復位異常很好

理解,它放在0x0的位置,一上電就執行它,而且我們的程序總是從復位異常處理程序開(kāi)始執行的,因

此復位異常處理程序不需要返回。那么怎么會(huì )執行到后面幾個(gè)異常處理函數呢?
看看書(shū)后,明白了ARM對異常的響應過(guò)程,于是就能夠回答以前的這個(gè)疑問(wèn)。
當一個(gè)異常出現以后,ARM會(huì )自動(dòng)執行以下幾個(gè)步驟:
(1)把下一條指令的地址放到連接寄存器LR(通常是R14),這樣就能夠在處理異常返回時(shí)從正確的位置

繼續執行。
(2)將相應的CPSR(當前程序狀態(tài)寄存器)復制到SPSR(備份的程序狀態(tài)寄存器)中。從異常退出的時(shí)

候,就可以由SPSR來(lái)恢復CPSR。
(3) 根據異常類(lèi)型,強制設置CPSR的運行模式位。
(4)強制PC(程序計數器)從相關(guān)異常向量地址取出下一條指令執行,從而跳轉到相應的異常處理程

序中。
至于這些異常類(lèi)型各代表什么,我也沒(méi)有深究。因為平常就關(guān)心reset了,也沒(méi)有必要弄清楚。
ARM規定了異常向量的地址:
b reset ; 復位 0x0
ldr pc, _undefined_instruction ;未定義的指令異常 0x4
ldr pc, _software_interrupt ;軟件中斷異常 0x8
ldr pc, _prefetch_abort ;預取指令 0xc
ldr pc, _data_abort ;數據 0x10
ldr pc, _not_used ;未使用 0x14
ldr pc, _irq ;慢速中斷異常 0x18
ldr pc, _fiq ;快速中斷異常 0x1c
這樣理解這段代碼就非常簡(jiǎn)單了。碰到異常時(shí),PC會(huì )被強制設置為對應的異常向量,從而跳轉到相應的

處理程序,然后再返回到主程序繼續執行。
這些引導程序的中斷向量,是僅供引導程序自己使用的,一旦引導程序引導Linux內核完畢后,會(huì )使用

自己的中斷向量。
嗬嗬,這又有問(wèn)題了。比如,ARM發(fā)生中斷(irq)的時(shí)候,總是會(huì )跑到0x18上執行啊。那Linux內核又怎

么能使用自己的中斷向量呢?原因在于Linux內核采用頁(yè)式存儲管理。開(kāi)通MMU的頁(yè)面映射以后,CPU所

發(fā)出的地址就是虛擬地址而不是物理地址。就Linux內核而言,虛擬地址0x18經(jīng)過(guò)映射以后的物理地址

就是0xc000 0018。所以L(fǎng)inux把中斷向量放到0xc000 0018就可以了。
MMU的兩個(gè)主要作用:
(1)安全性:規定訪(fǎng)問(wèn)權限
(2) 提供地址空間:把不連續的空間轉換成連續的。
第2點(diǎn)是不是實(shí)現頁(yè)式存儲的意思?

.globl _start ;系統復位位置
_start: b reset ;各個(gè)異常向量對應的跳轉代碼
ldr pc, _undefined_instruction ;未定義的指令異常

……

_undefined_instruction :
.word undefined_instruction

也許有人會(huì )有疑問(wèn),同樣是跳轉指令,為什么第一句用的是 b reset;
而后面的幾個(gè)都是用ldr?

為了理解這個(gè)問(wèn)題,我們以未定義的指令異常為例。

當發(fā)生了這個(gè)異常后,CPU總是跳轉到0x4,這個(gè)地址是虛擬地址,它映射到哪個(gè)物理地址
取決于具體的映射。
ldr pc, _undefined_instruction
相對尋址,跳轉到標號_undefined_instruction,然而真正的跳轉地址其實(shí)是_undefined_instruction

的內容——undefined_instruction。那句.word的相當于:
_undefined_instruction dw undefined_instruction (詳見(jiàn)畢設筆記3)。
這個(gè)地址undefined_instruction到底有多遠就難說(shuō)了,也許和標號_undefined_instruction在同一個(gè)

頁(yè)面,也許在很遠的地方。不過(guò)除了reset,其他的異常是MMU開(kāi)始工作之后才可能發(fā)生的,因此

undefined_instruction 的地址也經(jīng)過(guò)了MMU的映射。
在剛加電的時(shí)候,CPU從0x0開(kāi)始執行,MMU還沒(méi)有開(kāi)始工作,此時(shí)的虛擬地址和物理地址相同;另一方

面,重啟在MMU開(kāi)始工作后也有可能發(fā)生,如果reset也用ldr就有問(wèn)題了,因為這時(shí)候虛擬地址和物理

地址完全不同。

因此,之所以reset用b,就是因為reset在MMU建立前后都有可能發(fā)生,而其他的異常只有在MMU建立之

后才會(huì )發(fā)生。用b reset,reset子程序與reset向量在同一頁(yè)面,這樣就不會(huì )有問(wèn)題(b是相對跳轉的)

。如果二者相距太遠,那么編譯器會(huì )報錯的




關(guān)鍵詞: ARM指令淺

評論


技術(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>