, , dest = op_1 + op_2 + carry ADC 將把兩個操作數加起來,并把結果放置到目的寄存器中。它使用一個進位標志位,這樣就可以做比 32 位大的加法。下列例子將加兩個 128 位的數。" />

精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

史上最全ARM指令集詳解

算術和邏輯指令

ADC : 帶進位的加法

(Addition withCarry)

ADC{條件}{S} , , dest = op_1 + op_2 + carry

ADC將把兩個操作數加起來,并把結果放置到目的寄存器中。它使用一個進位標志位,這樣就可以做比 32 位大的加法。下列例子將加兩個 128 位的數。

128 位結果: 寄存器 0、1、2、和 3第一個 128 位數: 寄存器 4、5、6、和 7第二個 128 位數: 寄存器 8、9、10、和 11。

ADDS R0, R4, R8 ; 加低端的字 ADCS R1, R5, R9 ; 加下一個字,帶進位 ADCS R2, R6, R10 ; 加第三個字,帶進位 ADCS R3, R7, R11 ; 加高端的字,帶進位

如果如果要做這樣的加法,不要忘記設置 S 后綴來更改進位標志。

ADD : 加法

(Addition)

ADD{條件}{S} , , dest = op_1 + op_2

ADD將把兩個操作數加起來,把結果放置到目的寄存器中。操作數 1 是一個寄存器,操作數 2 可以是一個寄存器,被移位的寄存器,或一個立即值:

ADD R0, R1, R2 ; R0 = R1 + R2 ADD R0, R1, #256 ; R0 = R1 + 256 ADD R0, R2, R3,LSL#1 ; R0 = R2 + (R3 << 1)

加法可以在有符號和無符號數上進行。

AND : 邏輯與

(logicalAND)

AND{條件}{S} , , dest = op_1 AND op_2

AND將在兩個操作數上進行邏輯與,把結果放置到目的寄存器中;對屏蔽你要在上面工作的位很有用。 操作數 1 是一個寄存器,操作數 2 可以是一個寄存器,被移位的寄存器,或一個立即值:

AND R0, R0, #3 ; R0 = 保持 R0 的位 0 和 1,丟棄其余的位。

AND 的真值表(二者都是 1 則結果為 1):

Op_1 Op_2 結果 0 0 0 0 1 0 1 0 0 1 1 1

BIC : 位清除

(BitClear)

BIC{條件}{S} , , dest = op_1 AND (!op_2)

BIC是在一個字中清除位的一種方法,與 OR 位設置是相反的操作。操作數 2 是一個 32 位位掩碼(mask)。如果如果在掩碼中設置了某一位,則清除這一位。未設置的掩碼位指示此位保持不變。

BIC R0, R0, #%1011 ; 清除 R0 中的位 0、1、和 3。保持其余的不變。

BIC 真值表 :

Op_1 Op_2 結果 0 0 0 0 1 0 1 0 1 1 1 0

譯注:邏輯表達式為 Op_1 AND NOT Op_2

EOR : 邏輯異或

(logicalExclusiveOR)

EOR{條件}{S} , , dest = op_1 EOR op_2

EOR將在兩個操作數上進行邏輯異或,把結果放置到目的寄存器中;對反轉特定的位有用。操作數 1 是一個寄存器,操作數 2 可以是一個寄存器,被移位的寄存器,或一個立即值:

EOR R0, R0, #3 ; 反轉 R0 中的位 0 和 1

EOR 真值表(二者不同則結果為 1):

Op_1 Op_2 結果 0 0 0 0 1 1 1 0 1 1 1 0

MOV : 傳送

(Move)

MOV{條件}{S} , dest = op_1

MOV從另一個寄存器、被移位的寄存器、或一個立即值裝載一個值到目的寄存器。你可以指定相同的寄存器來實現 NOP 指令的效果,你還可以專門移位一個寄存器:

MOV R0, R0 ; R0 = R0... NOP 指令 MOV R0, R0, LSL#3 ; R0 = R0 * 8

如果 R15 是目的寄存器,將修改程序計數器或標志。這用于返回到調用代碼,方法是把連接寄存器的內容傳送到 R15:

MOV PC, R14 ; 退出到調用者 MOVS PC, R14 ; 退出到調用者并恢復標志位 (不遵從 32-bit 體系)

MVN : 傳送取反的值

(MoveNegative)

MVN{條件}{S} , dest = !op_1

MVN從另一個寄存器、被移位的寄存器、或一個立即值裝載一個值到目的寄存器。不同之處是在傳送之前位被反轉了,所以把一個被取反的值傳送到一個寄存器中。這是邏輯非操作而不是算術操作,這個取反的值加 1 才是它的取負的值:

MVN R0, #4 ; R0 = -5 MVN R0, #0 ; R0 = -1

ORR : 邏輯或

(logicalOR)

ORR{條件}{S} , , dest = op_1 OR op_2

OR將在兩個操作數上進行邏輯或,把結果放置到目的寄存器中;對設置特定的位有用。操作數 1 是一個寄存器,操作數 2 可以是一個寄存器,被移位的寄存器,或一個立即值:

ORR R0, R0, #3 ; 設置 R0 中位 0 和 1

OR 真值表(二者中存在 1 則結果為 1):

Op_1 Op_2 結果 0 0 0 0 1 1 1 0 1 1 1 1

RSB : 反向減法

(ReverseSubtraction)

RSB{條件}{S} , , dest = op_2 - op_1

SUB用操作數two減去操作數one,把結果放置到目的寄存器中。操作數 1 是一個寄存器,操作數 2 可以是一個寄存器,被移位的寄存器,或一個立即值:

RSB R0, R1, R2 ; R0 = R2 - R1 RSB R0, R1, #256 ; R0 = 256 - R1 RSB R0, R2, R3,LSL#1 ; R0 = (R3 << 1) - R2

反向減法可以在有符號或無符號數上進行。

RSC : 帶借位的反向減法

(ReverseSubtraction withCarry)

RSC{條件}{S} , , dest = op_2 - op_1 - !carry

同于SBC,但倒換了兩個操作數的前后位置。

SBC : 帶借位的減法

(Subtraction withCarry)

SBC{條件}{S} , , dest = op_1 - op_2 - !carry

SBC做兩個操作數的減法,把結果放置到目的寄存器中。它使用進位標志來表示借位,這樣就可以做大于 32 位的減法。SUB和SBC生成進位標志的方式不同于常規,如果需要借位則清除進位標志。所以,指令要對進位標志進行一個非操作 - 在指令執行期間自動的反轉此位。

SUB : 減法

(Subtraction)

SUB{條件}{S} , , dest = op_1 - op_2

SUB用操作數one減去操作數two,把結果放置到目的寄存器中。操作數 1 是一個寄存器,操作數 2 可以是一個寄存器,被移位的寄存器,或一個立即值:

SUB R0, R1, R2 ; R0 = R1 - R2 SUB R0, R1, #256 ; R0 = R1 - 256 SUB R0, R2, R3,LSL#1 ; R0 = R2 - (R3 << 1)

減法可以在有符號和無符號數上進行。

移位指令

ARM 處理器組建了可以與數據處理指令(ADC、ADD、AND、BIC、CMN、CMP、EOR、MOV、MVN、ORR、RSB、SBC、SUB、TEQ、TST)一起使用的桶式移位器(barrel shifter)。你還可以使用桶式移位器影響在 LDR/STR 操作中的變址值。

譯注:移位操作在 ARM 指令集中不作為單獨的指令使用,它是指令格式中是一個字段,在匯編語言中表示為指令中的選項。如果數據處理指令的第二個操作數或者單一數據傳送指令中的變址是寄存器,則可以對它進行各種移位操作。如果數據處理指令的第二個操作數是立即值,在指令中用 8 位立即值和 4 位循環移位來表示它,所以對大于 255 的立即值,匯編器嘗試通過在指令中設置循環移位數量來表示它,如果不能表示則生成一個錯誤。在邏輯類指令中,邏輯運算指令由指令中 S 位的設置或清除來確定是否影響進位標志,而比較指令的 S 位總是設置的。在單一數據傳送指令中指定移位的數量只能用立即值而不能用寄存器。

下面是給不同的移位類型的六個助記符:

LSL 邏輯左移 ASL 算術左移 LSR 邏輯右移 ASR 算術右移 ROR 循環右移 RRX 帶擴展的循環右移

ASL和LSL是等同的,可以自由互換。

你可以用一個立即值(從 0 到 31)指定移位數量,或用包含在 0 和 31 之間的一個值的寄存器指定移位數量。

邏輯或算術左移

(Logical orArithmeticShiftLeft)

Rx, LSL #n or Rx, ASL #n or Rx, LSL Rn or Rx, ASL Rn

接受 Rx 的內容并按用‘n’或在寄存器 Rn 中指定的數量向高有效位方向移位。最低有效位用零來填充。除了概念上的第 33 位(就是被移出的最小的那位)之外丟棄移出最左端的高位,如果邏輯類指令中 S 位被設置了,則此位將成為從桶式移位器退出時進位標志的值。

考慮下列:

MOV R1, #12 MOV R0, R1, LSL#2

在退出時,R0 是 48。 這些指令形成的總和是R0 = #12, LSL#2等同于 BASIC 的R0 = 12 << 2

邏輯右移

(LogicalShiftRight)

Rx, LSR #n or Rx, LSR Rn

它在概念上與左移相對。把所有位向更低有效位方向移動。如果邏輯類指令中 S 位被設置了,則把最后被移出最右端的那位放置到進位標志中。它同于 BASIC 的register = value >>> shift。

算術右移

(ArithmeticShiftRight)

Rx, ASR #n or Rx, ASR Rn

類似于 LSR,但使用要被移位的寄存器(Rx)的第 31 位的值來填充高位,用來保護補碼表示中的符號。如果邏輯類指令中 S 位被設置了,則把最后被移出最右端的那位放置到進位標志中。它同于 BASIC 的register = value >> shift。

循環右移

(RotateRight)

Rx, ROR #n or Rx, ROR Rn

循環右移類似于邏輯右移,但是把從右側移出去的位放置到左側,如果邏輯類指令中 S 位被設置了,則同時放置到進位標志中,這就是位的‘循環’。一個移位量為 32 的操作將導致輸出與輸入完全一致,因為所有位都被移位了 32 個位置,又回到了開始時的位置!

帶擴展的循環右移

(RotateRight with extend)

Rx, RRX

這是一個 ROR#0 操作,它向右移動一個位置 - 不同之處是,它使用處理器的進位標志來提供一個要被移位的 33 位的數量。

乘法指令

指令格式:

這兩個指令與普通算術指令在對操作數的限制上有所不同:

給出的所有操作數、和目的寄存器必須為簡單的寄存器。

你不能對操作數 2 使用立即值或被移位的寄存器。

目的寄存器和操作數 1 必須是不同的寄存器。

最后,你不能指定 R15 為目的寄存器。

MLA : 帶累加的乘法

(Multiplication withAccumulate)

MLA{條件}{S} , , , dest = (op_1 * op_2) + op_3

MLA的行為同于MUL,但它把操作數 3 的值加到結果上。這在求總和時有用。

MUL : 乘法

(Multiplication)

MUL{條件}{S} , , dest = op_1 * op_2

MUL提供 32 位整數乘法。如果操作數是有符號的,可以假定結果也是有符號的。

比較指令

指令格式:

譯注:CMP 和 CMP 是算術指令,TEQ 和 TST 是邏輯指令。把它們歸入一類的原因是它們的 S 位總是設置的,就是說,它們總是影響標志位。

CMN : 比較取負的值

(CompareNegative)

CMN{條件}{P} , status = op_1 - (- op_2)

CMN同于CMP,但它允許你與小負值(操作數 2 的取負的值)進行比較,比如難于用其他方法實現的用于結束列表的 -1。這樣與 -1 比較將使用:

CMN R0, #1 ; 把 R0 與 -1 進行比較

詳情參照CMP指令。

CMP : 比較

(Compare)

CMP{條件}{P} , status = op_1 - op_2

CMP允許把一個寄存器的內容如另一個寄存器的內容或立即值進行比較,更改狀態標志來允許進行條件執行。它進行一次減法,但不存儲結果,而是正確的更改標志。標志表示的是操作數 1 比操作數 2 如何(大小等)。如果操作數 1 大于操作操作數 2,則此后的有 GT 后綴的指令將可以執行。

明顯的,你不需要顯式的指定S后綴來更改狀態標志... 如果你指定了它則被忽略。

TEQ : 測試等價

(TestEquivalence)

TEQ{條件}{P} , Status = op_1 EOR op_2

TEQ類似于TST。區別是這里的概念上的計算是 EOR 而不是 AND。這提供了一種查看兩個操作數是否相同而又不影響進位標志(不象CMP那樣)的方法。加上P后綴的TEQ還可用于改變 R15 中的標志(在 26-bit 模式中)。

TST : 測試位

(Testbits)

TST{條件}{P} , Status = op_1 AND op_2

TST類似于CMP,不產生放置到目的寄存器中的結果。而是在給出的兩個操作數上進行操作并把結果反映到狀態標志上。使用TST來檢查是否設置了特定的位。操作數 1 是要測試的數據字而操作數 2 是一個位掩碼。經過測試后,如果匹配則設置 Zero 標志,否則清除它。象CMP那樣,你不需要指定S后綴。

TST R0, #%1 ; 測試在 R0 中是否設置了位 0。

分支指令

B : 分支

(Branch)

B{條件} <地址>

B 是最簡單的分支。一旦遇到一個 B 指令,ARM 處理器將立即跳轉到給定的地址,從那里繼續執行。注意存儲在分支指令中的實際的值是相對當前的 R15 的值的一個偏移量;而不是一個絕對地址。它的值由匯編器來計算,它是 24 位有符號數,左移兩位后有符號擴展為 32 位,表示的有效偏移為 26 位(+/- 32 M)。

在其他處理器上,你可能經常見到這樣的指令:

OPT 1 LDA &70 CMP #0 BEQ Zero STA &72 .Zero RTS在 ARM 處理器上,它們將變成下面這些東西:

OPT 1 ADR R1, #&70 LDR R0, [R1] CMP #0 BEQ Zero STR R0, [R1, #2] .Zero MOV PC, R14

這不是一個很好的例子,但你可以構想如何更好的去條件執行而不是分支。另一方面,如果你有大段的代碼或者你的代碼使用狀態標志,那么你可以使用條件執行來實現各類分支: 這樣一個單一的簡單條件執行指令可以替代在其他處理器中存在的所有這些分支和跳轉指令。

OPT 1 ADR R1, #&70 LDR R0, [R1] CMP R0, #0 STRNE R0, [R1, #2] MOV PC, R14

BL : 帶連接的分支

(Branch with Link)

BL{條件} <地址>

BL 是另一個分支指令。就在分支之前,在寄存器 14 中裝載上 R15 的內容。你可以重新裝載 R14 到 R15 中來返回到在這個分支之后的那個指令,

它是子例程的一個基本但強力的實現。它的作用在屏幕裝載器 2 (例子 4)中得以很好的展現...

.load_new_format BL switch_screen_mode BL get_screen_info BL load_palette .new_loop MOV R1, R5 BL read_byte CMP R0, #255 BLEQ read_loop STRB R0, [R2, #1]!

在這里我們見到在裝載器循環之前調用了三個子例程。接著,一旦滿足了條件執行就在循環中調用了 read_byte 子例程。

條件執行

ARM 處理器的一個非常特殊的特征是它的條件執行。我們指的不是基本的如果進位則分支,ARM 使這個邏輯階段進一步深化為如果進位則 XXX- 這里的 XXX 是任何東西。

為了舉例,下面是 Intel 8086 處理器分支指令的一個列表:

JA Jump if Above JAE Jump if Above or Equal JB Jump if Below JBE Jump if Below or Equal JC Jump if Carry JCXZ Jump if CX Zero (CX is a register that can be used for loop counts) JE Jump if Equal JG Jump if Greater than JGE Jump if Greater than or Equal JL Jump if Less than JLE Jump if Less Than or Equal JMP JuMP JNA Jump if Not Above JNAE Jump if Not Above or Equal JNB Jump if Not Below JNBE Jump if Not Below or Equal JNC Jump if No Carry JNE Jump if Not Equal JNG Jump if Not Greater than JNGE Jump if Not Greater than or Equal JNL Jump if Not Less than JNLE Jump if Not Less than or Equal JNO Jump if Not Overflow JNP Jump if Not Parity JNS Jump if Not Sign JNZ Jump if Not Zero JO Jump if Overflow JP Jump if Parity JPE Jump if Parity Even JPO Jump if Parity Odd JS Jump if Sign JZ Jump if Zero 80386 添加了: JECXZ Jump if ECX Zero

作為對比,ARM 處理器只提供了:

B 分支 BL 帶連接的分支

但 ARM 提供了條件執行,你可以不受這個表面上不靈活的方式的限制:

BEQ Branch if EQual BNE Branch if Not Equal BVS Branch if oVerflow Set BVC Branch if oVerflow Clear BHI Branch if HIgher BLS Branch if Lower or the Same BPL Branch if PLus BMI Branch if MInus BCS Branch if Carry Set BCC Branch if Carry Clear BGE Branch if Greater than or Equal BGT Branch if Greater Than BLE Branch if Less than or Equal BLT Branch if Less Than BLEQ Branch with Link if EQual .... BLLT Branch with Link if Less Than

還有兩個代碼,

AL - ALways,缺省條件所以不須指定

NV - NeVer,不是非常有用。你無論如何不要使用這個代碼...

當你發現所有 Bxx 指令實際上是同一個指令的時候,緊要關頭就到了。

接著你會想,如果你可以在一個分支指令上加上所有這些條件,那么對一個寄存器裝載指令能否加上它們? 答案是可以。

下面是可獲得的條件代碼的列表:

EQ : 等于

如果一次比較之后設置了 Z 標志。

NE : 不等于

如果一次比較之后清除了 Z 標志。

VS : 溢出設置

如果在一次算術操作之后設置了 V 標志,計算的結果不適合放入一個 32bit 目標寄存器中。

VC : 溢出清除

如果清除了 V 標志,與 VS 相反。

HI : 高于(無符號)

如果一次比較之后設置了 C 標志并清除了 Z 標志。

LS : 低于或同于(無符號)

如果一次比較操作之后清除了 C 標志或設置了 Z 標志。

PL : 正號

如果一次算術操作之后清除了 N。出于定義‘正號’的目的,零是正數的原因是它不是負數...

MI : 負號

如果一次算術操作之后設置了 N 標志。

CS : 進位設置

如果一次算術操作或移位操作之后設置了 C 標志,操作的結果不能表示為 32bit。你可以把 C 標志當作結果的第 33 位。

CC : 進位清除

與 CS 相反。

GE : 大于或等于(有符號)

如果一次比較之后...設置了 N 標志并設置了 V 標志或者...清除了 N 標志并清除了 V 標志。

GT : 大于(有符號)

如果一次比較之后...設置了 N 標志并設置了 V 標志或者...清除了 N 標志并清除了 V 標志并且...清除了 Z 標志。

LE : 小于或等于(有符號)

如果一次比較之后...設置了 N 標志并清除了 V 標志或者...清除了 N 標志并設置了 V 標志并且...設置了 Z 標志。

LT : 小于(有符號)

如果一次比較之后...設置了 N 標志并清除了 V 標志。或者...清除了 N 標志并設置了 V 標志。

AL : 總是

缺省條件,所以不用明顯聲明。

NV : 從不

不是特別有用,它表示應當永遠不執行這個指令。是窮人的 NOP。

包含 NV 是為了完整性(與 AL 相對),你不應該在你的代碼中使用它。

有一個在最后的條件代碼 S,它以相反的方式工作。當用于一個指令的時候,導致更改狀態標志。這不是自動發生的 - 除非這些指令的目的是設置狀態。例如:

ADD R0, R0, R1 ADDS R0, R0, R1 ADDEQS R0, R0, R1

第一個例子是一個基本的加法(把 R1 的值增加到 R0),它不影響狀態寄存器。

第二個例子是同一個加法,只不過它導致更改狀態寄存器。

最后一個例子是同一個加法,更改狀態寄存器。不同在于它是一個有條件的指令。只有前一個操作的結果是 EQ (如果設置了 Z 標志)的時候它才執行。

下面是條件執行的一個工作中的例子。你把寄存器 0 與存儲在寄存器 10 中內容相比較。

如果不等于 R10,則調用一個軟件中斷,增加它并分支回來再次做這些。否則清除 R10 并返回到調用它的那部分代碼(它的地址存儲在 R14)。

條件執行的一個例子 .loop ; 標記循環開始位置 CMP R0, R10 ; 把 R0 與 R10 相比較 SWINE &40017 ; 不等于: 調用 SWI &40017 ADDNE R0, R0, #1 ; 向 R0 加 1 BNE loop ; 分支到 'loop' MOV R10, #0 ; 等于 : 設置 R10 為零 LDMFD R13!, {R0-R12,PC} ; 返回到調用者

注解:

SWI 編號就象我寫的這樣。在 RISC OS 下,它是給 Econet_DoImmediate 的編號。不要字面的接受它,這只是一個例子!

你可能以前沒見過 LDMFD,它從棧中裝載多個寄存器。在這個例子中,我們從一個完全正式的棧中裝載 R0 至 R12 和 R14。關于寄存器裝載和存儲的更多信息請參閱 str.html。

我說要裝載 R14。那么為什么要把它放入 PC 中? 原因是此時 R14 存儲的值包含返回地址。我們也可以采用:LDMFD R13!, {R0-R12,R14} MOV PC, R14但是直接恢復到 PC 中可以省略這個 MOV 語句。

最后,這些寄存器很有可能被一個 SWI 調用所占用(依賴于在調用期間執行的代碼),所以你最好把你的重要的寄存器壓入棧中,以后在恢復它們。

SWI指令

SWI軟中斷

(Software Interrupt)

SWI{條件} <24 位編號>

指令格式

這是一個簡單的設施,但可能是最常用的。多數操作系統設施是用 SWI 提供的。沒有 SWI 的 RISC OS 是不可想象的。

Nava Whiteford 解釋了 SWI 是如何工作的(最初在 Frobnicate issue 12?)...

SWI 是什么?

SWI 表示 Software Interrupt。在 RISC OS 中使用 SWI 來訪問操作系統例程或第三方生產的模塊。許多應用使用模塊來給其他應用提供低層外部訪問。

SWI 的例子有:

文件器 SWI,它輔助讀寫磁盤、設置屬性等。

打印機驅動器 SWI,用來輔助使用打印并行端口

FreeNet/Acorn TCP/IP 協議棧 SWI,用 TCP/IP 協議在 Internet 上發送和接收數據。

在以這種方式使用的時候,SWI 允許操作系統擁有一個模塊結構,這意味著用來建立完整的操作系統的所需的代碼可以被分割成許多小的部分(模塊)和一個模塊處理程序(handler)。

當 SWI 處理程序得到對特定的例程編號的一個請求的時候,它找到這個例程的位置并執行它,并傳遞(有關的)任何數據。

它是如何工作的?

首先查看一下如何使用它。一個 SWI 指令(匯編語言)看起來如下:

SWI &02

SWI "OS_Write0"

這些指令實際上是相同的,將被匯編成相同的指令。唯一的不同是第二個指令使用一個字符串來表示 SWI 編號 &02。

在使用采用了字符串編號的程序的時候,在執行之前首先查找這個字符串。

在這里我們不想處理字符串,因為它不能給出它要進行什么的一個真實表示。它們通常用于增進一個程序的清晰程度,但不是實際執行的指令。

讓我們再次看一下第一個指令:

SWI &02

這是什么意思? 字面的意思是進入 SWI 處理程序并傳遞值 &02。在 RISC OS 中這意味著執行編號是 &02 的例程。

它是如何這么作的? 它如何傳遞 SWI 編號和進入 SWI 處理程序?

如果你查看內存的開始 32 字節(位于 0-&1C)并反匯編它們(查開實際的 ARM 指令)你將見到如下:

地址 內容 反匯編 00000000 : 0..? : E5000030 : STR R0,[R0,#-48] 00000004 : .ó?? : E59FF31C : LDR PC,&00000328 00000008 : .ó?? : E59FF31C : LDR PC,&0000032C 0000000C : .ó?? : E59FF31C : LDR PC,&00000330 00000010 : .ó?? : E59FF31C : LDR PC,&00000334 00000014 : .ó?? : E59FF31C : LDR PC,&00000338 00000018 : .ó?? : E59FF31C : LDR PC,&0000033C 0000001C : 2?? : E3A0A632 : MOV R10,#&3200000

讓我們仔細看一下。

除了第一個和最后一個指令之外(它們是特殊情況)你見到的都是把一個新值裝載到 PC (程序計數器)的指令,它們告訴計算機到哪里去執行下一個指令。

還展示了這個值是從內存中的一個地址接受來的。(你可以在 !Zap 主菜單上使用“Read Memory”選項去自己查看一下。)

這看起來好象與 SWI 沒多少關系,下面做進一步的說明。

一個 SWI 所做的一切就是把模式改變成超級用戶并設置 PC 來執行在地址 &08 處的下一個指令!

把處理器轉換到超級用戶模式會切換掉兩個寄存器 r13 和 r14 并用 r13_svc 和 r14_svc 替換它們。

在進入超級用戶模式的時候,還把 r14_svc 設置為在這個 SWI 指令之后的地址。

這個實際上就象一個連接到地址 &08 的分支指令(BL &08),但帶有用于一些數據(SWI 編號)的空間。

象我說過的那樣,地址 &08 包含跳轉到另一個地址的一個指令,就是實際的 SWI 程序的地址!

此時你可能會想“稍等一會! 還有 SWI 編號呢?”。實際上處理器忽略這個值本身。SWI 處理程序使用傳遞來的 r14_svc 的值來獲取它。

下面是完成它的步驟(在存儲寄存器 r0-r12 之后):

它從 r14 中減去 4 來獲得 SWI 指令的地址。

把這個指令裝載到一個寄存器。

清除這個指令的高端 8 位,去掉了 OpCode 而只剩下的 SWI 編號。

使用這個值來找到要被執行的代碼的例程的地址(使用查找表等)。

恢復寄存器 r0-r12。

使處理器離開超級用戶模式。

跳轉到這個例程的地址。

下面是一個例子,來自 ARM610 datasheet:

0x08 B Supervisor EntryTable DCD ZeroRtn DCD ReadCRtn DCD WriteIRtn ... Zero EQU 0 ReadC EQU 256 WriteI EQU 512 ; SWI 包含需要的例程在位 8-23 中和數據(如果有的話)在位 0-7 中。 ; 假定 R13_svc 指向了一個合適的棧 STMFD R13, {r0-r2 , R14} ; 保存工作寄存器和返回地址。 LDR R0,[R14,#-4] ; 得到 SWI 指令。 BIC R0,R0, #0xFF000000 ; 清除高端的 8 位。 MOV R1, R0, LSR #8 ; 得到例程偏移量。 ADR R2, EntryTable ; 得到入口表(EntryTable)的開始地址。 LDR R15,[R2,R1,LSL #2] ; 分支到正確的例程 WriteIRtn ; 寫 R0 中的位 0 - 7 中的字符。 ............. LDMFD R13, {r0-r2 , R15}^ ; 恢復工作空間,并返回、恢復處理器模式和標志。

這就是 SWI 指令的基本處理步驟。

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

    關注

    134

    文章

    9046

    瀏覽量

    366817
  • 寄存器
    +關注

    關注

    31

    文章

    5317

    瀏覽量

    120008
  • adc
    adc
    +關注

    關注

    98

    文章

    6438

    瀏覽量

    544097

原文標題:ARM指令集詳解

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    常用ARM指令集及匯編

    效率高,但是代碼密度低,而Thumb指令集具有更好的代碼密度,卻仍然保持ARM的大多數性能上的優勢,它是ARM指令集的子集。[hide]arm
    發表于 11-23 09:38

    ARM指令集

    ARM指令集,很好的資料。
    發表于 04-20 14:30

    史上最全的51單片機指令集

    史上最全的51單片機指令集
    發表于 09-27 22:28

    ARM指令集文章集合

    三、指令集如果你想要集中學習一下關于ARM指令集方面的知識(比如下面幾個知識點),可以看下下面的文章1、機器碼2、運算指令3、控制指令4、匯
    發表于 09-07 22:06

    ARM指令集的特點有哪些呢

    1、ARM指令集ARM指令集格式ARM指令集ARM
    發表于 12-14 07:24

    ARM指令集下載 arm指令集參考手冊

    ARM指令集下載 arm指令集參考手冊, ARM 指令集 寄存器和處理器模式(26-bi
    發表于 12-25 09:20 ?118次下載

    常用arm指令集及匯編

    常用arm指令集及匯編
    發表于 09-09 14:22 ?34次下載
    常用<b class='flag-5'>arm</b><b class='flag-5'>指令集</b>及匯編

    arm指令集(1)

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

    ARM指令集詳解

    ARM指令集詳解 內容提要 ARM指令集 ARM指令集
    發表于 03-09 09:39 ?263次下載
    <b class='flag-5'>ARM</b><b class='flag-5'>指令集</b><b class='flag-5'>詳解</b>

    ARM指令集介紹

    arm開發板 嵌入式開發 指令集 PDF文檔。
    發表于 05-03 16:42 ?5次下載

    常用的ARM指令集及匯編

    常用的ARM指令集及匯編
    發表于 10-30 10:07 ?24次下載
    常用的<b class='flag-5'>ARM</b><b class='flag-5'>指令集</b>及匯編

    thumb指令集是什么_thumb指令集arm指令集的區別

    thumb指令集arm指令集的一個子集,是針對代碼密度問題而提出的,它具有16位的代碼寬度。與等價的32位代碼相比較,thumb指令集在保留32位代碼優勢的同時,大大的節省了系統的存
    發表于 11-03 17:34 ?1.8w次閱讀
    thumb<b class='flag-5'>指令集</b>是什么_thumb<b class='flag-5'>指令集</b>與<b class='flag-5'>arm</b><b class='flag-5'>指令集</b>的區別

    ARM架構及ARM指令集 Thumb指令集你了解多少?

    ARM架構及ARM指令集、Thumb指令集你了解多少?
    的頭像 發表于 02-26 16:09 ?7087次閱讀

    ARM處理器的尋址方式和指令集介紹

    ARM處理器是基于精簡指令集計算機(RISC原理設計的,指令集和相關嶧碼機制較為簡單。ARM7TDM(S)具有32位ARM
    發表于 11-24 17:24 ?33次下載
    <b class='flag-5'>ARM</b>處理器的尋址方式和<b class='flag-5'>指令集</b>介紹

    一文詳解Arm Cortex-M處理器指令集

    Arm處理器是基于精簡指令集計算機(RISC)原理設計的,指令集和相關譯碼機制較為簡單,具有32位Arm指令集和16位Thumb
    的頭像 發表于 05-17 09:31 ?6242次閱讀