控制程序流
無條件跳轉
B label :最大允許跳32MB範圍
關於CPSR
條件標誌位:
• Negative(負數標誌位): N is 1 if the signed value is negative andcleared if the result is positive or 0.
• Zero(零標誌位): Is set if the result is 0; this usually denotes an equal result from a comparison. If the result is non-zero, this flag is cleared.
• Carry(進位標誌位): For addition type operations, this flag is set if the result produces an overflow. For subtraction type operation, this flag is set if the result requires a borrow. Also, it’s used in shifting to hold the last bit that is shifted out.
• OVerflow(溢出標誌位): For addition and subtraction, this flag is set if a signed overflow occurred. NOTE: Some instructions may specifically set oVerflow to flag an error condition.
中斷標誌位:
• I: When set, disables IRQ interrupts(關閉IRQ中斷)
• F: When set, disables FIQ interrupts(關閉FIQ中斷)
• A: When set, disables imprecise aborts (關閉不精確的中止?)
指令集標誌:
• Thumb: 16-bit compact instructions(16位緊湊指令)
• Jazelle: Obsolete mode for directly executing Java bytecodes(直接執行Java字節碼的過時的模式)
其它標誌位:
• Q: This flag is set to indicate underflow and/or saturation.(設置該標誌以指示下溢和/或飽和度)
• GE: These flags control the Greater than or Equal behavior in SIMD instructions.
• E: Is a flag that controls the “endianness” for data handling.(控制數據存儲使用的大/小端模式)
M is the processor mode such as user or supervisor(處理器模式,例如用戶模式、監視模式)
條件分支
一般的條件分支指令如下:
B{condition} label
{condition} | Flags | Meaning |
---|---|---|
EQ | Z=1 | 相等 |
NE | Z=0 | 不相等 |
CS或HS | C=1 | 無符號>= |
CC或LO | C=0 | 無符號< |
MI | N=1 | 負數 |
PL | N=0 | 正數或0 |
VS | V=1 | 溢出 |
VC | V=0 | 無溢出 |
HI | C=1且Z=0 | 無符號> |
LS | C=0且Z=1 | 無符號<= |
GE | N=V | 有符號>= |
LT | N!=V | 有符號< |
GT | Z=0,N=V | 有符號> |
LE | Z=1,N!=V | 有符號<= |
AL | 任何時候 | 無條件執行 |
示例:
BEQ _start
當Z標誌位爲1時執行_start分支
Loops
for循環的彙編形式
@ 1到10
MOV R2, #1
loop:
ADD R2, #1 @ I = I + 1
CMP R2, #10
BLE loop @ IF I <= 10 goto loop
while循環的彙編形式
loop: CMP R4, #5
BGE loopdone
... other statements in the loop body ...
B loop
loopdone: @program continues
If/Then/Else
IF R5 < 10 THEN
.... if statements ...
ELSE
... else statements ...
END IF
相應的彙編實現:
CMP R5, #10
BGE elseclause
... if statements ...
B endif
elseclause:
... else statements ...
endif: @ continue on after the /then/else ...
邏輯運算
AND{S} Rd, Rs, Operand2 與
EOR{S} Rd, Rs, Operand2 異或
ORR{S} Rd, Rs, Operand2 或
BIC{S} Rd, Rs, Operand2 (Rs AND NOT Operand2)
設計模式
在編寫彙編語言代碼時,很容易產生新的想法。例如,我們可以通過置寄存器的第十位爲1,然後將其右移直到寄存器爲零,來進行十次循環。這行得通,但是卻使程序閱讀變得困難。如果你退出程序並在下個月重新閱讀該程序,你有可能對它抓狂。
設計模式是常見編程模式的典型解決方案。如果採用一些關於如何執行循環和其他編程結構的標準設計模式,它將使你閱讀程序變得更加容易。
設計模式使編程更加高效,因爲在大多數情況下,可以僅使用一系列經過實踐檢驗的真實模式中的示例即可。
因此,我們以高級語言的模式實現了循環以及if / then / else。如果這樣做,它將使我們的程序更可靠,更快速地編寫。稍後,我們將研究如何使用匯編器中的宏來解決此問題。
將寄存器的內容存儲到內存
STRB R6, [R1]
分支程序的性能
在第1章“入門”中,我們提到了ARM32指令集是在指令管道中執行的。
一條指令需要三個時鐘週期來執行,每個週期需要1個時鐘週期。
1.將指令從內存加載到CPU。
2.解碼指令。
3.執行指令。
但是,CPU一次可以處理3條指令,每條指令執行不同的步驟,因此平均而言,每個時鐘週期我們執行一條指令。但是當我們有分支時會發生什麼呢?
執行分支時,我們已經解碼了下一條指令並將指令2加載到前面。當我們執行分支時,我們將前面已經完成的工作丟棄並重新開始。這意味着分支之後的指令將需要三個時鐘週期來執行。
如果在代碼中設置了很多分支,則可能會降低性能,可能會使程序減慢3倍。另一個問題是,如果使用很多分支進行編程,則會導致產生意大利麪條式代碼,即所有代碼行像一鍋意大利麪一樣糾結在一起,很難維護。
更多的比較指令
• CMN Rn, Operand2 :使用加法而不是減法
• TEQ Rn, Operand2 : 在Rn和Operand2之間執行按位異或運算。它根據結果更新CPSR。
• TST Rn, Operand2 : 在Rn和Operand2之間執行按位與運算。它根據結果更新CPSR。