新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM編程進階之一-ARM匯編偽指令

        ARM編程進階之一-ARM匯編偽指令

        作者: 時間:2016-11-27 來源:網絡 收藏
        到目前為止,我們已經具備編寫較為復雜的ARM匯編程序的能力,但要編寫較為復雜且實用的程序,我們就不得不掌握ARM匯編的偽指令(pseudo-instruction)。千萬別把匯編偽操作(directive)與匯編偽指令(pseudo-instruction)弄混了,directive不會被編譯器編譯為機器指令,但pseudo-instruction會。而pseudo-instruction與指令(instruction)的區別在于,1條instruction與1條機器指令對應,而編譯器會把1條pseudo-instruction編譯為1條或多條機器指令。

        ARM匯編偽指令共4條:ldr、adr、adrl、nop

        本文引用地址:http://www.104case.com/article/201611/322178.htm

        1、ldr

        首先我們來回答“基本尋址模式與基本指令”一文中提出的問題。“如果我們需要mov r0, #10000這樣的指令,應該怎么辦?(常數10000不能在機器指令32bit中的低12bit中被表示出來)”。當你進行編譯的時候,“Error:All70E”的錯誤就會出現,如下圖。

        其實,這個問題很容易解決,只需要將mov r0, #10000換為ldr r0, =10000即可。為什么這樣就可以了呢?因為,這里的ldr r0, =10000并非我們已經學過的ldr指令,而是一條偽指令,編譯器會將這條偽指令替換為:

        ldr r0, [pc, #-4]
        DCD 10000

        DCD所分配的內存空間中存放了整數10000,該內存空間被稱為literal pool,中文名稱“文字池”。由于整個程序都是由編譯器編譯的(包括文字池的分配),所以很顯然編譯器能夠知道ldr指令在內存中的地址與文字池在內存中的位置之間的偏移量,因此編譯器就可以正確地使用以pc為基址,采用相對尋址的ldr指令將文字池中的數取出加載到寄存器r0中。由此可見,編譯器對于ldr r0, =10000這條偽指令的處理,其實質是:

        在匯編源程序時,LDR偽指令被編譯器替換成一條合適的指令和存放常數的文字池。匯編器將常量放入文字池,并使用一條程序相對偏移的LDR指令從文字池讀出常量。

        由于,4byte可以存放任何int型整數,這樣一來,常數就可以是任何int型整數,而不再受制于12bit的限制。當然此時的常數是存放在內存中的,而不是存放在機器指令的32bit編碼中的。

        額外說明:

        a)、ldr r0, [pc, #-4]中是-4,而不是+4,是由于流水線的原因(參見“流水線對PC值的影響”一文)。今后對于流水線的這種影響,我將不再予以特別說明。

        b)、從指令位置到文字池的偏移量必須小于4KB

        c)、從語法上來看,與ARM指令的LDR相比,偽指令LDR的參數有“=”號,沒有“#”號

        d)、如果常數能夠被12bit表示出來,例如:ldr r0, =0x100,那么,編譯器對該偽指令的處理,是使用MOV(或者MVN)指令代替該LDR偽指令,例如:mov r0, #0x100,而不會采用ldr指令+文字池的方式。

        除了 ldr 寄存器, =常數 這種形式外,還有ldr 寄存器, =標號 這種形式也經常被使用,下面我就來講解這種形式的ldr偽指令。

        由上圖可見:ldr pc, =InitStack這條偽指令的作用是將標號InitStack所代表的地址賦予pc。 這里會使我們產生幾個疑問:

        a)、為什么不使用bl InitStack,而要使用ldr pc, =InitStack?

        這是因為bl指令的跳轉范圍是正負32M,而InitStack所代表的位置有可能距離ldr pc, =InitStack超過32M,此時bl就無能為力了。竟然存在這么大范圍跳轉的程序(這似乎意味著編譯出來的二進制可執行文件的大小會操作32M),這一點似乎令我們感到非常震驚。事實上是:大小超過32M的可執行程序的確幾乎不可能出現,但即使是很小的二進制程序中也可能進行大范圍(超過32M)的跳轉,這一點在bootloader程序中幾乎是必然的。


        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 广汉市| 中阳县| 峡江县| 伽师县| 泾阳县| 临颍县| 宁蒗| 彭州市| 新营市| 顺昌县| 资源县| 怀柔区| 长春市| 绥江县| 富宁县| 尚义县| 黎城县| 夏邑县| 南平市| 海安县| 新巴尔虎左旗| 拉萨市| 青川县| 上栗县| 敖汉旗| 宜良县| 宣城市| 昭苏县| 泗水县| 沙田区| 醴陵市| 香港| 铜梁县| 正蓝旗| 广东省| 日土县| 嘉黎县| 长白| 海兴县| 穆棱市| 梁山县|