ARM体系结构与汇编

  • ARM体系结构

在ARM处理器中,除了用户模式是普通模式,剩下的几种工 作模式都属于特权模式。

应用程序如果要读写磁盘上的音频数据,驱 动声卡播放音乐,往屏幕写数据显示歌词,则要首先通过系统调用或软 中断进入处理器特权模式,运行操作系统内核或硬件驱动代码,才能对 底层的硬件设备进行读写操作

 

  • ARM处理器中的寄存器可分为通用寄存器和专用寄存器两种。
  • 寄存器R0~R12属于通用寄存器,除了FIQ工作模式,在其他工作模式下这些寄存器都是共用、共享的:

      R0~R3通常用来传递函数参数,

      R4~R11用来保存程序运算的中间结果或函数的局部变量等,

      R12常用来作为函数调用过程中的临时寄存器。

  • 有一些寄存器在各自的工作模式下是独立存在的,如R13、R14、R15、CPSP、SPSR寄存器,在每个工作模式下都有自己单独的寄存器。
  • R13寄存器又称为堆栈指针寄存器 (Stack Pointer,SP),用来维护和管理函数调用过程中的栈帧变化,R13总是指向当前正在运行的函数的栈帧,一般不能再用作其他用途。
  • R14寄存器又称为链接寄存器(Link Register,LR),在函数调用过程中主要用来保存上一级函数调用者的返回地址。
  • 寄存器R15又称为程序计数器(Program Counter,PC),CPU从内存取指令执行,就是默认从PC保存的地址中取的,每取一次指令,PC寄存器的地址值自动增加。
  • 在ARM三级流水线中,PC指针的值等于当前正在运行的指令地址+8,后续的32位处理器虽然流水线的级数不断增加,但为了简化编程,PC指针的值继续延续了这种计算方式。
  • 当前处理器状态寄存器(Current Processor State Register,CPSR)主要用来表征当前处理器的运行状态。除了各种状态位、标志位,CPSR寄存器里也有一些控制位,用来切换处理器的工作模式和中断使能控制。

 

 

  • 在每种工作模式下,都有一个单独的程序状态保存寄存器(Saved Processor State Register,SPSR)。当ARM处理器切换工作模式或发生异常时,SPSR用来保存当前工作模式下的处理器现场,即将CPSR寄存器的值保存到当前工作模式下的SPSR寄存器。当ARM处理器从异常返回时,就可以从SPSR寄存器中恢复原先的处理器状态,切换到原来的工作模式继续运行
  • 为了快速响应中断,减少中断现场保护带来的时间开销,在FIQ工作模式下,ARM处理器有自己独享的R8~R12寄存器。

 

 

 

 

 

 

  • ARM汇编指令

一个完整的ARM指令通常由操作码+操作数组成,指令的编码格式如下:

指令格式的具体说明如下:

  • 使用<>标起来的是必选项,使用{ }标起来的是可选项。
  • <opcode>是二进制机器指令的操作码助记符,如MOV、ADD这些汇编指令都是操作码的指令助记符。
  • cond:执行条件,ARM为减少分支跳转指令个数,允许类似BEQ、BNE等形式的组合指令。
  • S:是否影响CPSR寄存器中的标志位,如SUBS指令会影响CPSR寄存器中的N、Z、C、V标志位,而SUB指令不会。
  • Rd:目标寄存器。
  • Rn:第一个操作数的寄存器。
  • operand2:第二个可选操作数,灵活使用第二个操作数可以提高代码效率。

3.2.1 存储访问指令

  • ARM指令集属于RISC指令集,RISC处理器采用典型的加载/存储体系结构,CPU无法对内存里的数据直接操作,只能通过Load/Store指令来实现:当我们需要对内存中的数据进行操作时,要首先将这个数据从内存加载到寄存器,然后在寄存器中对数据进行处理,最后将结果重新存储到内存中。ARM处理器属于冯·诺依曼架构,程序和数据都存储在同一存储器上,内存空间和I/O空间统一编址,ARM处理器对程序指令、数据、I/O空间中外设寄存器的访问都要通过Load/Store指令来完成。ARM处理器中经常使用的Load/Store指令的使用方法如下。

  • LDM/STM指令常用来加载或存储一组寄存器到一片连续的内存,通过和堆栈格式符组合使用,LDM/STM指令还可以用来模拟堆栈操作。LDM/STM指令常和表3-2的堆栈格式组合使用。

 

  • 在一个堆栈内存结构中,如果堆栈指针SP总是指向栈顶元素,那么这个栈就是满栈;如果堆栈指针SP指向的是栈顶元素的下一个空闲的存储单元,那么这个栈就是空栈。

  • 每入栈一个元素,栈指针SP都会往栈增长的方向移动一个存储单元。

    如果栈指针SP从高地址往低地址移动,那么这个栈就是递减栈;

    如果栈指针SP从低地址往高地址移动,那么这个栈就是递增栈。

    ARM处理器使用的一般都是满递减堆栈。

     

  • 在将一组寄存器入栈,或者从栈中弹出一组寄存器时,我们可以使用下面的指令。

  

在上面的例子中,R0会先入栈,接着R1、R2入栈,最后R14入栈,入栈操作完成后,栈指针SP在内存中的位置如图3-4左侧所示。

栈元素在出栈操作时,顺序刚好相反,栈中的元素先弹出到R14寄存器中,接着是R2、R1、R0。将栈中的元素依次弹出到R14、R2寄存器后,堆栈指针在内存中的位置如图3-4右侧所示。

  • 栈的特点是先入后出(First In Last Out,FILO),栈元素在入栈操作时,STMFD会根据大括号{ }中寄存器列表

      中各个寄存器的顺序,从左往右依次压入堆栈。

  • ARM还专门提供了PUSH和POP指令来执行栈元素的入栈和出栈操作。

 

 

 

 

3.2.2 数据传送指令

  • LDR/STR指令用来在寄存器和内存之间输送数据。
  • 如果我们想要在寄存器之间传送数据,则可以使用MOV指令。

    MOV和MVN指令的一般使用方法如下。

  

  • {cond}为条件指令可选项。
  • {S}用来表示是否影响CPSR寄存器的值,如MOVS指令就会影响寄存器CPSR的值,而MOV则不会。
  • MVN指令用来将操作数operand2按位取反后传送到目标寄存器Rd。
  • 操作数operand2可以是一个立即数,也可以是一个寄存器。

3.2.3 算术逻辑运算指令

算术运算指令包括基本的加、减、乘、除,逻辑运算指令包括与、或、非、异或、清除等。指令格式如下。

算术逻辑运算指令的基本使用方法及说明如下。

3.2.4 操作数:operand2详解

很多ARM指令会使用第二个参数operand2:可以是一个常数,也可以是寄存器+偏移的形式。操作数operand2在汇编程序中经常出现的两种格式如下。

第一种格式操作数是一个立即数。

第二种格式可以直接使用寄存器的值作为操作数。通过{,shift}可选项,还可以通过多种移位或循环移位的方式,构建更加灵活的操作数。可选项{,shift}可以选择的移位方式如下。

可选性指令的使用示例及说明如下。

3.2.5 比较指令

比较指令用来比较两个数的大小,或比较两个数是否相等。

比较指令的运算结果会影响CPSR寄存器的N、Z、C、V标志位。

CPSR寄存器(Current Processor State Register, 当前处理器状态寄存器)——条件码标志位
  bit[31] N   N=1表示运算结果为负数,N=0表示结果为正数或零。
  bit[30] Z   Z=1运算的结果为零。Z=0运算的结果不为零。对于CMP指令,Z=1表示进行比较的两个数相等。
  bit[29] C   Carry/Borrow/Extend  
  bit[28] V   V=1表示符号为溢出

比较指令的格式如下。

比较指令的使用示例及说明如下。

比较指令的运行结果Z=1时,表示运算结果为零,两个数相等;

N=1表示运算结果为负,N=0表示运算结果为非负,即运算结果为正或者为零

 

 

3.2.6 条件执行指令

  • 为了提高代码密度,减少ARM指令的数量,几乎所有的ARM指令都可以根据CPSR寄存器中的标志位,通过指令组合实现条件执行。
  • 如无条件跳转指令B,我们可以在后面加上条件码组成BEQ、BNE组合指令。
  • BEQ指令表示两个数比较,结果相等时跳转;BNE指令则表示结果不相等时跳转。
  • CPSR寄存器中的标志位根据需要可以任意搭配成不同的条件码,和ARM指令一起组合使用。ARM指令的条件码如表3-3所示。

条件执行经常出现在跳转或循环的程序结构中。如下面的汇编程序,通过循环结构,我们可以实现数据块的搬运功能。

我们可以将无条件跳转指令B和条件码NE组合在一起使用,构成一个循环程序结构。

3.2.7 跳转指令

在函数调用的场合,以及循环结构、分支结构的程序中经常会用到跳转指令。

ARM指令集提供了B、BL、BX、BLX等跳转指令,每个指令都有各自的用武之地和使用场景。

跳转指令的格式如下。

B label

跳转到标号label处,B跳转指令的跳转范围大小为[0,32MB],可以往前跳,也可以往后跳。

无条件跳转指令B主要用在循环、分支结构的汇编程序中,使用示例如下。

 

BL label

  BL跳转指令表示带链接的跳转。

  在跳转之前,BL指令会先将当前指令的下一条指令地址(即返回地址)保存到 LR 寄存器中,然后跳转到 label 处执行。

  BL指令一般用在函数调用的场合,主函数在跳转到子函数执行之前,会先将返回地址,即当前跳转指令的下一条指令地址保存到LR寄存器中;

    子函数执行结束后,LR寄存器中的地址被赋值给PC,处理器就可以返回到原来的主函数中继续运行了。

 

BX Rm

BX表示带状态切换的跳转。

Rm寄存器中保存的是跳转地址,要跳转的目标地址处可能是ARM指令,也可能是Thumb指令。

处理器根据Rm[0]位决定是切换到ARM状态还是切换到Thumb状态。

  • 0:表示目标地址处是ARM指令,在跳转之前要先切换至ARM状态。
  • 1:表示目标地址处是Thumb指令,在跳转之前要先切换至Thumb状态。

BLX指令是BL指令和BX指令的综合,表示带链接和状态切换的跳转,使用方法和上面相同

 

 

 

 

 

 

 

 

 

  • ARM寻址方式

  • ARM伪指令

  • ARM汇编程序设计

  • C语言和汇编语言混合编程

  • GNU ARM汇编语言

posted @   眉间  阅读(285)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示