ARM编程模型
ARM SVC:复位,执行SWI指令
快速中断FIQ:发生高优先级的中断
中断IRQ:发生低优先级的中断
中止:访问存储器发生非法情况
未定义:执行指令,不能识别
系统:与用户模式共用寄存器的特权模式
用户:多数应用程序与系统任务运行在模式
2,工作模式的分类
异常/非异常:
异常:管理,快速中断,中断,中止,未定义
非异常:系统,用户
特权/非特权
特权:管理,快速中断,中断,中止,未定义,系统
非特权:用户模式
3,工作模式之间是是否可以切换,如何切换?
工作模式之间可以切换
切换的方式有两种:
1,处理器自动切换:当发生异常,处理器自动进入对就的异常模式
2,指令切换
工作模式之间切换需要遵循的原则:
1,特权模式之间可以随意切换
2,可以从特权模式进入到用户模式,不能直接从用户模式切换到特权模式
3,如果用户模式切换到特权模式,可以通过调用SWI指令来完成。
4,ARM的运行状态
字对齐
0x20008000
0x20008004
0x20008008
0x2000800C
0x200080010
0x200080014
5,运行状态的切换
用指令切换
6,寄存器
在cortex-A8核心里
所有的寄存器都是没有地址,如果要用,直接使用r0,r1,r2
寄存器都是32bit
Ro-R12通用寄存器
R13(SP):栈顶指针,栈顶的地址,栈是内存的一个区域
异常模式下,都有自己的栈,对应R13保存栈顶指针
在异常发生时,CPU会自动切换到异常模式下,先保护现场
,将上一模式时,再将栈中保存的值依次出栈到对应的寄存器。
R14(LR):存放返回地址
R15(PC):只有一个,存放取指的指令地址
执行一条指令,分三个阶段:
取指
解码
执行
ARM寄存器
ARM支持的数据类型
内存的对齐方式:字、半字、字节
ARM存储格式:大端、小端
ARM指令:
汇编代码示例:
.text
.code 32
.global start //标号
start:
mov r0,#10 // r0 = 10
ldr r1,=3 //伪指令
add r0,r0,r1 //
b .
.end
ARM指令
示例
start:
cmp r0,r1 //比较r0-r1
beq not_copy //r0=r1相等时,跳转到not_copy执行。相当于c语言中的goto语句
mov r0,r1//r0 != r1时,r0=r1
not_copy:
.....
跳转范围: PC(new) = PC(当前) + 32MB 或 PC(当前) - 32MB
24bit用来表示偏移量
1bit 符号位
23bit偏移量 2^20 = 1MB ==>8*2^20 = 8MB
arm指令地址的特点:字对齐,最后的2bit为0
bl 指令跳出去执行完以后,会跳转回来,而b指令则不会跳回来
bl 2000807 delay //bl相当于函数的执行,执行以后,会跳回来
START:
MOV R0,#1 //R0=1
MOV R1,#2 //R1=2
//在执行BL指令时,CPU会自动将下一条指令的地址(B.)保存到LR寄存器,再跳转
BL DoAdd //相当于C语言中调用函数
B.
DoAdd
ADD R0,R0,R1 //RO = R0 + R1
MOV PC,LR //返回函数指令, PC = LR ,LR是存放返回地址的
.CODE 32 //ARM_code
ARM_code:
ADR R0,THUMB_code + 1 //THUMB_code + 1其实为:ADR R0,ARM_code,R0 = THUMB_code + 1
BX RO//带状态切换的跳转指令,在执行前会干以下两件事:
//1,CPSR[5] = R0[0],把当前状态改为了Thumb状态 ;CPSR[5] = 0为表示ARM状态,CPSR[5] = 1表示THUMB状态
//2,PC = R0 & 0xFFFFFFFE ==>把R0的第0位清0(因为前加了一个1)
...
.CODE 16 //THUMB_code
THUMB_code:
ADR R0,ARM_code//理由同上
BX R0//1,CPSR[5] = R0[0],将当前状态改为ARM状态
//2,PC = R0 & 0xFFFFFFFE
....
相对跳转:与当前PC相关
B BL
绝对跳转:
BX
BX: 指令是不带返回的,绝对跳转,调整范围4G,跳转到寄存器指定的地址
1,Rm[0]给CPSR的1位,改变当前程序状态
2,PC = R0 & 0xFFFFFFFE
BLX:既带状态又带返回
1,保存一条指定地址到LR
2,Rm[0]给CPSR的1位,改变当前程序状态
3,PC = R0 & 0xFFFFFFFE
B:相对跳转,PC(跳转) = PC(当前) +/- 偏移量(32MB),跳过去不返回
BL:相对跳转,PC(跳转) = PC(当前) +/- 偏移量(32MB),跳过去会返回
CPU会将下一条指令的地址给LR,然后跳转,通过手动返回,如:
MOV PC,LR //手动返回,一般用于函数的调用
案例:
1,编写sub.s ,sub.s代码如下:
.text //代码段
.code 32 //ARM模式
.global do_sub
do_sub:
mov r1,#10 //把10赋值给r1
mov r0,#0x14
sub r0,r0,r1
b . //
.end
2,安装4.4.1交叉编译器,因为这个低版本的编译器里面有arm-linux-gdb调试工具
arm-0009q3.tar.bz2
编译器安装方法
cd /home/tarena
mkdir opt
cd opt
sudo tar jxvf /路径
cd /home/tarena/opt/arm-2009q3/bin
cd /home/tarena
vi .bashrc
PATH = /解压目录/.../bin:$PATH:. #在.bashrc中最后一行添加这一句
修改完之后执行 “source .bashrc”让环境变量生效
arm-linux-gcc -v 查看最新的版本
查看是否存在arm-linux-gdb:
arm-linux-g
安装qemu软件包,用qemu在PC机模拟板子运行环境,这样的话,就可以在PC机上查看寄存器的值。
安装方法:
1,下载安装包
2,
cd /mnt/hgfs/1408/qemu/qemu
sudo dpkg -i * //解压安装
至此,运行环境搭建完毕
开始编译sub.s文件
cd 到sub.s文件所在目录:
cd /mnt/hgfs/1408/sub
arm-linux-as -g -o sub.o sub.s #编译,-g相当于在代码中添加调试信息
arm-linux-ld -e do_sub -o sub sub.o #链接,do_sub是代码中的一个全局标号,代码从这开始执行
qemu-arm -g 1234 sub #将sub程序在qemu虚拟环境中运行
执行完“qemu-arm -g 1234 sub ”后,在虚拟机中重新打开一个标签页,还是在相应的目录下面,执行:
arm-linux-gdb sub
(gdb)targe remote localhost:1324
(gdb)s #s相当于单独执行
(gdb)s #直到运行到 “b .”
(gdb)info r #查看寄存器