目录
方式一:直接修改PC寄存器的值(不建议使用,需要自己计算目标指令的绝对地址)
方式二:不带返回的跳转指令,本质就是将PC寄存器的值修改成跳转标号下指令的地址
方式三:带返回的跳转指令,本质就是将PC寄存器的值修改成跳转标号下指令的地址,同时将跳转指令下一条指令的地址存储到LR寄存器
一、跳转指令
实现程序的跳转本质上就是修改了PC寄存器的值
一般一个函数编译成的汇编指令在内存中是连续的
方式一:直接修改PC寄存器的值(不建议使用,需要自己计算目标指令的绝对地址)
@ MAIN:
@ MOV R1, #1
@ MOV R2, #2
@ MOV R3, #3
@ MOV PC, #0x18
@ MOV R4, #4
@ MOV R5, #5
@ FUNC:
@ MOV R6, #6
@ MOV R7, #7
@ MOV R8, #8
方式二:不带返回的跳转指令,本质就是将PC寄存器的值修改成跳转标号下指令的地址
@ MAIN:
@ MOV R1, #1
@ MOV R2, #2
@ MOV R3, #3
@ B FUNC
@ MOV R4, #4
@ MOV R5, #5
@ FUNC:
@ MOV R6, #6
@ MOV R7, #7
@ MOV R8, #8
![](https://i-blog.csdnimg.cn/blog_migrate/8e7b8e34bc840d09d032372c9713df4b.png)
方式三:带返回的跳转指令,本质就是将PC寄存器的值修改成跳转标号下指令的地址,同时将跳转指令下一条指令的地址存储到LR寄存器
@ MAIN:
@ MOV R1, #1
@ MOV R2, #2
@ MOV R3, #3
@ BL FUNC
@ MOV R4, #4
@ MOV R5, #5
@ FUNC:
@ MOV R6, #6
@ MOV R7, #7
@ MOV R8, #8
@ MOV PC, LR
@ 程序返回
C语言的函数调用
二、ARM指令的条件码
2.1比较指令
@ CMP指令的本质就是一条减法指令(SUBS),只是没有将运算结果存入目标寄存器
@ MOV R1, #1
@ MOV R2, #2
@ CMP R1, R2
@ BEQ FUNC
@ 执行逻辑:if(EQ){B FUNC} 本质:if(Z==1){B FUNC}
@ BNE FUNC
@ 执行逻辑:if(NE){B FUNC} 本质:if(Z==0){B FUNC}
@ MOV R3, #3
@ MOV R4, #4
@ MOV R5, #5
@ FUNC:
@ MOV R6, #6
@ MOV R7, #7
R1 和 R2不相等,并没有跳转,相等时发生跳转
换成BNE跳不了了
2.2ARM指令集中大多数指令都可以带条件码后缀
@ MOV R1, #1
@ MOV R2, #2
@ CMP R1, R2
@ MOVGT R3, #3
C语言翻译成汇编
2.3练习:用汇编语言实现以下逻辑
@ int R1 = 9;
@ int R2 = 15;
@ START:
@ if(R1 == R2)
@ {
@ STOP();
@ }
@ else if(R1 > R2)
@ {
@ R1 = R1 - R2;
@ goto START;
@ }
@ else
@ {
@ R2 = R2 - R1;
@ goto START;
@ }
我的答案比较笨,也许是病没好的事
.text
.global _start
_start:MOV R1, #9
MOV R2, #15
START:
CMP R1, R2
BEQ STOP
BHI FUNC
SUB R2, R2, R1
B START
STOP:
B STOP
FUNC:
SUB R1, R1, R2
B START
.end
老师的就简便多了
@ 练习答案
MOV R1, #9
MOV R2, #15
START:
CMP R1,R2
BEQ STOP
SUBGT R1, R1, R2
SUBLT R2, R2, R1
B START
STOP:
B STOP
三、Load/Srore指令:访问(读写)内存
一般LD开头的指令将指令从内存读到CPU,ST开头的指令将CPU的指令拿到内存。
在debug模式下单击Memory map,可以告诉我们当前芯片每段的权限
3.1写内存
@ MOV R1, #0xFF000000
@ MOV R2, #0x40000000
@ STR R1, [R2]
@ 将R1寄存器中的数据写入到R2指向的内存空间
同时验证了ARM是小端对齐的
数据是几个字节数据的起始地址就是几的整数倍
3.2读内存
@ LDR R3, [R2]
@ 将R2指向的内存空间中的数据读取到R3寄存器
3.3读/写指定的数据类型
@ MOV R1, #0xFFFFFFFF
@ MOV R2, #0x40000000
@ STRB R1, [R2]
@ 将R1寄存器中的数据的Bit[7:0]写入到R2指向的内存空间
@ STRH R1, [R2]
@ 将R1寄存器中的数据的Bit[15:0]写入到R2指向的内存空间
@ STR R1, [R2]
@ 将R1寄存器中的数据的Bit[31:0]写入到R2指向的内存空间
@ LDR指令同样支持以上后缀
四、ARM指令的寻址方式
寻址方式就是CPU去寻找操作数的方式
4.1立即寻址
@ MOV R1, #1
@ ADD R1, R2, #1
4.2寄存器寻址
@ ADD R1, R2, R3
4.3寄存器移位寻址
@ MOV R1, R2, LSL #1
4.4寄存器间接寻址
@ STR R1, [R2]
4.5基址加变址寻址
@ MOV R1, #0xFFFFFFFF
@ MOV R2, #0x40000000
@ MOV R3, #4
@ STR R1, [R2,R3]
@ 将R1寄存器中的数据写入到R2+R3指向的内存空间(以R2为基地址偏移R3的数量)
@ STR R1, [R2,R3,LSL #1]
@ 将R1寄存器中的数据写入到R2+(R3<<1)指向的内存空间
4.6基址加变址寻址的索引方式
4.6.1前索引
@ MOV R1, #0xFFFFFFFF
@ MOV R2, #0x40000000
@ STR R1, [R2,#8]
@ 将R1寄存器中的数据写入到R2+8指向的内存空间
4.6.2后索引
@ MOV R1, #0xFFFFFFFF
@ MOV R2, #0x40000000
@ STR R1, [R2],#8
@ 将R1寄存器中的数据写入到R2指向的内存空间,然后R2自增8
4.6.3自动索引
@ MOV R1, #0xFFFFFFFF
@ MOV R2, #0x40000000
@ STR R1, [R2,#8]!
@ 将R1寄存器中的数据写入到R2+8指向的内存空间,然后R2自增8
@ 以上寻址方式和索引方式同样适用于LDR