一、基础指令
1.mov
MOV{S}<c> <Rd>, #<const>
MOV{S}<c> <Rd>, <Rm>
s:是否影响CPSR状态寄存器;Rd目标寄存器;Rm源寄存器
mov r0, #1 ; r0 = 1
mov r1, #2 ; r1 = 2
mov r2, r1 ; r2 = r1
mov r3, r1, lsl #2 ; r3 = r1 << 2
mov r4, r0, lsl #1 ; r4 = r0 << 1
=>移位指令
LSR 逻辑右移:最高位补0,无符号数
ASR 算术右移:最高位补符号位,有符号数
ROR 循环右移:最低位移出来,放到最高位
LSL 逻辑左移:低位补0
=>立即数
-
数值在 0 ~ 0xFF,直接是合法立即数
-
展开二进制,最高位1到最低位1之间,二进制位数不能超过8位
-
8位二进制数,向右移动偶数次得到该数
2. add sub
add
加法
ADD{S}{<C>} <Rd>, <Rn>, #<const>
ADD{S}{<C>} <Rd>, <Rn>, <Rm>{,<shift>}
mov r1, #2
add r0, r1, #3 ; r0 = r1 +3 = 5
add r2, r0, r1 ; r2 = r0 + r1 =7
add r3, r1, r2, lsl #4 ; r3 = r1 + (r2 <<4)
sub
减法
SUB{S}{<C>} <Rd>, <Rn>, #<const>
SUB{S}{<C>} <Rd>, <Rn>, <Rm>{,<shift>}
mov r0, #5
mov r1, #3
sub r2, r0, #1 ; r2 = r0 -1 = 4
sub r2, r0, r1 ; r2 = r0 - r1 = 2
sub r3, r0, r1, lsl #4 ; r3 = r0 - (r1 <<4)
3. ldr str
ldr
Load,从内存加载数据到通用寄存器
LDR{<C>}{<Q>} <Rt>, <label>
LDR{<C>} <Rt>, \
ldr r0, =0x40000000 ; 将立即数加载到通用寄存器
ldr r1, r0 ; r1 = *r0,把r0指向内存的数据读到r1
str
Store,把寄存器数据写入内存RAM
str r1, r0 ; *r0 = r1
str r1, r0, #4 ; *(r0+4) = r1
str r1, r0, #4 ; *(r0) = r1,然后 r0 = r0 + 4(后变址)
str r1, r0, #4! ; r0 = r0 + 4,然后 *r0 = r1(前变址,!代表更新基址寄存器)
=>两数求和
ldr r0, =0x40000000 ; 变量i地址
ldr r1, r0 ; r1 = *r0
ldr r0, =0x40000004 ; 变量j地址
ldr r2, r0 ; r2 = *r0
add r3, r1, r2 ; r3 = r1 + r2
ldr r0, =0x40000008 ; sum地址
str r3, r0 ; *r0 = r3
4. BIC ORR
BIC
位清零。将寄存器某些bit清0,结果放回寄存器
BIC{S}{<C>} <Rd>, <Rn>, #<const>
ORR
位置1。将寄存器某些bit置1,结果放回寄存器
ORR{S}{<C>} <Rd>, <Rn>, #<const>
5.b
①判断
比较三个数,找出最大值
cpp
mov r1, #1
mov r2, #5
mov r3, #7
cmp r1, r2
bgt great
blt less
great
mov r0, r1
b label
less
mov r0, r2
b label
label
cmp r0, r3
bgt finished
movlt r0, r3
finished
b finished
②循环
求1+2+...+100
a.do while 循环
先执行,后判断(至少执行一次)
cpp
mov r0, #1 ; i
mov r1, #0 ; sum
loop
add r1, r0, r1 ; sum = sum + i
add r0, r0, #1 ; i++
cmp r0, #100
ble loop ; i<=100
finished
b finished
b.while循环
先判断,后执行
cpp
mov r0, #1
mov r1, #0
loop
cmp r0, #100
bgt finished ; i>100
add r1, r0, r1
add r0, r0, #1
b loop
finished
b finished
③ bl bx lr
• bl label:跳转,自动把返回地址保存到lr(r14)
• bx lr:等价于 mov pc, lr,返回调用处
cpp
start
mov r0, #10
mov r1, #15
bl max_of_two_numbers ;调用函数
max_of_two_numbers
cmp r0, r1
movge r2, r0
movlt r2, r1
bx lr ;返回调用处,继续执行下一条指令
6.STMFD / LDMFD
栈4种实现:
空增:先写数据,指针自增
空减:先写数据,指针自减
满增:指针自增,再写数据
满减:指针自减,再写数据(ARM默认)
a.STMFD
入栈,保存现场
STMFD{<C>} <Rn>{!}, <registers>
!:执行完指令自动更新Rn(sp)
stmfd sp!, {r0, r1, r2, r3-r12, lr}
b.LDMFD
出栈,恢复现场
ldmfd sp!, {r0, r1, r2, r3-r12, lr}
7.调用
1) 汇编调用C函数
a.参数≤4个
用r0~r3传递参数;返回值放在r0
cpp
import add_c
stmfd sp!, {r0-r12, lr}
mov r0, #1
mov r1, #2
mov r2, #3
mov r3, #4
bl add_c ;调用C函数
ldmfd sp!, {r0-r12, lr}
bx lr
b.参数>4个
从第5个开始,压栈传递
cpp
import add_c
stmfd sp!, {r0-r12, lr}
mov r0, #1
mov r1, #2
mov r2, #3
mov r3, #4
mov r4, #5
push {r4} ;第5个参数压栈
bl add_c
pop {r4}
ldmfd sp!, {r0-r12, lr}
bx lr
2)C语言调用汇编函数
汇编文件中用export导出函数
C文件中用extern声明
汇编函数内部要负责现场保护与恢复
cpp
export asm_func
asm_func
add r2, r2, #100
bx lr
8.MRS MSR
处理器工作模式切换
MRS
读特殊寄存器(CPSR)到通用寄存器
MRS{<C>} <Rd>, <spec_reg>
MSR
把通用寄存器的值写入特殊寄存器(CPSR)
MSR{<C>} <spec_reg>, <Rd>
切换到USER模式:
cpp
mrs r0, cpsr ;把cpsr读到r0
bic r0, r0, #0x1F ;清除模式位
orr r0, r0, #0x10 ;设置USER模式编码
msr cpsr_c, r0 ;写回cpsr