ARM工作模式和汇编

摘自 朱有鹏嵌入式

1.ARM 有7个基本工作模式:

各种模式的切换,可以是程序员通过代码主动切换(通过写CPSR寄存器),也可以是CPU在某些情况下自动切换。

各种模式下权限和可以访问的寄存器不同

操作系统有安全级别要求,因此CPU设计多种模式是为了方便操作系统的多种角色安全等级需要。

  • User : 非特权模式,大部分任务执行在这种模式
  • FIQ : 当一个高优先级(fast) 中断产生时将会进入这种模式
  • IRQ : 当一个低优先级(normal) 中断产生时将会进入这种模式
  • Supervisor :当复位或软中断指令执行时将会进入这种模式
  • Abort : 当存取异常时将会进入这种模式
  • Undef : 当执行未定义指令时会进入这种模式
  • System : 使用和User模式相同寄存器集的特权模式

2.ARM的37个寄存器

ARM是IO与内存统一编址的,

  • ARM总共有37个寄存器,都是32位长度,37个寄存器中30个为“通用”型,1个固定用作PC,一个固定用作CPSR,5个固定用作5种异常模式下的SPSR。但是每种模式下最多只能看到18个寄存器,其他寄存器虽然名字相同但是在当前模式不可见。

  • 对r13这个名字来说,在ARM中共有6个名叫r13(又叫sp)的寄存器,但是在每种特定处理器模式下,只有一个r13是当前可见的,其他的r13必须切换到它对应的模式下才能看到。这种设计叫影子寄存器(banked register)。
    在这里插入图片描述

  • CPSR程序状态寄存器

在这里插入图片描述

  • CPSR中各个bit位表明了CPU的某些状态信息,这些信息非常重要,和后面学到的汇编指令息息相关(譬如BLE指令中的E就和CPSR中的Z标志位有关)

  • CPSR中的I、F位和开中断、关中断有关

  • CPSR中的mode位(bit4~bit0共5位)决定了CPU的工作模式,在uboot代码中会使用汇编进行设置。

  • SPSR是用来保存CPSR的

  • PC(r15)程序控制寄存器

    • PC(Program control register)为程序指针,PC指向哪里,CPU就会执行哪条指令(所以程序跳转时就是把目标地址代码放到PC中)
    • 整个CPU中只有一个PC(CPSR也只有一个,但SPSR有5个)

3. ARM异常处理方式

正常工作之外的流程都叫异常,异常会打断正在执行的工作,并且一般我们希望异常处理完成后继续回来执行原来的工作。中断是异常的一种

发生异常后CPU会进入相应的工作模式,与异常相关的工作模式有5种

异常处理中有一些是硬件自动做的,有一些是程序员需要自己做的。

CPU设计时提供的异常向量表,一般称为一级向量表。有些CPU为了支持多个中断,还会提供二级中断向量表

  • 异常向量表

    • 所有的CPU都有异常向量表,这是CPU设计时就设定好的,是硬件决定的。
    • 当异常发生时,CPU会自动动作(PC跳转到异常向量处处理异常,有时伴有一些辅助动作)
    • 异常向量表是硬件向软件提供的处理异常的支持。
  • 异常处理机制(这些操作只能在 ARM 态执行)

    • 当异常产生时, ARM core:
      • 拷贝 CPSR 到 SPSR_
      • 设置适当的 CPSR 位:
        • 改变处理器状态进入 ARM 态(Thumb态下没法进行异常处理)
        • 改变处理器模式进入相应的异常模式
        • 设置中断禁止位禁止相应中断 (如果需要)
      • 保存返回地址到 LR_
      • 设置 PC 为相应的异常向量
    • 返回时, 异常处理需要:
      • 从 SPSR_恢复CPSR_
      • 从LR恢复PC

在这里插入图片描述

4.汇编语言

4.1 指令与伪指令

(汇编)指令是CPU机器指令的助记符,经过编译后会得到一串10组成的机器码,可以由CPU读取执行。

(汇编)伪指令本质上不是指令(只是和指令一起写在代码中),它是编译器环境提供的,目的是用来指导编译过程,经过编译后伪指令最终不会生成机器码。

  • gnu汇编中的符号

    • @ 用来做注释。可以在行首也可以在代码后面同一行直接跟,和C语言中//类似
    • #做注释,一般放在行首,表示这一行都是注释而不是代码。
    • :以冒号结尾的是标号
    • . 点号在gnu汇编中表示当前指令的地址
    • 立即数前面要加#或$,表示这是个立即数
  • 常用伪指令

    • .global _start @ 给_start外部链接属性
    • .section .text @ 指定当前段为代码段
    • .ascii .byte .short .long .word @定义变量类型
    • .quad .float .string @ 定义数据
    • .align 4 @ 以16字节对齐, 2^4
    • .balignl 16 0xabcdefgh @16字节对齐填充 b表示位填充;align表示对齐,l表示long,以4字节为单位填充;16表示16字节对齐;0xabcdefgh为填充材料
    • .equ @ 类似于C中宏定义
  • 偶尔会用到的gnu伪指令

    • .end @标识文件结束
    • .include @ 头文件包含
    • .arm / .code32 @声明以下为arm指令
    • .thumb / .code16 @声明以下为thumb指令
  • 最重要的伪指令

    ARM中有一个ldr指令,还有一个ldr伪指令。一般都使用ldr伪指令而不用ldr指令

    • ldr 大范围的地址加载指令

    • adr 小范围的地址加载指令

      adr编译时会被1条sub或add指令替代,而ldr编译时会被一条mov指令替代或者文字池方式处理;

      adr总是以PC为基准来表示地址,因此指令本身和运行地址有关,可以用来检测程序当前的运行地址在哪里

      ldr加载的地址和链接时给定的地址有关,由链接脚本决定。

    • adrl 中等范围的地址加载指令

    • nop 空操作

4.2 汇编特点

  • LDR/STR架构
    ARM采用RISC架构,CPU本身不能直接读取内存,而需要先将内存中内容加载入CPU中通用寄存器中才能被CPU处理。
    • ldr(load register)指令将内存内容加载入通用寄存器。ldr reg memeory
    • str(store register)指令将寄存器内容存入内存空间中。str reg memory
    • ldr/str组合用来实现 ARM CPU和内存数据交换

4.3 8种寻址方式

  • 寄存器寻址 mov r1, r2
  • 立即寻址 mov r0, #0xFF00
  • 寄存器移位寻址 mov r0, r1, lsl #3
  • 寄存器间接寻址 ldr r1, [r2] //将r2中的内存地址处的值赋值给r1
  • 基址变址寻址 ldr r1, [r2, #4] //将r2中的内存地址+4处的值赋值给r1
  • 多寄存器寻址 ldmia r1!, {r2-r7, r12} //以r1存储的内存地址为起始地址,依次将地址后面的八个值赋值给r2-r7和r12共7个寄存器
  • 堆栈寻址 stmfd sp!, {r2-r7, lr} //堆栈操作
  • 相对寻址 beq flag //

4.4 指令后缀
同一指令经常附带不同后缀,变成不同的指令。经常使用的后缀有:

  • B(byte)功能不变,操作长度变为8位
  • H(half word)功能不变,长度变为16位
  • S(signed)功能不变,操作数变为有符号。如 ldr ldrb ldrh ldrsb ldrsh
  • S(S标志)功能不变,影响CPSR标志位。如 mov和movs movs r0, #0

4.5 条件执行后缀
在这里插入图片描述

  • 条件后缀是否成立,不是取决于本句代码,而是取决于这句代码之前的代码运行后的结果。
  • 条件后缀决定了本句代码是否被执行,而不会影响上一句和下一句代码是否被执行。

4.6 多级指令流水线
为增加处理器指令流的速度,ARM使用多级流水线.,允许多个操作同时处理,而非顺序执行。PC指向正被取指的指令,而非正在执行的指令
在这里插入图片描述
4.7 常用指令

  • 数据处理指令

  • 数据传输指令 mov mvn

  • 算术指令 add sub rsb adc sbc rsc

  • 逻辑指令 and orr eor bic

  • 比较指令 cmp cmn tst teq

  • 乘法指令 mvl mla umull umlal smull smlal

  • 前导零计数 clz

  • cpsr访问指令 mrs & msr
    CPSR寄存器比较特殊,需要专门的指令访问,mrs用来读psr,msr用来写psr

  • 跳转(分支)指令 b & bl & bx

    • b 直接跳转(就没打开算返回)
    • bl branch and link,跳转前把返回地址放入lr中,以便返回;用于函数调用
    • bx跳转同时切换到ARM模式,一般用于异常处理的跳转。
  • 访存指令 ldr/str & ldm/stm & swp

    • 单个字/半字/字节访问 ldr/str
    • 多字批量访问 ldm/stm
    • swp r1, r2, [r0]
    • swp r1, r1, [r0]
  • 软中断指令 swi(software interrupt)

    软中断指令用来实现操作系统中系统调用

  • 协处理器cp15操作指令 mcr & mrc

    协处理器:SoC内部另一处理核心,协助主CPU实现某些功能,被主CPU调用执行一定任务。ARM设计上支持多达16个协处理器,但是一般SoC只实现其中的CP15(cp:coprocessor)。协处理器和MMU、cache、TLB等处理有关,功能上和操作系统的虚拟地址映射、cache管理等有关。

    • mrc用于读取CP15中的寄存器

    • mcr用于写入CP15中的寄存器

    • 使用方法

      mcr{<cond>}   p15, <opcode_1>, <Rd>, <Crn>, <Crm>, {<opcode_2>}
      opcode_1:对于cp15永远为0
      Rd:ARM的普通寄存器
      Crn:cp15的寄存器,合法值是c0~c15
      Crm:cp15的寄存器,一般均设为c0
      opcode_2 :一般省略或为0
      
      举例
      mrc p15, 0, r0, c1, c0, 0
      orr	r0, r0, #1
      mcr p15, 0, r0, c1, c0, 0
      
  • 多寄存器访问指令

    ldr/str每周期只能访问4字节内存,如果需要批量读取、写入内存时太慢,解决方案是stm(store register mutiple)/ldm(load register mutiple)

    <LDM>{<cond>}<addressing_mode> Rb{!}, <寄存器 list>        //内存块  ==》寄存器列表
    <STM>{<cond>}<addressing_mode> Rb{!}, <寄存器 list>        //寄存器列表 ==》内存块
    
    stmia	sp, {r0 - r12}
    //将r0存入sp指向的内存处(假设为0x30001000);然后地址+4(即指向0x30001004),将r1存入该地址;然后地	址再+4(指向0x30001008),将r2存入该地址······直到r12内容放入(0x3001030),指令完成。一个访存周期同时完成13个寄存器的读写
    
    • 8种后缀

      • ia(increase after)先传输,再地址+4
      • ib(increase before)先地址+4,再传输
      • da(decrease after)先传输,再地址-4
      • db(decrease before)先地址-4,再传输
      • fd(full decrease)满递减堆栈
      • ed(empty decrease)空递减堆栈
      • fa(·······) 满递增堆栈
      • ea(·······)空递增堆栈
    • 4种栈

      • 空栈:栈指针指向空位,每次存入时可以直接存入然后栈指针移动一格;而取出时需要先移动一格才能取出
      • 满栈:栈指针指向栈中最后一格数据,每次存入时需要先移动栈指针一格再存入;取出时可以直接取出,然后再移动栈指针
      • 增栈:栈指针移动时向地址增加的方向移动的栈
      • 减栈:栈指针移动时向地址减小的方向移动的栈
    • !的作用

      ldmia	r0, {r2 - r3}
      ldmia	r0!, {r2 - r3}    
      

      感叹号的作用就是r0的值在ldm过程中发生的增加或者减少最后写回到r0去,也就是说ldm时会改变r0的值。

    • ^ 的作用

      ldmfd	sp!, {r0 - r6, pc}
      ldmfd	sp!, {r0 - r6, pc}^
      

      ^的作用:在目标寄存器中有pc时,会同时将spsr写入到cpsr,一般用于从异常模式返回。

5. ARM汇编中的立即数

  • ARM指令都是32位,除了指令标记和操作标记外,本身只能附带很少位数的立即数。因此立即数有合法和非法之分。
  • 合法立即数:经过任意位数的移位后非零部分可以用8位表示的即为合法立即数
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值