mov: move
sub: subtract
cmp: compare
cmpls: ls--->lower or same, le--->less or equal, hi--->higher
ldr: load register
lsl: logical shift left
str: store register
b: branch
bl: branch label, change pc
bne: branch not equal
beq: branch equal
blt: branch less than
push {r4, r5} : store r4, r5 to stack
pop {r4, r5}: restore r4, r5 from stack
ldm: load multiple
stm: store multiple
and:
ldrd r0, r1, [r2, #4] : load 8 bytes from r2 + 4, and high 4 bytes stored in r0, lower in r1
.align 2: 2 * 2 = 4, the ldr instruction we used to read memory only works at addresses that are multiples of 4
tst : compares two numbers by computing the logical and operation of the numbers, and then comparing the result with 0
strh reg,[dest]: stores the low half word number in reg at the address given by dest.
alias .req: reg sets alias to mean the register reg.
.unreq alias: removes the alias alias.
teq reg,#val: checks if the number in reg is equal to val.
========================================
Register | Brief | Preserved | Rules |
---|---|---|---|
r0 | Argument and result | No | r0 and r1 are used for passing the first two arguments to functions, and returning the results of functions. If a function does not use them for a return value, they can take any value after a function. |
r1 | Argument and result | No | |
r2 | Argument | No | r2 and r3 are used for passing the second two arguments to functions. There values after a function is called can be anything. |
r3 | Argument | No | |
r4 | General purpose | Yes | r4 to r12 are used for working values, and their value after a function is called must be the same as before. |
r5 | General purpose | Yes | |
r6 | General purpose | Yes | |
r7 | General purpose | Yes | |
r8 | General purpose | Yes | |
r9 | General purpose | Yes | |
r10 | General purpose | Yes | |
r11 | General purpose | Yes | |
r12 | General purpose | Yes | |
lr | Return address | No | lr is the address to branch back to when a function is finished, but this does have to contain the same address after the function has finished. |
sp | Stack pointer | Yes | sp is the stack pointer, described below. Its value must be the same after the function has finished. |
========================================
movw 與 movt 指令
movw 與 movt 一般結合使用,用來往寄存器中加載一個 32 bit value。
環境:xcode 4.6.2,iPad 2, lldb
代碼:
void ArmTest() {
asm (
"movw r1, #0xF8C4\n\t" // 1
"movt r1, #0x40\n\t" // 2
"mov r0, r0"
);
}
在函數的開始部分設置斷點,
然后讀取 r1 寄存器的值(register read r1):r1 = 0x00000000
使用 ni 調試指令來繼續執行一條指令,讀取 r1 寄存器的值:r1 = 0x0000f8c4
繼續單指令執行,讀取寄存器值:r1 = 0x0040f8c4
可以得到結論:movw 將值加載到寄存器的低 16 位,movt 加載到高 16 位,合起來加載一個 32 bit value。
========================================
Register Alt. Name Usage r0 a1 First function argument Integer function result Scratch register r1 a2 Second function argument Scratch register r2 a3 Third function argument Scratch register r3 a4 Fourth function argument Scratch register r4 v1 Register variable r5 v2 Register variable r6 v3 Register variable r7 v4 Register variable r8 v5 Register variable r9 v6 rfp Register variable Real frame pointer r10 sl Stack limit r11 fp Argument pointer r12 ip Temporary workspace r13 sp Stack pointer r14 lr Link register Workspace r15 pc Program counter
========================================
movs 說明
movs r3, #0
cpsr {
0x30,
n = 0x0,
z = 0x0,
c = 0x0,
v = 0x0,
q = 0x0,
j = 0x0,
ge = 0x0,
e = 0x0,
a = 0x0,
i = 0x0,
f = 0x0,
t = 0x1,
mode = 0x10
}
執行后:
cpsr {
0x40000030,
n = 0x0,
z = 0x1,
c = 0x0,
v = 0x0,
q = 0x0,
j = 0x0,
ge = 0x0,
e = 0x0,
a = 0x0,
i = 0x0,
f = 0x0,
t = 0x1,
mode = 0x10
}
總之,movs 在 mov 的功能基礎上影響標志位(zero位)。
=============================
bic 指令
bic Rd, Rn, Oprand2
BIC(位清除)指令對 Rn 中的值 和 Operand2 值的反碼按位進行邏輯“與”運算。
BIC 是 邏輯”與非” 指令, 實現的 Bit Clear的功能
舉例:
BIC R0, R0 , #0xF0000000
#將 R0 高4位清零
BIC R1, R1, #0x0F
#將R1 低4位清0
RSB 反向減法
Rn, Operand2
RSB(反向減法)指令可從 Operand2 中的值減去 Rn 中的值。
這是很有用的,因為有了該指令,Operand2 的選項范圍就會更大。
例如:
RSB r4, r4, #1280
從1280中減去 R4
RSB R4, R0, #0×46
從0×46 中 減去 R0, 放入R4
===================================
STM 與 LDM
STM和LDM的主要用途是現場保護、數據復制、參數傳遞等,其模式有8種,如下:
注:前面4種用於數據塊的傳輸,后面4種用於堆棧操作
(1)IA 每次傳送后地址加4
(2)IB 每次傳送前地址加4
(3)DA 每次傳送后地址減4
(4)DB 每次傳送前地址減4
(5)FD 滿遞減堆棧
(6)FA 滿遞增堆棧
(7)ED 空遞減堆棧
(8)EA 空遞增堆棧
下面的講述對於空遞減堆棧和空遞增堆棧同樣適用.
在堆棧操作時,經常錯誤以為使用STMFD滿遞減將寄存器壓入堆棧后,在彈出數據的時候應該使用LDMFA。
但是FD和FA僅用於指示目前操作的堆棧是何種模式(堆棧共有四種模式),FD指明目前的堆棧是滿遞減堆棧,
則數據入棧時的指令為STMFD,那么數據出棧時的指令對應的為LDMFD,而不是LDMFA。
我們可以這樣認為STMFD等價於STMDB,LDMFD等價於STMIA
那么,數據傳輸的順序和數據入棧的順序又是如何呢
先來看STMFD SP!,{R1-R3} 執行的結果圖(操作之后SP指向SP')
SP-------> |R3|
|R2|
SP'------>|R1|
那么STMFD SP!,{R3,R2,R1}執行后的堆棧順序是不是剛好和上面的堆棧順序相反,實際情況時這兩個指令執行后的堆棧數據順序一樣,因為ARM編譯器會自動將STMFD SP!,{R3,R2,R1}轉換為STMFD SP!,{R0-R3}指令,也就是說,ARM編譯器默認高寄存器優先存入堆棧。即便你在指令STMFD SP!,{R3,R2,R1}中刻意“安排”了寄存器入棧順序,而在編譯時編譯器又重新做了處理,打亂了你期望的數據入棧順序。
同理STMDB R0!,{R1-R3}和STMDB R0!,{R3,R2,R1}指令執行后數據在堆棧中的順序完全一致。
STMFD SP!,{R1-R3}指令對應的出棧指令是LDMFD SP!,{R1-R3}(R1,R2,R3的順序任意)
===================================
CBZ & CBNZ
比較,為零則跳轉;比較,為非零則跳轉。
可以使用 CBZ
或 CBNZ
指令避免更改條件代碼標記並減少指令數目。
除了不更改條件代碼標記外,CBZ Rn, label
與下列指令序列功能相同:
CMP Rn, #0 BEQ label
除了不更改條件代碼標記外,CBNZ Rn, label
與下列指令序列功能相同:
CMP Rn, #0 BNE label
===================================
IT EQ /* if the EQ condition is true, (T)hen execute the next instruction */
MOVEQ r0, #1 /* note the redundant condition code, which needs to match the IT instruction */
------------------
ITE EQ /* if the EQ condition is true, (T)hen execute the next instruction (E)lse execute the instruction after it */
MOVEQ r0, #1
MOVNE r0, #0 /* note that the condition code must be inverted, since this is an "else" instruction */
===================================