1.什么是汇编指令
汇编指令:是机器指令的助记符,经过编译后会得到一串01010组成的机器码,可以由cpu读取执行
伪指令:本质上不是指令,只是和指令一起写在代码中,是指导编译过程的,是编译系统提供的,不会生成对应的机器码
2.数据搬移指令(指令格式)
mov r0, #1 @将立即数1赋值给r0
mov r1,r0 @将r0的值赋值给r1
mov r2, r0, lsl #1 @将r0的值左移1位赋值给r2
mov r3, r2, lsr #2 @将r2的值右移两位赋值给r3
mvn r5,r3 @将r3取反之后赋值给r5
.text @定义一个指令段
mov r0,#3
mov r1,r0
mov r2, r1, lsl #2
mov r3,r2,lsr #1
mvn r5,#0
.end @表示汇编程序结束
汇编指令的格式:
<opcode> {<cond>} {s} <rd>, <rn>,{<operand2>}
其中:<>是必须的
{}是可选的
opcode:汇编指令
cond:执行条件
s:是否影响cpsr寄存器的值(cpsr的条件位)
rd:目标寄存器
rn:第一操作数寄存器,只能是寄存器
operand2:第二操作数
以mov指令为例,学习机器指令格式:
mov {cond} {s} rd, op2
31-28 27 26 25 24-21 20 19-16 15-12 11-0
[31-28]:条件码
27-26:预留 默认为0
25: 1----->第二操作数是立即数 0----->第二操作数是寄存器
24-21:操作码 mov------>1101
20:1------>影响cpsr的值 0------>不影响cpsr的值
19-16:第一操作数寄存器
15-12:目标寄存器
11-0:第二操作数寄存器
如果是立即数:0-7位 立即数
11-8:移位值
最终的立即数 = 立即数 循环右移 (移位值*2)位
合法立即数:如果一个32位的数,可以通过0-7位的数循环右移偶数位得到就是合法的
0x00ab0000(合法) 0x0000ffff (不合法) 0x10000001(合法)
E3A00001
1110 001 1101 0 0000 0000 0000 0000 0001
总结:如果立即数是0-255,绝对是合法的,可以直接使用mov指令,而如果大于255,就直接使用ldr伪指令就好
三级流水线:取指 译码 执行
pc:正在取指的指令的地址
正在执行的指令的地址 = pc-8
3.算术指令
add r0,r1,r2 @r0 = r1+r2
add r0,r1 @r0+=r1
sub @减法
mul @乘法
.text
mov r0, #1
mov r1, r0
add r2,r0,r1
sub r3,r2,#1
mul r5,r2,r3
.end
4.逻辑指令
and r0, r1, r2 @r0 = r1 & r2
orr r0,r1,r2 @r0 = r1 | r2
bic r0, 0xff @将r0的0-7位清0
.text
mov r0, #0xff
mov r1, #0xef
and r2,r0,r1
orr r3, r0, r1
bic r2, #0x2
.end
5.比较指令
cmp r0,r1 @比较r0和r1的大小
cmp r0,#1 @比较r0和1的大小
moveq r2,#2 @当r0==1的时候,将2赋值给r2
tst r0,#0x2 @测试r0的第2位(从1算的)是否为0
moveq r2,#0xdd
movne r2,#0xee
注意:cmp和tst会自动引起cpsr值的变化
.text
mov r0,#1
mov r1,r0
cmp r1,#1
moveq r2,#0xff
@tst r0,#0x2
@moveq r2,#0xdd
@movne r2,#0xee
.end
6.跳转指令
b loop @跳转到loop这个语句标号处
loop:
nop
nop
其中:nop是空指令,只占用时间,不做任何事情
loop:语句标号,表示的是它下一条指令的地址
实现1-5的累加和
.text
.if 0
mov r0,#1 @i
mov r1,#0 @sum
loop:
cmp r0,#6
addlt r1,r0
addlt r0,#1
blt loop
nop
nop
nop
.endif
.end
bl:在跳转时,会将返回地址自动保存到lr中
总结:b------->循环 bl------>调用函数
汇编中如何传参?
规定:r0-r3就是参数 r0是返回值
如果超过四个参数,就入栈
注意:lr = pc-4
.text
main:
nop
nop
nop
mov r0,#1
mov r1,#5
nop
bl addFunc
nop
nop
nop
addFunc:
mov r5,#0 @sum
loop:
cmp r0,r1
addls r5,r0
addls r0,#1
blt loop
mov r0,r5
addFunc_end:
mov pc,lr
.end
7.内存访问指令
ldr:将内存的值拷贝到寄存器
str:将寄存器的值拷贝到内存
前提:内存是通过地址访问的
ldr r0,[r1] @将r1这个地址的内容拷贝给r0,r1存的是一块内存的首地址
@r0 = *r1
str r0,[r1] @*r1 = r0
.text
@将a的值拷贝给c
@将a的值拷贝到寄存器
ldr r1,=a @伪指令
ldr r2,=c
ldr r0,[r1] @汇编指令
@将寄存器的值拷贝给c
str r0,[r2]
.data: @定义一个数据段
@定义变量a和c
a:
.word 0x12345678 @在存储器中分配4个字节的内存单元,与int一样
c:
.word 0x0
.end
ldr和str:四个字节
ldrb和strb: 一个字节
ldrh和strh:两个字节
拷贝字符串:
一次拷贝一个字符
ldr r0,[r1, #4] @r0 = *(r1+4)
ldr r0,[r1],#4 @r0=*r1, r1+=4
.text
@将str1的值拷贝给str2
ldr r1,=str1
ldr r2,=str2
loop:
ldrb r0,[r1],#1
cmp r0,#0
beq done
strb r0,[r2],#1
b loop
done:
nop
nop
nop
.data
str1:
.string "abcde\0" @定义字符串
str2:
.space 10 @申请10个字节空间
.end