《ARM汇编编程:基础指令集入门》
ARM汇编基础指令集
一、Cortex-A 的内核寄存器组
二、赋值指令 MOV、LDR
1、MOV
MOV
目标寄存器,
立即数
MOV R0,#1 ;为寄存器R0赋值,值为1
2、LDR
LDR
目标寄存器, =
赋值数
LDR R0,=0xAB00CD ;为寄存器R0赋值,值为0xAB00CD
三、算数指令 ADD、SUB、MUL
注意:运算符只能为 A+B(两个参数),A+B+…超过两个是不允许的
1、ADD加法
ADD
目标寄存器,
寄存器1,
寄存器2(也可以是立即数)
ADD R0,R0,R1 ;*R0 = *R0 + *R1
ADD R0,R0,#10 ;*R0 = *R0 + 10
2、SUB减法
SUB
目标寄存器,
寄存器1,
寄存器2(也可以是立即数)
SUB R0,R0,R1 ;*R0 = *R0 - R1
SUB R0,R0,#10 ;*R0 = *R0 - 10
3、MUL乘法
MUL
目标寄存器,
寄存器1,
寄存器2(也可以是立即数)
MUL R0,R0,R1 ;*R0 = *R0 * R1
MUL R0,R0,#10 ;*R0 = *R0 * 10
四、移位指令 LSL、LSR
1、LSL左移位
MOV
目标寄存器,
寄存器1, LSL
立即数
MOV R0,R1,LSL #4 ;*R0 = *R1 << 4
2、LSR右移位
MOV
目标寄存器,
寄存器1, LSR
立即数
MOV R0,R1,LSR #4 ;*R0 = *R1 >> 4
五、逻辑位指令 AND、ORR、MVN、EOR
1、AND与
AND
目标寄存器,
寄存器1,
寄存器2(也可以是立即数)
AND R0,R0,R1 ;*R0 = *R0 & *R1
AND R0,R0,#0X0F ;*R0 = *R0 & 0X0F
2、ORR或
ORR
目标寄存器,
寄存器1,
寄存器2(也可以是立即数)
ORR R0,R0,R1 ;*R0 = *R0 | *R1
ORR R0,R0,#0X0F ;*R0 = *R0 | 0X0F
3、MVN非
将 操作2 取反的值给目标寄存器
MVN
目标寄存器,
寄存器2(也可以是立即数)
MVN R0,R1 ;*R0 = ~*R1
MVN R0,#0X0F ;*R0 = ~0X0F
4、EOR异或
EOR
目标寄存器,
寄存器1,
寄存器2(也可以是立即数)
EOR R0,R0,R1 ;*R0 = *R0 ^ *R1
EOR R0,R0,#0X0F ;*R0 = *R0 ^ 0X0F
六、跳转指令 B、BL
1、B直接跳转
B
跳转地址(可以是标签,因为标签就是地址)
MOV R0,#100 ;*R0 = 100
B set_R1 ;goto set_R1 (该操作也可以使用 LDR PC,=set_R1 理论是一样的)
ADD R2,R0,R1 ;*R2 = *R0 + *R1 这里将不会执行,因为跳转到set_R1无法再回到当前位置
set_R1:
MOV R1,#200
2、BL暂存当前位置后直接跳转
BL与B的不同之处就是,在跳转(给PC赋值)之前,先保存了当前的程序运行位置的地址(保存在了寄存器LR中)
B L
跳转地址(可以是标签,因为标签就是地址)
MOV R0,#100 ;*R0 = 100
BL set_R1 ;goto set_R1 (该操作也可以使用: MOV LR,PC SUB LR,LR,#4 LDR PC,=set_R1 理论是一样的)
ADD R2,R0,R1 ;*R2 = *R0 + *R1 这里将不会执行,因为跳转到set_R1无法再回到当前位置
set_R1:
MOV R1,#200
MOV PC,LR
B指令和BL指令在跳转存放的不是一个绝对地址,而存放的是一个相对地址,相对于我当前地址偏移的一个距离,存放的是一个偏移量。
七、比较指令 CMP:EN、EQ、GT、LT、GE、LE
CMP
比较寄存器1,
比较寄存器2(也可以是立即数)
基础指令+模式基础指令相关参数…
EN 》》不等于
EQ 》》等于
GT 》》大于
LT 》》小于
GE 》》大于等于
LE 》》小于等于
在R0 = 10,R1 = 20的情况下
允许赋值指令
CMP R0,R1
MOVEN ,R2,R1
if(*R0 == *R1) *R2 = *R1;
允许算数指令
CMP R0,R1
ADDEN ,R2,R0,R1
if(*R0 == *R1) *R2 = *R0 + *R1;
允许逻辑位指令
CMP R0,R1
EOREN R2,R0,R1
if(*R0 == *R1) *R2 = *R0 & *R1;
允许跳转指令
CMP R0,R1
BLEN fun
CMP R0,R1
BEN fun
if(*R0 == *R1) goto fun;
比较指令允许的指令不止这些,还有很多
八、单个内存读写指令 LDR、STR
1、LDR 读取内存的地址
普通:
LDR
目标寄存器,[
读取地址]
基地址偏移:
LDR
目标寄存器,[
读取地址,
纯偏移]
基地址偏移+改变 :
LDR
目标寄存器,[
读取地址,
偏移并改变]!
普通+改变 :
LDR
目标寄存器,[
读取地址],
偏移并改变
2、STR 写入内存的地址
普通:
STR
目标寄存器,[
读取地址]
基地址偏移:
STR
目标寄存器,[
读取地址,
纯偏移]
基地址偏移+改变 :
STR
目标寄存器,[
读取地址,
偏移并改变]!
普通+改变 :
STR
目标寄存器,[
读取地址],
偏移并改变
LDR
目标寄存器 ,[
读取地址]
九、多个内存读写指令 STM、LDM
模式
IA 先读写,后增加地址
IB 先增加地址,后读写
DA 先读写,后减少地址
DB 先减少地址,后读写
指令+模式 基地址值(必须是寄存器),{写入值} ;基地址(寄存器) 的地址不会发生改变
指令+模式 基地址值(必须是寄存器)!,{写入值} ;基地址(寄存器) 的地址会发生改变
1、STM
LDM 在基地址的基础上,将数据写入偏移数据
设R0 = 0x100,R1 = 1,R2 = 2,R3 = 3;
以R0内存中的数值为基地址,将数据写入对应的 基地址/基地址偏移 内存中;
IA 先读写,后增加地址
STMIA R0,{R1-R3} ;先写入后偏移(向高),但R0内存中的值还是0X100
STMIA R0,{R1,R2,R3} ;编译器会将其转换成STMIA R0,{R1-R3}
STMIA R0,{R3,R2,R1} ;编译器会将其转换成STMIA R0,{R1-R3}
STMIA R0!,{R1-R3} ;先写入后偏移(向高),但最终R0内存中的值也会偏移变为0X110
IB 先增加地址,后读写
STMIB R0,{R1-R3} ;先偏移后写入(向高),但R0内存中的值还是0X100
STMIB R0,{R1,R2,R3} ;编译器会将其转换成STMIB R0,{R1-R3}
STMIB R0,{R3,R2,R1} ;编译器会将其转换成STMIB R0,{R1-R3}
STMIB R0!,{R1-R3} ;先偏移后写入(向高),但最终R0内存中的值也会偏移变为0X110
DA 先读写,后减少地址
STMDA R0,{R1-R3} ;先写入后偏移(向低),但R0内存中的值还是0X100
STMDA R0,{R1,R2,R3} ;编译器会将其转换成STMDA R0,{R1-R3}
STMDA R0,{R3,R2,R1} ;编译器会将其转换成STMDA R0,{R1-R3}
STMDA R0!,{R1-R3} ;先写入后偏移(向低),但最终R0内存中的值也会偏移变为0X0F4
DB 先减少地址,后读写
STMDB R0,{R1-R3} ;先偏移后写入(向低),但R0内存中的值还是0X100
STMDB R0,{R1,R2,R3} ;编译器会将其转换成STMDB R0,{R1-R3}
STMDB R0,{R3,R2,R1} ;编译器会将其转换成STMDB R0,{R1-R3}
STMDB R0!,{R1-R3} ;先偏移后写入(向低),但最终R0内存中的值也会偏移变为0X0F4
2、LDM
LDM 读取基地址内存中的数据,存放到其它地址中
下面只举例 模式IA
设一个R0 = 0X100,R1 = 0,R2 = 0;R1的地址为0X200,R2的地址为0X300;
LDMIA R0,{R1,R2}