常⽤ARM指令
常⽤ARM指令1:数据处理指令
mov mvn
MOV(MOVE)指令可完成从另⼀个寄存器、被移位的寄存器或将⼀个⽴即数加载到⽬的寄存器
MOV R0,R1;R1的值传到R0
MOV R3,#3 ;把常数3传给R3
MVN( MOVE Negative)取反后再传值,⽐MOV多了⼀步取反
MVN R0, #0 ;把0取反(即-1)传给R0
MVN R1,R2 ;把R2的值取反传给R1
算术指令
add sub rsb adc sbc rsc
ADD加法指令
ADD R0,R1,R2; R0=R1+R2
ADD R0,R1,#3 ;R0=R1+3
ADC带进位加法指令,即除了加两个数以外,还要把CPSR的C值也要带进来
通常⽤于⼤数(超过32Bit整数)相加,这时单⽤ADD不能处理,必须折成两步,其中⼀步⽤ADC.
以下是做64Bit的加法
ADDS R0,R1,R2; R0=R1+R2,ADDS中S表⽰把进位结果写⼊CPSR
ADC R5,R3,R4 ;R5=R3+R4+C
逻辑指令
and orr eor bic
AND位与指令
AND R0,R1,R2; R0=R1 & R2
AND R0,R1,#0xFF ;R0=R1 & 0xFF
ORR位或指令
ORR R0,R1,R2; R0=R1 | R2
ORR R0,R1,#0xFF ;R0=R1 | 0xFF
TST测试某⼀位是否为1,并把结果写⼊CPSR,供下⼀句使⽤
TST R1,#0xffe; 等同于if(R1 & 0xffe)
TST R1,#%1;测试最低位是否为1,%表⽰⼆进制
BIC清位操作
BIC R0,R0,#0xF;等同于 R0 &=~(0xF)
BIC R0,R0,#%1011;该指令清除 R0 中的位 0 1 3,其余的位保持; %表⽰是⼆进制,0x表⽰⼗六进制 ⽐较指令
cmp cmn tst teq
CMP⽐较两个操作数,并把结果存⼊CPSR供下⼀句语句使⽤
CMP R0,R1; ⽐较R0,R1
乘法指令
mvl mla umull umlal smull small
MUL R0,R1,R2 ;R0 = R1 × R2
MULS R0,R1,R2 ;R0 = R1 × R2,同时设置CPSR中的相关条件标志位
MLA R0,R1,R2,R3 ;R0 = R1 × R2 + R3
MLAS R0× R2 + R3,同时设置CPSR中的相关条件标志位
SMULL R0,R1,R2,R3 ;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的⾼32位
加载/存储指令 LDR,STR
LDR R0,[R1]; R1的值当成地址,再从这个地址装⼊数据到R0 (R0=*R1)
LDR R1,=0x30008000 ; 把地址0x30008000的值装⼊到R1中
STR R0,[R1] ; 把R0的值,存⼊到R1对应地址空间上(*R1 = R0)。
STR R0,=0x30008000 ;把R0中值存⼊到地址0x30008000
常⽤ARM指令2:cpsr访问指令
mrs & msr
mrs⽤来读psr,msr⽤来写psr
CPSR寄存器⽐较特殊,需要专门的指令访问,这就是mrs和msr。
常⽤ARM指令3:跳转(分⽀)指令
b & bl & bx
b 直接跳转(就没打开算返回)
B main ;跳转到标号为main地代码处
bl branch and link,跳转前把返回地址放⼊lr中,以便返回,以便⽤于函数调⽤ bx跳转同时切换到ARM模式,⼀般⽤于异常处理的跳转
常⽤ARM指令4:访存指令
ldr/str & ldm/stm & swp
单个字/半字/字节访问 ldr/str
多字批量访问 ldm/stm
swp r1, r2, [r0]
swp r1, r1, [r0]
常⽤ARM指令5:软中断指令
swi(software interrupt)
软中断指令⽤来实现操作系统中系统调⽤
协处理器cp15操作指令
mcr & mrc
mrc⽤于读取CP15中的寄存器
mcr⽤于写⼊CP15中的寄存器
MRC & MCR的使⽤⽅法
mcr{<cond>} p15, <opcode_1>, <Rd>, <Crn>, <Crm>, {<opcode_2>}
opcode_1:对于cp15永远为0
Rd:ARM的普通寄存器
Crn:cp15的寄存器,合法值是c0~c15
Crm:cp15的寄存器,⼀般均设为c0
opcode_2:⼀般省略或为0
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1
mcr p15, 0, r0, c1, c0, 0
8种后缀
ia(increase after)先传输,再地址+4
ib(increase before)先地址+4,再传输
da(decrease after)先传输,再地址-4
db(decrease before)先地址-4,再传输
fd(full decrease)满递减堆栈
ed(empty decrease)空递减堆栈
fa(·······)满递增堆栈
ea(·······)空递增堆栈
四种栈
空栈:栈指针指向空位,每次存⼊时可以直接存⼊然后栈指针移动⼀格;⽽取出时需要先移动⼀格才能取出
满栈:栈指针指向栈中最后⼀格数据,每次存⼊时需要先移动栈指针⼀格再存⼊;取出时可以直接取出,然后再移动栈指针 增栈:栈指针移动时向地址增加的⽅向移动的栈
减栈:栈指针移动时向地址减⼩的⽅向移动的栈
!的作⽤
ldmia r0, {r2 - r3}
ldmia r0!, {r2 - r3}
感叹号的作⽤就是r0的值在ldm过程中发⽣的增加或者减少最后写回到r0去,也就是说ldm时会改变r0
的值。
^的作⽤
ldmfd sp!, {r0 - r6, pc}
ldmfd sp!, {r0 - r6, pc}^
^的作⽤:在⽬标寄存器中有pc时,会同时将spsr写⼊到cpsr,⼀般⽤于从异常模式返回。
伪指令的意义
伪指令不是指令,伪指令和指令的根本区别是经过编译后会不会⽣成机器码。
伪指令的意义在于指导编译过程。
伪指令是和具体的编译器相关的,我们使⽤gnu⼯具链,因此学习gnu环境下的汇编伪指令。
gnu汇编中的⼀些符号
@ ⽤来做注释。可以在⾏⾸也可以在代码后⾯同⼀⾏直接跟,和C语⾔中//类似
# 做注释,⼀般放在⾏⾸,表⽰这⼀⾏都是注释⽽不是代码。
:以冒号结尾的是标号
. 点号在gnu汇编中表⽰当前指令的地址
# ⽴即数前⾯要加#或$,表⽰这是个⽴即数
常⽤gnu伪指令
.global _start @ 给_start外部链接属性 .section .text @ 指定当前段为代码段
.ascii .byte .short .long .word
.quad .float .string @ 定义数据
.align 4 @ 以16字节对齐
.balignl 16 0xabcdefgh @ 16字节对齐填充偶尔会⽤到的gnu伪指令
.end @标识⽂件结束
.include @ 头⽂件包含
.arm / .code32 @声明以下为arm指令
.thumb / .code16 @声明以下为thubm指令
最重要的⼏个伪指令
ldr ⼤范围的地址加载指令
adr ⼩范围的地址加载指令
adrl 中等范围的地址加载指令
nop 空操作
比较指令cmp怎么用
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论