久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

轉(zhuǎn)載:arm匯編b,,bl指令淺析

 堆泄露棧溢出 2015-03-12

B或BL指令引起處理器轉(zhuǎn)移到“子程序名”處開始執(zhí)行。兩者的不同之處在于BL指令在轉(zhuǎn)移到子程序執(zhí)行之前,,將其下一條指令的地址拷貝到R14(LR,鏈 接寄存器),。由于BL指令保存了下條指令的地址,因此使用指令“MOV PC ,LR”即可實現(xiàn)子程序的返回,。而B指令則無法實現(xiàn)子程序的返回,,只能實現(xiàn)單純的跳轉(zhuǎn)。用戶在編程的時候,,可根據(jù)具體應用選用合適的子程序調(diào)用語句,。

   AREA Init,CODE,READONLY  

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

.

.

bl delay                 ;調(diào)用延遲

.

.

mov pc,lr                 ;返回

下面的在BLOG中看到覺得講得比較詳細就拷過來了

ARM匯編指令的一些總結(jié)
ARM匯編指令很多,,但是真正常用的不是很多,而且需要認真琢磨的又更少了,。
比較有用的是MOV B BL LDR STR
還是通過具體匯編代碼來學習吧,。
@ disable watch dog timer      
mov   r1, #0x53000000   //立即數(shù)尋址方式 
mov   r2, #0x0 
str   r2, [r1]        
立即數(shù)尋址方式,立即數(shù)要求以“#”作前綴,,對于十六進制的數(shù),,還要求在#后面加上0x或者&。STR是比較重要的指令了,,跟它對應的是LDR,。 ARM指令集是加載/存儲型的,,也就是說它只處理在寄存器中的數(shù)據(jù)。那么對于系統(tǒng)存儲器的訪問就經(jīng)常用到STR和LDR了,。STR是把寄存器上的數(shù)據(jù)傳輸 到指定地址的存儲器上,。它的格式我個人認為很特殊:
STR(條件) 源寄存器,<存儲器地址>
比如 STR R0, [R1] ,,意思是R0-> [R1],,它把源寄存器寫在前面,跟MOV,、LDR都相反,。
LDR應該是非常常見了。LDR就是把數(shù)據(jù)從存儲器傳輸?shù)郊拇嫫魃?。而且有個偽指令也是LDR,,因此我有個百思不得其解的問題??催@段代碼:
mov r1, #GPIO_CTL_BASE 
add   r1, r1, #oGPIO_F 
ldr   r2,=0x55aa   // 0x55aa是個立即數(shù)啊,,前面加個=干什么,? 
對于當中的ldr 那句,,我就不明白了,如果你把=去掉,,是不能通過編譯的,。我查了一些資料,個人感覺知道了原因:這個=應該表示LDR不是ARM指令,,而是偽指令,。作為偽指令的時候,LDR的格式如下:
LDR 寄存器,, =數(shù)字常量/Label
它的作用是把一個32位的地址或者常量調(diào)入寄存器,。嗬嗬,那大家可能會問,,
“MOV r2,#0x55aa”也可以啊,。應該是這樣的。不過,,LDR是偽指令啊,,也就是說編譯時編譯器會處理它的。怎么處理的呢,?——規(guī)則如下:如果該數(shù)字常量 在MOV指令范圍內(nèi),,匯編器會把這個指令作為MOV。如果不在MOV范圍中,,匯編器把該常量放在程序后面,,用LDR來讀取,,PC和該常量的偏移量不能超過 4KB。
然后說一下跳轉(zhuǎn)指令,。ARM有兩種跳轉(zhuǎn)方式,。
(1) mov pc <跳轉(zhuǎn)地址〉
這種向程序計數(shù)器PC直接寫跳轉(zhuǎn)地址,能在4GB連續(xù)空間內(nèi)任意跳轉(zhuǎn),。
(2)通過 B BL BLX BX 可以完成在當前指令向前或者向后32MB的地址空間的跳轉(zhuǎn)(為什么是32MB呢,?寄存器是32位的,此時的值是24位有符號數(shù),,所以32MB),。
B是最簡單的跳轉(zhuǎn)指令。要注意的是,,跳轉(zhuǎn)指令的實際值不是絕對地址,,而是相對地址——是相對當前PC值的一個偏移量,它的值由匯編器計算得出,。
BL非常常用,。它在跳轉(zhuǎn)之前會在寄存器LR(R14)中保存PC的當前內(nèi)容。BL的經(jīng)典用法如下:
bl NEXT   ; 跳轉(zhuǎn)到NEXT 
…… 
NEXT 
…… 
mov pc, lr    ; 從子程序返回,。 
最后提一下Thumb指令,。ARM體系結(jié)構(gòu)還支持16位的Thumb指令集。Thumb指令集是ARM指令集的子集,,它保留了32位代碼優(yōu)勢的同時還大大 節(jié)省了存儲空間,。由于Thumb指令集的長度只有16位,所以它的指令比較多,。它和ARM各有自己的應用場合,。對于系統(tǒng)性能有較高要求,應使用32位存儲 系統(tǒng)和ARM指令集,;對于系統(tǒng)成本和功耗有較高要求,,應使用16位存儲系統(tǒng)和ARM指令集。 
對ARM異常(Exceptions)的理解
分類:技術(shù)筆記
畢設(shè)筆記
1.對ARM異常(Exceptions)的理解
所有的系統(tǒng)引導程序前面中會有一段類似的代碼,,如下:
.globl _start                    ,;系統(tǒng)復位位置
_start: b       reset            ;各個異常向量對應的跳轉(zhuǎn)代碼
ldr     pc, _undefined_instruction ,;未定義的指令異常
ldr     pc, _software_interrupt     ,;軟件中斷異常
ldr     pc, _prefetch_abort          ;內(nèi)存操作異常
ldr     pc, _data_abort               ,;數(shù)據(jù)異常
ldr     pc, _not_used                  ,;未使用
ldr     pc, _irq                       ;慢速中斷異常
ldr     pc, _fiq                       ;快速中斷異常

從中我們可以看出,,ARM支持7種異常,。問題時發(fā)生了異常后ARM是如何響應的呢?第一個復位異常很好理解,,它放在0x0的位置,,一上電就執(zhí)行它, 而且我們的程序總是從復位異常處理程序開始執(zhí)行的,,因此復位異常處理程序不需要返回,。那么怎么會執(zhí)行到后面幾個異常處理函數(shù)呢?
看看書后,,明白了ARM對異常的響應過程,,于是就能夠回答以前的這個疑問。
當一個異常出現(xiàn)以后,,ARM會自動執(zhí)行以下幾個步驟:
(1)把下一條指令的地址放到連接寄存器LR(通常是R14),,這樣就能夠在處理異常返回時從正確的位置繼續(xù)執(zhí)行。
(2)將相應的CPSR(當前程序狀態(tài)寄存器)復制到SPSR(備份的程序狀態(tài)寄存器)中,。從異常退出的時候,,就可以由SPSR來恢復CPSR。
(3) 根據(jù)異常類型,,強制設(shè)置CPSR的運行模式位,。
(4)強制PC(程序計數(shù)器)從相關(guān)異常向量地址取出下一條指令執(zhí)行,從而跳轉(zhuǎn)到相應的異常處理程序中,。
至于這些異常類型各代表什么,,我也沒有深究。因為平常就關(guān)心reset了,,也沒有必要弄清楚。
ARM規(guī)定了異常向量的地址:
b       reset            ,; 復位 0x0
ldr pc, _undefined_instruction ,;未定義的指令異常 0x4
ldr     pc, _software_interrupt     ;軟件中斷異常    0x8
ldr     pc, _prefetch_abort          ,;預取指令    0xc
ldr     pc, _data_abort               ,;數(shù)據(jù)        0x10
ldr     pc, _not_used                  ;未使用      0x14
ldr     pc, _irq                       ,;慢速中斷異常   0x18
ldr   pc, _fiq                       ,;快速中斷異常    0x1c
這樣理解這段代碼就非常簡單了。碰到異常時,,PC會被強制設(shè)置為對應的異常向量,,從而跳轉(zhuǎn)到相應的處理程序,然后再返回到主程序繼續(xù)執(zhí)行,。
這些引導程序的中斷向量,,是僅供引導程序自己使用的,,一旦引導程序引導Linux內(nèi)核完畢后,會使用自己的中斷向量,。
嗬嗬,,這又有問題了。比如,,ARM發(fā)生中斷(irq)的時候,,總是會跑到0x18上執(zhí)行啊。那Linux內(nèi)核又怎么能使用自己的中斷向量呢,?原因在于 Linux內(nèi)核采用頁式存儲管理,。開通MMU的頁面映射以后,CPU所發(fā)出的地址就是虛擬地址而不是物理地址,。就Linux內(nèi)核而言,,虛擬地址0x18經(jīng) 過映射以后的物理地址就是0xc000 0018。所以Linux把中斷向量放到0xc000 0018就可以了,。
MMU的兩個主要作用:
(1)安全性:規(guī)定訪問權(quán)限
(2) 提供地址空間:把不連續(xù)的空間轉(zhuǎn)換成連續(xù)的,。
第2點是不是實現(xiàn)頁式存儲的意思?

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

……

_undefined_instruction :
.word undefined_instruction

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

為了理解這個問題,,我們以未定義的指令異常為例。

當發(fā)生了這個異常后,,CPU總是跳轉(zhuǎn)到0x4,,這個地址是虛擬地址,它映射到哪個物理地址
取決于具體的映射,。
ldr pc, _undefined_instruction 
相對尋址,,跳轉(zhuǎn)到標號_undefined_instruction,然而真正的跳轉(zhuǎn)地址其實是_undefined_instruction的內(nèi)容——undefined_instruction,。那句.word的相當于:
_undefined_instruction dw undefined_instruction (詳見畢設(shè)筆記3),。
這個地址undefined_instruction到底有多遠就難說了,也許和標號_undefined_instruction在同一個頁面,,也許在 很遠的地方,。不過除了reset,其他的異常是MMU開始工作之后才可能發(fā)生的,因此undefined_instruction 的地址也經(jīng)過了MMU的映射,。
在剛加電的時候,,CPU從0x0開始執(zhí)行,MMU還沒有開始工作,,此時的虛擬地址和物理地址相同,;另一方面,重啟在MMU開始工作后也有可能發(fā)生,,如果reset也用ldr就有問題了,,因為這時候虛擬地址和物理地址完全不同。

因此,,之所以reset用b,,就是因為reset在MMU建立前后都有可能發(fā)生,而其他的異常只有在MMU建立之后才會發(fā)生,。用b reset,,reset子程序與reset向量在同一頁面,這樣就不會有問題(b是相對跳轉(zhuǎn)的),。如果二者相距太遠,,那么編譯器會報錯的


本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/yfjelley/archive/2009/08/11/4435331.aspx

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多