处理器内核
ARM7TDMI外部接口图:
指令流水线
为了增加处理器指令流的处理速度,ARM7系列采用了三级流水线,允许多个操作同时进行(一个执行的同时,另一个进行译码,另一个进行取址来提高效率),而非顺序操作。注意:pc指向正在被取址的指令,而非正在执行的指令。
最佳流水线
指令周期CPI=6,6个时钟周期执行了6条指令,所有的操作都在寄存器中
LDR流水线
分支流水线
中断流水线
ARM9TDMI
ARM9TDMI使用了哈佛架构增加了指令存储器接口和数据存储器接口,可以实现指令和数据的同时访问,采用的5级流水线,CPI为1.5,提高了最大时钟频率
图中我们可以看到ARM7和ARM9一些区别,ARM7在执行阶段读寄存器,而ARM9在译码阶段读寄存器。
ARM10
下面我们用一张图来总结一下:
ARM汇编指令集
条件执行和标志位
ARM指令都可以通过添加适当的条件码来达到条件执行的目的,举个例子
CMP r3,#0
ADDNE r0,r1,r2
判断R3寄存器中的内容是否等于0,不等于再执行加指令 r0=r1+r2
我们也可以通过添加后缀 S来影响标志位
例如 SUBS
下面我把一些条件码用一张图呈现出来:
ARM数据处理指令机器码格式
31-28位:为指令的条件码
24-21位:指令的操作码
20位:为标志位S
19-16位:Rn第一操作数寄存器的编码
15-12位:Rd目标寄存器的编码
11-0位:操作数(3-0位:第二操作数R寄存器的编码,5-6位:移位方式,11-7位:移动位数)
注意:不能对立即数进行左移右移操作!!
下面我们来展示一些指令的使用加深印象:
1.搬移指令MOV
@ 搬移指令.text @汇编文本段的开始mov r0, #5 @r0=5mov r1,r0 @ r1=r0mov r2, #1 @ r2=1mov r3, r2, LSL #3 @r3=r2<<3mov r4,r3, LSR #2mrs r6,cpsr @将cpsr状态寄存器的内容搬移到其他寄存器@mov r1,#0x10@msr cpsr,r1 @将R1寄存器内容写入cpsr状态寄存器中.end @汇编文本段的结束
我们在keil中进行编译,可以看到E3A00005是第一条指令的机器码,E为1110是默认的条件码,而24-21位为1101刚好是MOV的操作码,而11-0位为5刚好也是我们的操作数5.
2.逻辑指令 and与,orr或,bic清零
@1.将模式设置为user/system模式mrs r0, cpsr @将cpsr内容取出放到r0寄存器and r0, #0xfffffffc @将r0寄存器的内容相与msr cpsr,r0 @将内容写到cpsr寄存器@2.orr指令orr r0,#0x3mrs r0,cpsr @可以,但是在user模式下可以对cpsr进行读取操作msr cpsr,r0 @不可以,user模式下不是特权模式,不能对cpsr进行写入操作所以不能变回svc模式
注意,当我们通过更改cpsr状态寄存器来切换模式,将SVC切换到user模式后,不能在user模式下再对cpsr寄存器进行写入将其变回svc状态,但是可以进行读取操作
@3.bic指令将FIQ开启mrs r0, cpsrbic r0,#0x40 @将r0中6号位清零msr cpsr,r0
bic指令可以将立即数中为1的bits位清零,我们可以通过这个操作更改状态寄存器的内容,比如上面我们就将状态寄存器中的6号位清零达到开启FIQ的操作。
3.比较指令CMP,TST
@4.tst指令mrs r0,cpsrtst r0,#0x20 @测试r0的第5号位是否为0@5.cmp指令cmp r0,#1 @比较r0寄存器中的内容是否和1相等@6.判断当前状态是否是ARM状态,是则切换到user工作模式mrs r0,cpsrtst r0,#0x20biceq r0,#0x3msreq cpsr,r0
可以看到在判断之后我们的清零和写入操作都加上了条件码,满足对应的条件才会执行对应的指令
4.跳转指令b,bl
b:跳转到某段标号的代码处
bl:跳转到某个标号处,同时记录下一条指令的地址到LR寄存器
@1.跳转指令b.text@编写代码实现1+2+。。。。+10mov r0,#1loop: @某段代码的标号cmp r0,#11addlt r1,r1,r0 @lt表示条件码addlt r0,#1blt loop@跳转到loopNOP @空指令.end
可以看到我们代码中加了条件码来达到我们的执行条件就是当r0中寄存器的内容小于11时执行加法指令和跳转指令来达到循环的效果。
@2.跳转指令bl.textmain:mov r0,#2@ bl 跳转到某个标号处,同时记录下一条指令的地址到LR寄存器bl func1while:b whilefunc1:mov r6,lrcmp r0,#2bleq func2blne func3mov pc,r6 @让cpu到lr指定的地址处取指令,也就是回到bl的下一条指令处func2:add r0,#3mov pc,lrfunc3:sub r0,#1mov pc,lr.end
bl在执行跳转的时候会将我们下一条指令的地址放到lr中,但是在func1中我们又会进行一次条件跳转可能会导致之前的指令地址被覆盖,所以我们将地址保存到了r6寄存器中,这样func1执行完毕后才能跳转回原来该继续执行的位置。
5.load和store
ldr默认读4个字节,ldrb读一个字节,ldrh读两个字节
下面我们来看看例子:
.textmain:@ldr伪指令,将buf这个地址不合法的立即数写到r0中ldr r0,=buf@ldrb将r0地址上的第一个字节数据读到r1中ldrb r1,[r0]@ldrb将r0+4地址上的第一个字节读到r1中ldrb r1,[r0,#4]mov r2,#0x9@strb将r2中的数据前1个字节写入r0+2地址上@ *(r0+2)=r2strb r2,[r0,#2]main_end:NOPNOP.data @汇编文件数据段的开始buf:@buf相当于缓冲区的首地址(数组名)@.byte 表示一个字节空间.byte 0x1,0x2,0x3,0x4,0x5.end
如果觉得《ARM体系结构2:处理器内核和汇编指令集》对你有帮助,请点赞、收藏,并留下你的观点哦!