新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM微處理器寄存器裝載和存儲

        ARM微處理器寄存器裝載和存儲

        作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏

        傳送單一數(shù)據(jù)

        使用單一數(shù)據(jù)傳送指令(STR 和 LDR)來裝載和存儲單一字節(jié)或字的數(shù)據(jù)從/到內(nèi)存。尋址是非常靈活的。

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

        首先讓我們查看指令格式:

        LDR{條件}    Rd, <地址>STR{條件}    Rd, <地址>LDR{條件}B   Rd, <地址>STR{條件}B   Rd, <地址>
        指令格式

        這些指令裝載和存儲 Rd 的值從/到指定的地址。如果象后面兩個指令那樣還指定了‘B’,則只裝載或存儲一個單一的字節(jié);對于裝載,寄存器中高端的三個字節(jié)被置零(zeroed)。

        地址可以是一個簡單的值、或一個偏移量、或者是一個被移位的偏移量。可以還可以把合成的有效地址寫回到基址寄存器(去除了對加/減操作的需要)。

        各種尋址方式的示例: 

        譯注:下文中的 Rbase 是表示基址寄存器,Rindex 表示變址寄存器,index 表示偏移量,偏移量為 12 位的無符號數(shù)。用移位選項表示比例因子。標(biāo)準(zhǔn)尋址方式 - 用 AT&T 語法表示為 disp(base, index, scale),用 Intel 語法表示為 [base + index*scale + disp],中的變址(連帶比例因子)與偏移量不可兼得。

        STR    Rd, [Rbase]          存儲 Rd 到 Rbase 所包含的有效地址。STR    Rd, [Rbase, Rindex]  存儲 Rd 到 Rbase + Rindex 所合成的有效地址。 STR    Rd, [Rbase, #index]  存儲 Rd 到 Rbase + index 所合成的有效地址。index 是一個立即值。例如,STR Rd, [R1, #16] 將把 Rd 存儲到 R1+16。STR    Rd, [Rbase, Rindex]! 存儲 Rd 到 Rbase + Rindex 所合成的有效地址,并且把這個新地址寫回到 Rbase。STR    Rd, [Rbase, #index]! 存儲 Rd 到 Rbase + index 所合成的有效地址,并且并且把這個新地址寫回到 Rbase。STR    Rd, [Rbase], Rindex  存儲 Rd 到 Rbase 所包含的有效地址。把 Rbase + Rindex 所合成的有效地址寫回 Rbase。STR    Rd, [Rbase, Rindex, LSL #2] 存儲 Rd 到 Rbase + (Rindex * 4) 所合成的有效地址。STR    Rd, place            存儲 Rd 到 PC + place 所合成的有效地址。
        你當(dāng)然可以在這些指令上使用條件執(zhí)行。但要注意條件標(biāo)志要先于字節(jié)標(biāo)志,所以如果你希望在結(jié)果是等于的時候裝載一個字節(jié),要用的指令是LDREQB Rx, (不是LDRBEQ...)。

        如果你指定預(yù)先變址尋址(這里的基址和變址都在方括號中),用是否存在‘!’來控制寫回操作。上面的第4和第5個例子中使用了這個標(biāo)志。你可以使用它來在內(nèi)存中自動正向或反向移動。一個字符串打印例程將變成:

        .loopLDRB   R0, [R1, #1]!SWI    "OS_WriteC"CMP    R0, #0BNE    loop
        而不是:
        .loopLDRB   R0, [R1]SWI    "OS_WriteC"ADD    R1, R1, #1CMP    R0, #0BNE    loop

        對于過后變址尋址‘!’是無效的(這里的變址在方括號外面,比如上面的例子6),因為寫回是暗含的。

        如同你見到的那樣,變址可以被移位來實(shí)現(xiàn)比例縮放。除此之外,可以從基址上減去偏移量。在這種情況下,你可以使用如下代碼:

        LDRB   R0, [R1, #-1]

        盡管你可以存儲或裝載 PC,但你不可以用裝載或存儲指令來修改 PSR。要裝載一個被存儲的‘狀態(tài)’并正確的恢復(fù)它,請使用:

        LDR    R0, [Rbase]MOVS   R15, R0
        假如你在有特權(quán)的模式下,MOVS 將導(dǎo)致 PSR 的位被更改。
        對 PC 使用MOVS不遵從 32-bit 體系,你需要使用 MRS 和 MSR 來處理 PSR。

        依照 ARM 匯編手冊:

        譯注:下文所敘述內(nèi)容針對的是小端字節(jié)序配置,對大端字節(jié)序配置在手冊中另有專門敘述。

        • 如果提供的地址在一個字邊界上,則字節(jié)裝載(LDRB)使用在 0 至 7 位上的數(shù)據(jù),如果在一個字地址加上一個字節(jié)上,則使用 8 至 15 位,以此類推。選擇的字節(jié)被放入目標(biāo)寄存器的低端 8 位中,并把寄存器中其余的位用零填充。
        • 字節(jié)存儲(STRB)在數(shù)據(jù)總線上重復(fù)源寄存器的的低端 8 位 4 次。由外部的內(nèi)存系統(tǒng)來激活適當(dāng)?shù)淖止?jié)子系統(tǒng)來存儲數(shù)據(jù)。
        • 字裝載(LDR)或字存儲(STR)將生成一個字對齊的地址。使用一個非字對齊的地址將有不明顯和未規(guī)定的結(jié)果。實(shí)際上提示的是你不能使用 LDR 從一個非對齊的地址裝載一個字。

         

        傳送多個數(shù)據(jù)

        使用多數(shù)據(jù)傳送指令(LDM 和 STM)來裝載和存儲多個字的數(shù)據(jù)從/到內(nèi)存。

        LDM/STM 的主要用途是把需要保存的寄存器到棧上。如我們以前見到過的STMFD R13!, {R0-R12, R14}。

        指令格式是:

        xxM{條件}{類型}  Rn{!}, <寄存器列表>{^}

        ‘xx’是 LD 表示裝載,或 ST 表示存儲。

        再加 4 種‘類型’就變成了 8 個指令:

        棧        其他LDMED     LDMIB     預(yù)先增加裝載LDMFD     LDMIA     過后增加裝載LDMEA     LDMDB     預(yù)先減少裝載LDMFA     LDMDA     過后減少裝載 STMFA     STMIB     預(yù)先增加存儲STMEA     STMIA     過后增加存儲STMFD     STMDB     預(yù)先減少存儲STMED     STMDA     過后減少存儲
        指令格式

        匯編器關(guān)照如何映射這些助記符。注意 ED 不同于 IB;只對于預(yù)先減少裝載是相同的。在存儲的時候,ED 是過后減少的。

        FD、ED、FA、和 EA 指定是滿棧還是空棧,是升序棧還是降序棧。一個滿棧的棧指針指向上次寫的最后一個數(shù)據(jù)單元,而空棧的棧指針指向第一個空閑單元。一個降序棧是在內(nèi)存中反向增長(就是說,從應(yīng)用程序空間結(jié)束處開始反向增長)而升序棧在內(nèi)存中正向增長。

        其他形式簡單的描述指令的行為,意思分別是過后增加(Increment After)、預(yù)先增加(Increment Before)、過后減少(Decrement After)、預(yù)先減少(Decrement Before)。

        RISC OS 使用傳統(tǒng)的滿降序棧。在使用符合 APCS 規(guī)定的編譯器的時候,它通常把你的棧指針設(shè)置在應(yīng)用程序空間的結(jié)束處并接著使用一個 FD (滿降序 - Full Descending)棧。如果你與一個高級語言(BASIC 或 C)一起工作,你將別無選擇。棧指針(傳統(tǒng)上是 R13)指向一個滿降序棧。你必須繼續(xù)這個格式,或則建立并管理你自己的棧(如果你是死硬派人士那么你可能喜歡這樣做!)。

        ‘基址’是包含開始地址的寄存器。在傳統(tǒng)的 RISC OS 下,它是棧指針 R13,但你可以使用除了 R15 之外的任何可獲得的寄存器。

        如果你想把操作后棧頂?shù)漠?dāng)前的內(nèi)存地址保存到棧指針中,可以簡單的在棧指針寄存器后面設(shè)置一個寫回標(biāo)志‘!’。

        寄存器列表放在{花括號}中。不管你用什么次序在其中指定寄存器,寄存器按從最低到最高的編號次序與到從低端到高端的內(nèi)存之間傳送數(shù)據(jù)。并且因為用指令中的一個單一的位來表示是否保存一個寄存器,不可能指定某個寄存器兩次。它的副作用是不能用下面這樣的代碼:

        STMFD  R13!, {R0, R1}LDMFD  R13!, {R1, R0}
        來交換兩個寄存器的內(nèi)容。

        提供了一個有用的簡寫。要包含一個范圍的寄存器,可以簡單的只寫第一個和最后一個,并在其間加一個橫杠。例如R0-R3等同與R0, R1, R2, R3,只是更加整齊和理智而已...

        在把 R15 存儲到內(nèi)存中的時候,還保存了 PSR 位。在重新裝載 R15 的時候,除非你要求否則不恢復(fù) PSR 位。要求的方法是在寄存器列表后跟隨一個‘^’。 

        STMFD  R13!, {R0-R12, R14}...LDMFD  R13!, {R0-R12, PC}
        這保存所有的寄存器,做一些事情,接著重新裝載所有的寄存器。從 R14 裝載 PC,它由一個 BL 或此類指令所設(shè)置。不觸及 PSR 標(biāo)志。 
        STMFD  R13!, {R0-R12, R14}...LDMFD  R13!, {R0-R12, PC}^
        這保存所有的寄存器,做一些事情,接著重新裝載所有的寄存器。從 R14 裝載 PC,它由一個 BL 或此類指令所設(shè)置。變更 PSR 標(biāo)志。
        警告: 這些代碼不遵從 32 bit 體系。你需要使用 MRS 和 MSR 來處理 PSR,你不能使用‘^’后綴。

        注意在這兩個例子中,R14 被直接裝載到 PC 中。這節(jié)省了對 MOV(S) R14 到 R15 中的需要。
        警告: 使用 MOVS PC,... 不遵從 32 bit 體系。你需要使用 MRS 和 MSR 來處理 PSR。

         

        SWP : 單一數(shù)據(jù)交換

        (Swap)

        SWP{條件}{B}  , , []
        指令格式

        SWP將:

        • 從操作數(shù) 2 所指向的內(nèi)存裝載一個字并把這個字放置到目的寄存器中。
        • 把寄存器操作數(shù) 1 的內(nèi)容存儲到同一個地址中。
        如果目的和操作數(shù) 1 是同一個寄存器,則把寄存器的內(nèi)容和給定內(nèi)存位置的內(nèi)容進(jìn)行交換。
        如果提供了B后綴,則將傳送一個字節(jié),否則傳送一個字。


        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 钟山县| 沙坪坝区| 澄迈县| 西和县| 忻州市| 庄河市| 桐城市| 陈巴尔虎旗| 黄山市| 南通市| 右玉县| 类乌齐县| 阳西县| 安泽县| 海晏县| 眉山市| 上虞市| 得荣县| 张家口市| 曲麻莱县| 阳谷县| 大邑县| 甘谷县| 通榆县| 沙坪坝区| 调兵山市| 洪泽县| 温州市| 偃师市| 金乡县| 兴义市| 安顺市| 略阳县| 洛隆县| 甘谷县| 武隆县| 安福县| 调兵山市| 大厂| 大邑县| 浙江省|