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,prefetch

abort,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 reserved

     mov r0, #0xfffffff 
       mcr p15, 0, r0, c1, c0, 2   @ Defines access permissions for each coprocessor
         @ Privileged and User mode access

     mov 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 cpu

  ldr  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 bit

 ldr 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 / 2

 ldr 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 ≤ 2000MHz

 ldr    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 ≤ 600MHz

 ldr 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
.data  

stack:  .space  4*512


 

原创粉丝点击