在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

深度剖析ARM跳轉指令

汽車電子技術 ? 來源:宅學部落 ? 作者:王利濤 ? 2023-02-17 09:37 ? 次閱讀

跳轉指令

順序、選擇、循環是構建程序的基本結構,任何一個邏輯復雜的程序基本上都可以由這三種程序結構組合而成。而跳轉指令,則在子程序調用、選擇、循環程序結構中被大量使用。程序的跳轉是如何實現的呢?在了解這個機制之前,我們需要先了解一下程序計數器PC。

程序計數器PC,是CPU寄存器列表中最重要的一個寄存器。它就像一桿槍,指哪打哪:你給PC指針賦值哪個地址,CPU就會到PC指針指向的這個地址去取指令、翻譯指令、執行指令。一般情況下,當你沒有給PC指針賦新地址時,CPU在PC指針指向的地址取完指令后,PC計數器會自動加一,指向下一條指令,程序可以自動執行下去。當我們需要跳轉時,可以直接給PC指針賦一個新地址,于是CPU就會跳轉到新地址去執行了。

ARM中,常見的跳轉指令有B、BL、MOV、LDR等。不同的指令,它們的使用條件、使用場合是不同的,今天就給大家總結一下它們的區別及各自使用的場合。

1B跳轉指令

B指令是ARM中最基本的跳轉指令,它的使用方法如下:

B label

上面語句表示跳轉到label的標號處去執行。B跳轉指令是ARM中最簡單的指令,只是單純的跳轉,而且是相對跳轉。它可以跳到以當前位置PC為基址,前后32MB的地址空間范圍,所以B指令只是在臨近的代碼塊、標號之間跳轉。

B指令跳轉,大多數時候是單向的,跳過去就不再返回來了。但是我們可以通過添加一些標號來實現一些控制邏輯:比如循環、選擇程序結構:

;循環結構示例
LOOP
    SUB R0,R0,#1
    ...
    CMP R0,#0
    BNE LOOP
;選擇結構示例
    MOV R1,#10
    MOV R2,#20
    CMP R1,R2
    BEQ HERE
    ...
    B END 
HERE
    ...
END
    ...

在上面的程序中,我們使用B跳轉指令實現了選擇、循環這兩種基本的程序結構。B指令像ARM的其它指令一樣,可以根據CPSR狀態寄存器的標志位,有條件的執行。這樣,可以減少指令數目、提高代碼密度和運行效率。如BNE、BEQ就是當結果相等、不相等時的條件跳轉。

當前程序狀態寄存器:

圖片

各種各樣的條件碼:

圖片

2BL指令

BL指令跟B不同:在跳轉之前,會先將當前指令的下一條指令地址保存到LR寄存器中,然后才跳轉到標號執行。這樣做的好處是:當我們想從標號地方返回時,可以直接將LR寄存器中的返回地址賦值給PC,程序就可以返回到原來的程序中繼續執行了。

BL跳轉指令一般用在子程序的調用中。無論是匯編語言子程序,還是C語言子程序,在跳轉到子程序之前,都要將返回地址保存起來。當子程序執行完畢,將LR寄存器保存的返回地址,重新賦值給PC,處理器就可以返回到主程序繼續執行了。

BEGIN
    MOV R0,#SRC
    MOV R1,#DST
    MOV R2,#100
    BL COPY
    NOP
    ...
 COPY
    SUB R2,R2,#1
    LDR R3,[R0],#1
    STR R3,[R1],#1
    CMP R2,#0
    BNE COPY
    MOV PC,LR

上面的匯編代碼段,我們定義了一個匯編子程序COPY,實現了數據拷貝的功能。當我們使用BL指令調用這個子程序COPY時,CPU會首先將當前指令的下一條指令:NOP 的地址保存到LR寄存器中,然后才跳轉到COPY子程序去執行。在COPY子程序中,處理完數據搬運后,通過

MOV PC,LR

這條語句,將保存在LR寄存器中的返回地址,重新賦值給PC,這樣我們就可以返回到原來的程序中繼續執行了。

在上面的匯編代碼中,LR,即R14,連接寄存器,常用來存放程序的返回地址;PC,即R15,程序計數器,表示當前指令地址。LR和PC都是ARM匯編器為了方便程序員編程,預定義的一些宏。你在程序中使用這些助記符其實就是相當于操作R14和R15寄存器。除此之外,ARM中常用的助記符有:

  • FP:棧幀基址寄存器,即R12
  • SP:棧指針寄存器,即R13
  • LR:鏈接寄存器,即R14
  • PC:程序計數器,即R15

同樣,在C語言調用子函數的過程中,在跳轉子函數執行之前,CPU也會將當前指令的下一條指令地址保存到LR寄存器中,然后再跳轉到子函數中執行。因為在子函數運行過程中,也有可能會用到ARM的一些寄存器,也有可能會調用其它的子函數,會覆蓋掉保存在LR寄存器中的返回地址,所以,我們一般在運行子函數之前,會首先將LR寄存器壓入子函數的棧幀,相當于將返回地址保存到了棧上。當子函數運行結束時,再通過出棧操作,將保存在棧中的返回地址彈出到PC指針中,這樣程序就成功從子程序中返回了,直接返回到原來的函數中繼續執行。

int main(void)
{
    func();
    printf("Hello!\\n");
    return 0;
} 
;對應的匯編代碼
main
    BL func
    BL printf
func
    PUSH LR
    ...
    pop pc 
;func子函數返回

3MOV指令

通過上面的學習,我們可以看到,無論是B指令、還是BL指令,都是相對尋址。其本質都是以當前指令地址PC為基址,然后加上一個[0,32M]的偏移,達到修改PC的目的。

除此之外,我們也可以直接給PC指針賦值,達到跳轉的目的。如上面的 func 子程序返回,就是直接通過

MOV PC,LR

這條指令,將LR寄存器中的返回地址,直接賦值給PC,直返回到原來的主函數去執行。

MOV指令主要用來在寄存器之間傳輸數據,或者將一個立即數傳送到寄存器。但是MOV指令有一個硬傷,就是傳遞的立即數只能是8位數,有大小的限制。這是為什么呢?很簡單,ARM是RISC架構,在一個32位的ARM中,指令通常都是32位的。而一個指令中,通常要包括操作碼+操作數,如下圖:

圖片

一條指令,總共有32個bit空間,MOV這個操作碼要占幾位吧,Rd寄存器編碼要占據幾位吧,剩下的留給立即數的空間就不多了,所以這也就限定了MOV指令能傳遞的立即數的大小了。而一般的32位程序中,無論是變量還是函數,它們的地址一般都是32位的,如果使用MOV指令,將他們的地址傳送到PC,使用下面的形式:

MOV PC,#0x30008000

你會發現,立即數#0X30008000這個地址就已經32位了,在加上MOV指令這個操作碼,已經超過32位了,編譯器是無法翻譯這個指令的,所以說,當一個變量或函數地址為32位時,使用MOV指令給PC直接賦值,行不通,那怎么辦呢?

4LDR偽指令

辦法總是有的,比如,我們就可以通過偽指令LDR,直接將一個32位的立即數地址,傳送到PC:

LDR PC,=0x30008000

LDR偽指令的功能和MOV一樣,都可以將一個立即數傳送到寄存器。唯一區別的就是,MOV指令只能傳送8位的,而LDR可以傳送一個32位的立即數或地址。

這里需要注意一下,立即數 0X30008000 的前面有一個等于號“=”,這表示前面的LDR指令是一個偽指令。除此之外,在ARM中,LDR還有另外一個意思,用來將內存中的數據加載到寄存器。我們知道,ARM是RISC架構,使用LDR/STR架構,不能直接修改內存中的數據。如果我們要修改內存中的一個變量,要首先使用LDR指令將內存中的變量加載到寄存器中,接著對寄存器進行操作,最后再使用STR指令將寄存器中的變量回寫到內存中。所以,LDR可以看作是一個偽指令,也可以看做是普通的一個LDR指令,判定他們的區別就是看前面的等于號。

普通的LDR指令主要使用寄存器間接尋址,常用的使用方式如下:

LDR R0,[R1]
LDR R0,0x30008000

這里注意后面一句,是將地址0x30008000地址上的內容傳動到寄存器R0,而不是直接將這個地址傳送到R0,這里一定要注意其跟LDR偽指令的區別,這一點沒有注意到,你在分析程序時就可能誤入歧途了。

在《C語言嵌入式Linux高級編程》第二期中,我們已經探討了CPU、指令集、偽指令的基本概念,這里就不贅述了。簡單來說,偽指令并不是真正的ARM指令,并不屬于ARM指令集中的標準指令。它只是編譯器為了方便我們程序員開發程序,定義的一些助記符。在編譯時,這些偽指令還是會使用指令集中的標準指令來實現。

比如上面的LDR偽指令,程序在編譯時,看到這個偽指令,會使用ARM指令集中標準的指令實現。如果LDR偽指令中的立即數小于8位,它就會轉換為MOV指令來實現:

LDR R0,=200
MOV R0,#200

如果LDR偽指令中,立即數大于8bit表示的數據范圍,比如說是一個32位的立即數或地址,那就不能使用MOV指令來實現了,可以采用文字池的形式,先將這個地址常量單獨存放在存儲單元中,然后使用相對尋址,曲線救國,完成這個32位地址或立即數與寄存器之間的傳輸,這些細節在教程視頻中都有講到,就不再贅述了。

5小結

通過上面的學習,我們基本上理清了ARM系統中常見的幾種跳轉指令,以及它們的區別。只有徹底理解他們的底層機制及實現細節,才有可能在使用反匯編分析程序時,達到事半功倍的效果,從而大大提高我們的工作效率。否則,這些基本的細節和概念搞不清,將會永遠成為你學習和工作上的障礙。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 計數器
    +關注

    關注

    32

    文章

    2261

    瀏覽量

    94983
  • 程序結構
    +關注

    關注

    1

    文章

    7

    瀏覽量

    6946
  • 程序調用
    +關注

    關注

    0

    文章

    3

    瀏覽量

    837
收藏 人收藏

    評論

    相關推薦

    c語言深度剖析

    c語言深度剖析
    發表于 04-02 09:12

    C語言深度剖析

    C語言深度剖析
    發表于 08-25 09:08

    C語言深度剖析

    C語言深度剖析[完整版].pdfC語言深度剖析[完整版].pdf (919.58 KB )
    發表于 03-19 05:11

    arm匯編跳轉指令總結

    目前所知道的跳轉指令有 b,bl,bep,bne.他們共同點是都是以b開頭,首先從字面上分析:b:是Branch,表示分支。bl:是Branch Link表示帶連接的分支。bep:Branch
    發表于 04-26 02:39

    請問一下ARM跳轉指令的范圍是多少

    , ?]構造跳轉指令。)B,BL指令保存的是偏移地址,這個地址的計算方法是:假設跳轉指令處的地址是A,
    發表于 04-14 09:30

    請問一下ARM匯編中的B跳轉指令和LDR跳轉的區別在哪

    請問一下ARM匯編中的B跳轉指令和LDR跳轉的區別有哪些不同之處呢?
    發表于 07-21 15:57

    ARM匯編語言跳轉指令的特殊用法還有嗎

    關于 ARM匯編語言跳轉指令的特殊用法。有如下兩條跳轉指令: beq lablefbeq lableb其中 lable 為某段程序的標號,b
    發表于 10-31 15:30

    arm匯編語言跳轉指令有何特殊用法呢?

    關于 ARM 匯編語言跳轉指令的特殊用法。有如下兩條跳轉指令: beq lablefbeq lableb其中 lable 為某段程序的標號,
    發表于 02-24 15:28

    arm指令集(1)

    arm指令集(1)  ARM跳轉指令可以從當前指令向前或向后的32MB地址空間
    發表于 03-02 15:46 ?79次下載

    ARM指令集(2)

    ARM指令集(2)  1.跳轉指令   在ARM中有兩種方式可以實現程序的跳轉:一種是刀
    發表于 03-02 15:49 ?68次下載

    Thumb指令集之Thumb跳轉指令

    Thumb指令集中的跳轉指令分以下6種類型。 ① 無條件跳轉,其跳轉空間為2KB。 ② 條件跳轉
    發表于 10-19 10:04 ?1次下載
    Thumb<b class='flag-5'>指令</b>集之Thumb<b class='flag-5'>跳轉</b><b class='flag-5'>指令</b>

    跳轉指令B及帶連接的跳轉指令BLX上 

    跳轉(B)和跳轉連接(BL)指令是改變指令執行順序的標準方式。ARM一般按照字地址順序執行指令
    發表于 10-19 10:26 ?2次下載
    <b class='flag-5'>跳轉</b><b class='flag-5'>指令</b>B及帶連接的<b class='flag-5'>跳轉</b><b class='flag-5'>指令</b>BLX上 

    ARM嵌入式系統的中斷服務例程跳轉

    在32位 ARM 系統中,一般都是在中斷向量表中放置一條分支指令或PC寄存器加載指令,實現 程序跳轉 到 中斷服務 例程的功能。例如: IRQEntry B HandleIRQ ;
    發表于 04-10 10:11 ?2840次閱讀

    PLC跳轉/標號指令的工作原理及應用舉例

    跳轉/標號執行是用來跳過部分程序使其不執行必須用在同一程序塊內部實現跳轉跳轉/標號指令有兩條,分別為跳轉
    的頭像 發表于 10-08 09:59 ?6014次閱讀

    西門子博途SCL的GOTO跳轉指令

    跳轉標簽和“跳轉指令必須在同一個塊中。在一個塊中,跳轉標簽的名稱只能指定一次。每個跳轉標簽可以是多個
    發表于 07-03 14:53 ?8611次閱讀
    主站蜘蛛池模板: 国产美女激情视频 | 高h水果榨汁play男男 | 在线视频亚洲欧美 | 手机在线观看视频你懂的 | 国产午夜精品久久久久免费视 | 国产精品美女一区二区三区 | 又黑又长黑人欧美三级 | 如果我们是季节韩剧在线观看 | 亚洲最大成人在线 | 天天干人人干 | 欧美αv| 色四虎| 一级特黄女毛毛片 | 天堂男人网 | 韩国三级久久精品 | 免费看污视频的网站 | 狠狠色视频 | 手机看高清特黄a大片 | 性色欧美| 成年人在线网站 | 国产香蕉在线精彩视频 | 国产精品秒播无毒不卡 | 亚洲国产高清精品线久久 | 天堂最新资源在线 | 奇米久草| 天堂资源在线官网资源 | 国产精品久久久久久久成人午夜 | 国产深夜福利在线观看网站 | 黄色毛片基地 | 最新久久免费视频 | 欧美在线黄色 | 狠狠躁夜夜躁人人爽天天段 | 波多野结衣50连精喷在线 | 国产中日韩一区二区三区 | 黄色毛片播放 | 中文字幕一区二区三区在线不卡 | 首页 亚洲 欧美 制服 丝腿 | 四虎国产精品永久在线 | 久久电影www成人网 久久电影福利 | 日本国产在线 | 亚洲αv久久久噜噜噜噜噜 亚洲аv电影天堂网 |