ARM小结
来源:互联网 发布:崩坏3rd矩阵空间 编辑:程序博客网 时间:2024/04/30 03:24
一:
B与BL异同点:
相同点:
都是分支语句
范围大小一样PC+_32M对一条32位机器码的指令,要跳转的指令中已经包含了地址,32位中的4位代表条件位,4位代表指令的类型,剩余的用来表示地址,但PC值的最后两位没有用,然而我们也把它们计算进去, 这有2^(32-4-4+2)=64M,因为要上下跳,所以PC+_32M
不同点:
B是无连接,跳转后不能返回,对应C中的IF..ELSE
BL是带连接的跳转,相当与C语言中的循环语句。
对于非叶子结点,LR必须压栈保护,叶子函数:没有调用其他函数的函数,压栈与退栈需要自己手动完成
(对于汇编来说)
二:
NOR FLASH 与NAND FLASH的区别:
NOR FLASH:
有三大总线,CPU可以直接访问,参加统一编址
NAND FLASH:
是一个串行FLASH,没有三大总结架构,CPU不能直接访问,独立编址。
三:
ARM有三种状态:
1,ARM态
2,Thumb态
3,Thumbee态四:
处理器的工作模式:(为了控制资源-通用寄存器)
1,User:非特权模式,大部分任务执行在这种模式下。
主要是为了保护内核,不能访问MMU 协处理器
2,FIQ:当一个高优级中断产生时将会进入这种模式
3,IROQ:当一个高优级中断产生时将会进入这种模式
异常与中断的区别:异常不可屏蔽,中断可屏蔽
异常的范围广,中断范围窄
4,Supervisor:当复位或软中断的时候将会进入这种模式
使用文件I/o引起了从用户态到内核态,从User模式到Supervisor模式的改变
复位的种类:
上电复位
人为复位
欠压/过压复位
看门狗复位(防止PC受到干扰)用fork()产生一个进程,定时支喂狗,如果主进程跑飞了,就不会去喂狗,到时候,就会复位。
5,Abort:当存取异常将会进入这种模式
异常:有预取指令异常与取数据异常
6,Undef:当执行未定义的指令时会进入这种模式
7,System:与User使用相同的寄存器集的特权模式
8,Monitor:(Cortex-a特有的模式)
五:
load/store架构:
1,只有该架构的才可以访问内存,其他的都是它的变种,
2,栈只能放在内存中,
3,私有寄存器越多,效率越高
4,数据搬移的三要素:目的,源与大小。
六:AMBA(Advanced microcontroller Bus architecture)
先进的微处理顺总线架构,是ARM公司基于ARM处理器设计的总线架构,在AMBA下延伸了两在总线 AHB(Advanced High Performance)与AP(Advancedperipheral bus) AHB用来连接高速设备APB用来连接低速设备,而这两者通过APB桥来联系。
七:
规则:ARM{x}{y}{z}{T}{D}{M}{I}{E}{J}{F}{-S}
x -- 处理器系列
y -- 存储管理/保护单元
z -- cache
T -- 支持Thumb指令集
D -- 支持片上调试
M -- 支持快速乘法器
I -- 支持Embedded ICE,支持嵌入式跟踪调试
E -- 支持增强型DSP指令
J -- 支持Jazelle
F -- 具备向量浮点单元VFP
-S -- 可综合版本
八:
1:
cmp r3,#0 subs r3,#0
beq skip beq skip
cmp可以影响条件位,sub不可以,必须加”S”来影响条件位。
异同点是cmp指令执行快,因为不需要回写寄存器。
2:ATPCS(ARM-THUMB procedure call standard)
子程序通过寄存器R0~R3来传递参数.超过四个要用堆栈来传。
并且要注意的是R0对应第一个参数,R1对应第二参数,依次类推。
if(a==0) fun(1)
cmp r1,#0
moveq r0,#1(由ATPCS规定)
bleq fun 这条指令受cmp指令结果的影响,当前指令是否执行取决于上一条影响标志位的指令的执行
结果。
if(a==4||a==10) x=0(短路特性)
cmp r0,#4
cmpne r0,#10
moveq r1,#0
九:
ARM的八种寻址方式:
1,立即数寻址:操作数本身就在指令中,取出指令也就取得了操作数。
注意点:没有任何一条指令可包括一个32bit的立即数,因为ARM指令是固定长度,不可能全都用来表示立即数,规定数据处理指令格式中,第二个操作数有12位。 用8位位图数来理解,高4位(0-15)X2用来表示移位数(0-30),记住一条准则:最后8位一定要移动偶数位。
立即数产生的方法:
第一种:就是移位操作(移位数不能超过5 bit无符号常数);
第二种就是mvn来进行反转例:mov r0,#0xffff ffff assembles mvn r0,#0
如果这两种方法都不能产生立即数,那么就是非法立即数,被称为32 bit常数,要装载它必须用到伪指令ldrr0,=0xff ldr r0,=0x5555 5555 这条伪指令在汇编的时候,可能被汇编成mov mvn 或 ldr指令,ldr指令从数据池中读取数据。
***所以把常数装载到寄存器中时一律使用该伪指令。
立即数寻址的特点:寻址方式最快,但是受立即数规范的影响。
2,寄存器寻址:利用寄存器的数值做为操作数。
特点:所有微处理器中都支持的一种;速度仅次于立即数寻址。
3,寄存器移位寻址:寄存器的数值相应移位得到操作数,移位的方式在指令中以助记符的形式给出,移位数可以是立即数或寄存器给出。
4,寄存器间接寻址:寄存器的值被做为操作数的地址,而操作数本身则放在存储器中。需要使用load/store架构
特点:访问的速度是相当慢的,有ldrsb ldrsh(s表示还符号)但是不影响标志位,没有strsb strsh指令。
5,基址变址寻址 :基址寄存器的值与指令中给出的偏移量的值的相加,得到一个有效的操作数的地址。
三种索引方式:
前索引: ldr r0,[r1,#4] 运行后r1的值不变(即基址寄存器的值没有变)
自动索引:ldr r0 ,[r1,#4]! !代表回基址。运行后r1的值改变。相当于C语言中的*(++P)
后索引: ldr r0 ,[r1],#4 运行后r1的值改变。相当于C语言中的*(P++);
6,多寄存器寻址:ldmxx xx可以是ia,ib,da,db
需要考虑的问题:
基址寄存的初始地址有没有被用
内存地址的方向变换
指令完成后基址寄存器指向的地址有没有被用
那个寄存器里的值最先被传入内存
stmia 与 ldmdb 是反操作这样可以恢复寄存器里的值。
7,相对寻址:已PC的当前值为基址,指令中的地址标号为偏移量,之和得到操作数的地址。
8,堆栈寻址:
ARM支持4种堆栈操作方式:(FD,FA,ED,EA),但是ATPCS规范规定使用FD,
入栈 stmfd sp!,{r0-r12}
出栈 ldmfd sp!,{r0-r12}
十:
SWP指令的优势(该指令必需有汇编来写,没有对应的C 语言,不能由ARMCC来编译必须用命汇编器)
1,存储器读写的原子性操作(完成一个字节或字的交换)
如果用load/store架构来实现的话,对于中断的到来,再返回 可能出错。
2,通常用于信号量操作
十一:
SWP:能完成从用户态到内核态,从USR到SVC模式
十二:
PSR (可以按位域来访问)
CPSR,CPSR,只能用MRS,MSR来访问
在用户模式下所有位均可以读,都是只胡条件标志位可以写
十三:
.s与.S的区别,在写的汇编语言时,如用引用C语言的头文件时,必须使用后者,其他两者无差别。
十四:
标号:
段内标号的地址值是在汇编的时候确定的。
段外标号的地址值是在连接的时候确定的。
局部标号:只能用0-99的数字表示。
F:只向前搜索
B:只向后搜索
十五:
异常返回 :
如果把SPSR_IQ直接组CPSR则从异常模式到的用户模式,我们就不能再对LR进行操作了(每种异常模式下都有私有寄存器LR), 如果顺序返过来也不可以,此时PC的值已经到了用户状态,就不可以再去操作spsr_iq了。 所以有了特殊的指令来现实,即指令后还“S”并用PC做为目的寄存器。在特权模式下不公更新PC,而且会拷贝SPSR到CPSR。
从SWI,UNDEF异常返回
MOVS PC,LR (之所以不用减去4,这是主动进入的,指令的完成代表中断)
从FIQ,IRQ,预取异常
SUBS PC,#4
从数据异常返回
SUBS PC,#8(不想丢掉指令本身)
如果LR之前被压栈的话作用(STMFD SP!,{LR})
LDMFD SP!,{PC}^
例:
irq_handler:
sub lr,lr,#4
stmfd sp!,{r0-r12,lr}
bl do_irq
ldmfd sp!,{r0-r12,pc}^ //^'s fucntion :spsr's value to cpsr
十六:
异常优先级:
注意点:异常是在当前指令执行完成以后才被响应的(这一点关系到pc返回值)
多个异常可以在同一时刻被响应,同一时刻仅限于同一时刻,在其他的时候,可以允许其他异常可以发生
,但是中断是可以被嵌套的(一般不用)。
异常顺序:
reset ,data abort ,fiq,irq,prefetchabort,swi,uddefine instruction
十七:
异常向量表放的指令
1,能放B,但是不能放BL,BL是为了保护能够返回,但是我们没有必要返回,异常向量的地方去,我们需要返回的
中断的地方。受+-32M的影响
2,能放MOV PC,#立即数 受非法立即数的影响
3,LDR PC,=标号或是立即数 [PC + OFFSET]OFFSET 的范围是+-4096K的影响
十八:
FIQ 与IRQ
为什么FIQ 比IRQ的处理速度快:
1,FIQ向量位于异常向量表的未位,不需要跳转指令,可以从异常向量处连续执行
2,FIQ模式下的私有寄存器比较多(5个R8-R12) 这样在处理数据的时候,压栈的个数就减少了,不需要忍受慢速设备。
十九:
SWi注意的问题:
在汇编中如果SWI调用时处于管理模式将会冲掉LR_svc 在调用之前对LR_svc压栈保护
二十:
变量类型
全局和静态变量保留在RAM中 需要使用loads/stores访问外部存储器 很慢
局部变量是通常放在寄存器中,用来快速且高效的处理如果编译器的寄存器分配算法认为超过现有的寄存器数量,将把变量压入栈中
对局部变量用WORD(INT)代替半字和字节 为了确保不受其他条件的的影响,可特别指定使用32-bit寄存器变量。
二十一:
volatile的用法:
推荐一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables 非自动变量有两种,一种是全局变量,一种是静态变量 )
3). 多线程应用中被几个任务共享的变量
嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所有这些都要求使用volatile变量。不懂得volatile内容将会带来灾难。
假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是真正懂得volatile完全的重要性。
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数被用来计算某个整数的平方,它能实现预期设计目标吗?如果不能,试回答存在什么问题:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中断服务子程序修改一个指向一个buffer的指针时。
3). 这段代码是个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能在两次取值语句之间发生改变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望
的平方值!正确的代码如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}
注意点:告诉compiler不能做任何优化
表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中
重复使用。
二十二:
起动代码的任务:
1,异常向量表的映射
2,各模式栈的分配
3,中断入口
4,时钟的初始化或者说是总线时钟的初始化。
下面是基于coitex-A8裸机的起动代码的
.equ GPG3CON, 0XE03001C0
.equ ELFIN_CLOCK_POWER_BASE, 0XE0100000
.equ APLL_LOCK_OFFSET, 0x00
.equ MPLL_LOCK_OFFSET, 0X04
.equ EPLL_LOCK_OFFSET, 0X08
.equ HPLL_LOCK_OFFSET, 0X0C
.equ CLK_DIV0_OFFSET, 0X300
.equ CLK_DIV0_MASK, 0X3FFF
.equ CLK_DIV0_VAL, ((1<<0)|(0<<4)|(3<<8)|(1<<12)|(1<<16))
.equ APLL_CON_OFFSET, 0X100
.equ CLK_DIV1_VAL, ((1<<16)|(1<<12)|(1<<8)|(1<<4))
.equ CLK_DIV1_OFFSET, 0x304
.equ APLL_VAL, (1<<31 | 445<<16 | 4<<8 | 0)
.equ MPLL_VAL, (1<<31 | 89<<16 | 2<<8 | 1)
.equ EPLL_VAL, (1<<31 | 90<<16 | 3<<8 | 3)
.equ HPLL_VAL, (1<<31 | 96<<16 | 6<<8 | 3)
.equ CLK_SRC0_OFFSET, 0x200
.equ GPG3DAT, 0XE03001C4
.equ MPLL_CON_OFFSET, 0X104
.equ EPLL_CON_OFFSET, 0X108
.equ HPLL_CON_OFFSET, 0X10c
.extern mmu_setmtt;
.text
.global _start
_start:
b reset
ldr pc,_undefined_instruction
ldr pc,_software_interrupt
ldr pc,_prefetch_abort
ldr pc,_data_abort
ldr pc,_not_used
ldr pc,_irq
ldr pc,_fiq_undefined_instruction: .word _undefined_instruction
_software_interrupt: .word _software_interrupt
_prefetch_abort: .word _prefetch_abort
_data_abort: .word _data_abort
_not_used: .word _not_used
_irq: .word irq_handler
_fiq: .word _fiq
reset:
ldr r0,=0x34000
mcr p15,0,r0,c12,c0,0 @ Holds the base address. Determines the location that the core
@ branches to 0x20100000, on an exception. The value is 0.
@ LSB 5 bit reservedmov r0, #0xfffffff
mcr p15, 0, r0, c1, c0, 2 @ Defines access permissions for each coprocessor
@ Privileged and User mode accessmov r0, #0x40000000
fmxr fpexc, r0 @ enable NEON and VFP coprocessor,NEON and VFP enable bit. Setting the EN bit to 1 enables the NEON and VFP coprocessor
// bl mmu_disable
mrs r0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0 @enable svc mode of cpuldr r0,=GPG3CON @init gpio for led
ldr r1,=0x1111
str r1,[r0]
/* disable watchdog */
ldr r0,=0xea200000
mov r1,#0
str r1,[r0]
/*
* Initialize core clock and bus clock.
*/ldr r0, =ELFIN_CLOCK_POWER_BASE /*0xe0100000*/
mov r1, #0xe10
str r1, [r0, #APLL_LOCK_OFFSET] @input clock frequency is 12MHz and masking time is 300us,
str r1, [r0, #MPLL_LOCK_OFFSET] @the value of PLL_MASKTIME will be 3600(=0xE10).
str r1, [r0, #EPLL_LOCK_OFFSET] @
str r1, [r0, #HPLL_LOCK_OFFSET] @ldr r1, [r0, #CLK_DIV0_OFFSET] @0XE0100000+ CLK_DIV0_OFFSET=(0X300)
ldr r2, =CLK_DIV0_MASK @CLK_DIV0_MASK=(0X3FFF)
bic r1, r1, r2 @clear low 14 bitldr r2, =CLK_DIV0_VAL @CLK_DIV0_VAL=((1<<0)|(0<<4)|(3<<8)|(1<<12)|(1<<16)), 0x11301
orr r1, r1, r2 @DOUT_APLL = MOUT_APLL / 2;
str r1, [r0, #CLK_DIV0_OFFSET] @ARMCLK = DOUTAPLL / 1
@HCLKD0 = DOUTARM / 4
@PCLKD0 = HCLKD0 / 2ldr r1, =APLL_VAL @APLL_VAL=(1<<31 | 0x1bd<<16 | 0x4<<8 | 0),0x81bd0400
str r1, [r0, #APLL_CON_OFFSET] @0XE0100000 + APLL_CON_OFFSET=0X100
@FOUTAPLL = 1335MHz
@The output frequency is calculated by the following equation:
@FOUT = MDIV * FIN / (PDIV * 2^(SDIV) )
@where, MDIV, PDIV, SDIV for APLL and MPLL must meet the following conditions :
@PDIV: 1 ≤ PDIV ≤ 63
@MDIV: 64 ≤ MDIV ≤ 1023
@SDIV: 0 ≤ SDIV ≤ 5
@Fref (=FIN / PDIV): 3MHz ≤ Fref ≤ 6MHz
@FVCO (=MDIV * FIN / PDIV): 1000MHz ≤ FVCO ≤ 2000MHz
@FOUT: 50MHz ≤ FVCO ≤ 2000MHzldr r1, [r0, #CLK_DIV1_OFFSET] @0XE0100000 + CLK_DIV1_OFFSET+0x304
ldr r2, =CLK_DIV1_VAL @CLK_DIV1_VAL=((1<<16)|(1<<12)|(1<<8)|(1<<4))=0x11110
orr r1, r1, r2
str r1, [r0, #CLK_DIV1_OFFSET] @DOUTAPLL2 = MOUTAPLL / 1
@DOUTMPLL = MOUTAMPLL / 2
@DOUTMPLL2 = MOUTAMPLL / 2
@DOUTD1_BUS= MOUTAMPLL / 2
@PCLK = DOUTD1_BUS / 2
ldr r1, =MPLL_VAL @MPLL_VAL=(1<<31 | 89<<16 | 2<<8 | 1)=0x80590201
str r1, [r0, #MPLL_CON_OFFSET] @0XE0100000 + MPLL_CON_OFFSET=0X104
@FOUTMPLL = 267MHZ
@The output frequency is calculated by the following equation:
@FOUT = MDIV * FIN / (PDIV * 2^(SDIV) )
@where, MDIV, PDIV, SDIV for PLLs must meet the following conditions:
@PDIV: 1 ≤ PDIV ≤ 63
@MDIV: 16 ≤ MDIV ≤ 255
@SDIV: 0 ≤ SDIV ≤ 5
@Fref (=FIN / PDIV): 2MHz ≤ Fref ≤ 6MHz
@FVCO (=MDIV * FIN / PDIV): 300MHz ≤ FVCO ≤ 600MHz
@FOUT : 10MHz ≤ FOUT ≤ 600MHzldr r1, =EPLL_VAL @EPLL_VAL=(1<<31 | 90<<16 | 3<<8 | 3)=0x805a0303
str r1, [r0, #EPLL_CON_OFFSET] @0XE0100000 + EPLL_CON_OFFSET=0X108
@FOUTEPLL = 45MHz
ldr r1, =HPLL_VAL @HPLL_VAL=(1<<31 | 96<<16 | 6<<8 | 3)=0x80600603
str r1, [r0, #HPLL_CON_OFFSET] @0XE0100000 + HPLL_CON_OFFSET+0X10c
@FOUTHPLL = 54MHz
ldr r1, [r0, #CLK_SRC0_OFFSET] @0XE0100000 + CLK_SRC0_OFFSET=0x200
ldr r2, =0x1111 @
orr r1, r1, r2
str r1, [r0, #CLK_SRC0_OFFSET] @1:FOUTAPLL MOUTAPLL =1335MHz
@1:FOUTMPLL MOUTMPLL =267MHZ
@1:FOUTEPLL MOUTEPLL =45MHz
@1:FOUTHPLL MOUTHPLL =54MHz
mov r1, #0x10000
1: subs r1, r1, #1
bne 1b
/************************create first-level table ******************/
/* ldr r0,=0x00000000
ldr r1,=0xfffff
ldr r2,=0x20100000
ldr r3,=0xc12
bl mmu_setmtt
ldr r0,=0x100000
ldr r1,=0xf0000000
ldr r2,=0x100000
ldr r3,=0xc12
bl mmu_setmtt*/
/**************set table base addr******************/
// ldr r0,=0x21000000
// mcr p15,0,r0,c2,c0,0
/********************disable Icache **************/
@ mrc p15,0,r0,c1,c0,0
@ bic r0,r0,#0x1000
@ mcr p15,0,r0,c1,c0,0/********************disable Dcache **************/
@ mrc p15,0,r0,c1,c0,0
@ bic r0,r0,#0x4
@ mcr p15,0,r0,c1,c0,0@ ldr r5, =0xffffffff @ define the access permissions for each one of the 16 domains
@ mcr p15, 0, r5, c3, c0, 0 @ Manager. Accesses are not check@ bl mmu_enable
init_stack:
ldr r0,stacktop /*get stack top pointer*/
/********svc mode stack********/
mov sp,r0
sub r0,#128*4 //512 byte for irq mode of stack
/****irq mode stack**/
msr cpsr,#0xd2
mov sp,r0
sub r0,#128*4 //512 byte for irq mode of stack
/***fiq mode stack***/
msr cpsr,#0xd1
mov sp,r0
sub r0,#0
/***abort mode stack***/
msr cpsr,#0xd7
mov sp,r0
sub r0,#0
/***undefine mode stack***/
msr cpsr,#0xdb
mov sp,r0
sub r0,#0
/*** sys mode and usr mode stack ***/
msr cpsr,#0x10
mov sp,r0 //1024 byte for user mode of stack
b main.align 4
irq_handler:sub lr,lr,#4
stmfd sp!,{r0-r12,lr}
bl do_irq
ldmfd sp!,{r0-r12,pc}^
/*
.global mmu_disable
mmu_disable:
mrc p15,0,r0,c1,c0,0
bic r0,r0,#1
mcr p15,0,r0,c1,c0,0
movs pc,lr.global mmu_enable
mmu_enable:
mrc p15,0,r0,c1,c0,0
orr r0,r0,#1
mcr p15,0,r0,c1,c0,0
mov pc,lr
*/
stacktop: .word stack+4*512
.datastack: .space 4*512
- ARM小结
- ARM寻址方式小结 [ARM]
- ARM寄存器小结
- ARM寄存器小结
- ARM 驱动一些小结
- ARM寄存器小结
- arm架构基础知识小结
- ARM寻址方式小结
- arm架构基础知识小结
- ARM芯片移植经验小结
- ARM CORTEX-3指令小结
- ARM体系结构(复习小结)
- arm中断(小结10)
- 嵌入式 arm指令小结一
- 嵌入式 arm指令小结二
- ARM Linux Oops使用小结
- ARM Linux Oops使用小结
- arm基础汇编指令小结
- Android requires compiler compliance level 5.0 or 6.0. Found '1.7' instead. Please use Android Tool
- 黑马程序员——Java基础语法(一)---关键字、常量、变量、运算符
- Ubuntu 12.04增加右键命令:在终端中打开
- C++ boost智能指针weak_ptr
- 读书三境界
- ARM小结
- EditText不自动获取焦点
- 设计模式简述
- CListCtrl
- 使用Javascript创建XML文件
- TP----android 4.2.2 TP 调试
- jQuery 自学笔记—1 前言
- DeDecms 标签运行php
- poj1077Eight