ARM体系结构的数据存储格式
- 小端:低位放在低地址
- 大端:低位放在高地址
指令长度及数据类型
1.CPU与内存之间的连线:中间是用数据总线(32根线就能表示CPU是32位即4个字节)连接的
2.字节:8位
3.半字:16位
4.字:32位
异常
- 只要正常的程序流被暂时中止,处理器进入异常模式。例如响应一个来自外设的中断。在处理异常之前,ARM9内核保存当前的处理器状态(CPSR>SPSR),这样当处理程序结束时可以恢复执行原来的程序()(SPSR->CPSR)
- 如果同时发生两个或更多的异常,那么将按照固定的顺序来处理异常,即异常优先级
异常优先级
复位异常
未定义指令异常
软件中断异常
预取中止异常
IRQ
FIQ
数据中止异常
对异常的响应
- 在异常发生后,ARM9内核会作以下工作
- 在适当的LR中保存下一条指令的地址,当异常入口来自:
1.ARM状态,那么ARM9将当前指令地址加4或8复制(取决于异常的类型)到LR中
2.为Thumb状态,那么ARM9将当前指令地址加2,4或加8(取决于异常的类型)复制到LR中,异常处理器程序不必确定状态
3.如果同时发生两个或更多异常,那么将按照异常的优先级的顺序来处理异常
- 将CPRS复制到适当的SPSR中
- 将CPSR模式位强制设置为与异常类型相对应的值
- 强制PC从相关的异常向量处取指
- ARM9内核在处理中断异常时置位中断禁止标志,这样可以防止不受控制的异常嵌套
ARM微处理器指令系统
ARM微处理器的指令的分类与格式
ARM是三地址指令格式,指令的基本格式如下
1.<opcode> {<cond>} {s} <Rd>,<Rn>{,<operand2>}
- 其中<>号内的项时必须的,{}号内的项时可选的.
opcode:指令助记符;
cond:执行条件;
s:是否影响CPSR寄存器的值;
Rd:目标寄存器
Rn:第1个操作数的寄存器
operand2:第2个操作数
指令的条件域
<opcode> {<cond>} {S} <Rd>,<Rn>{,<operand2>}
- 使用条件码"cond"可以实现高效的逻辑操作(节省跳转和条件语句),提高代码效率
- 所有的ARM指令都可以条件执行,而Thumb指令只有B(跳转)指令具有条件执行功能.如果指令不标明条件代码,将默认为无条件(AL)执行
指令的条件域
- 指令条件码表
- 示例
(1)C代码
if(a>b)
{
a++;
}
else
{
b++;
}
(2)对应的汇编代码
CMP R0,R1//R0(a)与R1(b)比较
ADDHI R0,R0,#1//若R0>R1,则R0=R0+1
ADDLS R1,R1,#1//若R0<=R1,则R1=R1+1
### ARM指令集
#### 跳转指令
>- 在ARM中有两种方式可以实现程序的跳转,一种是使用分支指令直接跳转,另一种则是直接向PC寄存器赋值实现跳转(MOV指令).分支指令有一下三种:
>1.分支指令B
>2.带链接的分支指令BL
>3.带状态切换的分支指令BX
>4.带返回和状态切换的跳转指令BLX
ADRL R0,ThumbFun+1 //将Thumb程序的入口加1存入R0 (+1表示状态切换)
BX R0
#### 数据处理指令
>- 数据处理指令大致可分为3类
>1.数据传送指令
>2.算术逻辑运算运算
>3.比较指令
>- 数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作.所有ARM数据处理指令均可选择使用S后缀,以使指令影响状态标志
### 乘法指令
#### 乘法与乘加指令
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-7a918f31200f8aaa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-b2f47bb2a013d265.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>- MUL Rd,Rm,Rs//Rm*Rs放入Rd
>- 64位无符号乘法指令:UMULL RdLo,RdHi,Rm,Rs //Rm*Rs的低32位放在RdLo里,高32位放在RdHi里面
### 程序状态寄存器访问指令
>- MRS{cond} Rd,psr
>- MRS:将psr寄存器里面的值存放到CPU里面的寄存器
>- MSR:将CPU里面的寄存器的内容存放到指定的psr寄存器中
### ARM指令的寻址方式
#### 立即数寻址
>- mov r0 #10
>- 判断立即数是否合法:将立即数(16进制)用二进制表示,再将低位与高位的偶数个0去掉,剩下的位数<=8位,则合法,否则不合法
#### 立即数续
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-6bbe196704fe60e3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#### 寄存器寻址
>- mov R1,R2//将R2的值放入R1中
>- SUB R,R1,R2//
#### 寄存器间接寻址
>- LDR R1,[R2] //将R2指向的存储单元的数据读出保存到R1寄存器中
>- SWP R1,R1,[R2]
>- 可以访问内存空间的指令:LDxxx,STxxx,SWPxxx
#### 寄存器偏移寻址
>- mov R0,R2,LSL #3//将R2里面的值逻辑左移3位再放到R0中
>- mov R0,R2,LSL R1
>1.逻辑左移:LSL 高位扔掉,低位补0
>2.逻辑右移:LSR 低位扔掉,高位补0
>3.数学左移:ASL 拿符号位,补低位
>4.数学右移:ASR 拿到高位,补0
>5.循环右移:ROR 低位拿出,补高位
>6.带扩展的循环右移:RRX
>7.桶形移位器
#### 基址变址寻址
>- (前索引)LDR R2,[R3,#0x0C]//读取R3+0x0C地址上的存储单元的内容,放入R2
>- STR R1,[R0,#-4]!//先R0=R0-4,然后把R0的值寄存到保存到R1指定的存储单元
>- (后索引)LDR R0,[R1],#4//将R1指向的存储单元的值放到R0,然后R1的地址加4
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-21d1c1fef7068346.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-22699cd6981d8284.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#### 多寄存器寻址
>- LDMIA R1!,{R2-R4,R12}//将R1指向的单元中的数据读出到R2-R4 、R12中(R1自动加4)
>- STMIA R0!{R2-R4,R12}//将R2-R4 、R12指向的单元中的值保存到R0指向的数据单元中(R0自动加4)
##### 多寄存器寻址续(基址寄存器的增长方式)
>1.IA:每次传送后地址增加4
>2.IB:每次传送前地址增加4
### 堆栈寻址
>- 堆栈是一个按特定顺序存取的存储区,操作顺序为"后进先出".堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶.存储器堆栈可分为两种:
>1.向上生长:向高地址方向生长,称为递增堆栈
>2.向下生长:向低地址方向生长,称为递减堆栈
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-aec2b40fa40d5d05.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
>- 堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个待压入数据额空位置,称为空堆栈
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-af9c929c65ddf070.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
##### 堆栈寻址续
![Paste_Image.png](http://upload-images.jianshu.io/upload_images/3245624-347ab5074bd2fdd6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#### 相对寻址
BL SUBR1//调用到SUBR1子程序
BEQ LOOP//条件跳转到LOOP标号处
......
LOOP MOV R6,#1
......
SUBR1
### ARM汇编语言的基本框架
AREA ARMexp1,CODE,READONLY
ENTRY
start
MOV r0,#10
MOV r1,#3
ADD r0,r0,r1
stop
MOV r0,#0x18
LDR r1,=0x20026
SWI 0x123456
END
### C语言编译的几个步骤
>1.预处理:傻替换,条件编译
>2.编译:把C语言程序翻译成汇编语言的程序编
>3.汇编:把每一条指令翻译成二进制语句
>4.链接
预处理 编译 汇编 链接
1.c 1.i 1.S 1.o 将1.o,2.o,3.o,库文件 生成可执行的文件
2.c 2 .i 2.S 2.o
3.c 3.i 3.S 3.o
>- register int i;//如果有寄存器可用,则将i变量保存到寄存器中,不放在内存中,
>- register int &i//是错误的,因为不在内存里,所以没有地址(以防可能有寄存器或无寄存器,都不要这样写)