ARM System Developer's Guide 学习笔

作者: kekeMemory | 来源:发表于2020-04-16 23:32 被阅读0次

访存指令

访存指令用于数据在存储器和处理器寄存器之间传递。有三种访存指令:单寄存器传输指令、多寄存器传输指令,交换指令。

1. 单寄存器传输指令

  • 概念:这些指令用于将单数据移入和移出寄存器。数据类型支持有符号和无符号字长(32-bits),半字长(16-bits)和字节。
  • 常用的单寄存器传输指令 及其 语法
常用的单寄存器传输指令 及其 语法

其中
addressing1(数据类型是word, unsigned byte)可用桶形移位器-比例因子是2的倍数;
addressing2(数据类型是半字,有符号半字,有符号字节,以及双字)。

  • LDR,STR 指令
    LDR只在存储器加载32-bit字长地址,4字节的倍数-0,4,8...。

示例1.1

以下示例为从寄存器r1中包含的内存地址进行加载,然后将存储返回到存储器中的相同地址。

寄存器r1:
第一条指令:加载寄存器r1指向的内存地址的内容到寄存器r0。

目标寄存器r0:
第二条指令:存储寄存器r0的内容到寄存器r1指向的内存地址。

r1 的偏移为0,寄存器r1为基地址寄存器。

LDR,STR 指令示例

单寄存器寻址模式

ARM指令集提供了不同的寻址模式。这些模式结合了索引方法:带写回的预索引,预索引和后索引。
索引方法如下表所示:


索引方法( ! 表示写回到基址寄存器)

示例1.2:

寻址前
  • 带写回的预索引
    通过基寄存器地址加上地址偏移的计算,然后更新基寄存器地址为新地址。该模式用于遍历数组。

解析
基寄存器r1:
r1地址和偏移量相加,新地址为:mem32[0x00009000+0x00000004] -- mem32[0x00009004],基寄存器r1地址更新为这个新地址:即 r1 = 0x00009004;

目标寄存器r0:
加载更新后的寄存器r1指向的内存地址的内容到r1。
mem32[0x00009004] = 0x02020202, r1现在地址存储的内容是 0x02020202,即r0 = 0x02020202

preindex with writeback
  • 预索引
    与上面相反,索引偏移和带写回的预索引一样但是不更新基寄存器地址。该模式用于在访问数据结构中的元素时间。
    解析
    基寄存器r1:
    r1地址和偏移量相加,新地址为:mem32[0x00009000+0x00000004] -- mem32[0x00009004],基寄存器r1地址地址不更新,不变,即 r1 = 0x00009000

    目标寄存器r0:
    r1的地址不变,但是由于偏移后的地址为0x00009004,mem32[0x00009004] = 0x02020202, 即r0 = 0x02020202

preindexing
  • 后索引
    当地址被用了以后只是更新基寄存器地址。该模式用于遍历数组。
    解析
    基寄存器r1:
    r1地址和偏移量相加,新地址为:mem32[0x00009000+0x00000004] -- mem32[0x00009004],因为地址被用了,所以只更新基寄存器r1地址更新为这个新地址:即 r1 = 0x00009004;

    目标寄存器r0:
    在这个模式下,目标寄存器加载源地址指向的内容。mem32[0x00009000] = 0x01010101, 即 r0 = 0x01010101。

postindexing
  • 小结:
    示例1.2 使用了preindex方法,展现了每一个索引方法是如何影响 寄存器 r1 地址的,以及加载到 寄存器 r0 中的数据内容。每一个指令展现了在同一个先决条件的索引方法结果。

  • 总结1:
    下表为LDR 指令的不同变化:


    不同寻址模式的LDR指令集
  • 总结2:
    下表为使用16-bits半字长或有符号字节数据访存时可用的寻址方式:

2. 多寄存器传输指令

  • 概念:多寄存器传输指令在一个指令下,可以在内存和寄存器中传递多个寄存器。传输从指向存储器的基地址寄存器Rn开始;多寄存器传输指令可提高效率,例如:数据块的操作,上下文切换,堆栈操作;
    多寄存器传输指令会增加中断延时(不会打断正在执行的指令)。ARM不支持经常中断当执行的时候。
    编译器比如armcc提供了switch指令可以控制一条load-store指令最大寄存器数目,限制了最大中断延迟。
  • 常用的多寄存器传输指令 及其 语法
多寄存器传输指令 及其 语法

下表为多寄存器传输指令的不同寻址模式,N 为寄存器个数。
基地址寄存器Rn决定了多寄存器传输指令的源地址和目标地址。通过下面的转换,寄存器可以自动更新。

多寄存器传输指令的不同寻址模式
  • IA 执行后增加

  • IB 执行前增加

  • DA 执行后减少

  • DB 执行前减少
    更新基地址的load-store指令对,用于类似成对的push pop操作,
    STMIA - LDMDB
    STMIB - LDMDA
    STMDA - LDMIB
    STMDB - LDMIA

  • LDMIA 指令示例:
    下例中,寄存器r0是基寄存器Rn阶乘,表示指令执行后更新寄存器。可以注意到,在多寄存器传输指令中寄存器没有单独列出,而是用符号 " - " 代表一段寄存器范围。在这个例子中,寄存器范围是从寄存器r1 到 r3。
    每一个寄存器可以列出,用圆括号 { 和 } 来分开每一个寄存器。


指令执行前

在先决条件下,基址寄存器r0指向的内存地址为 0x80010 ,内存地址0x80010,0x80014和0x80018上相应存储的值是0x01,0x02 和 0x03.

下图为图形表示:


LDMIA 指令 Per-condition 图形表示

多寄存器传输指令LDMIA执行后,寄存器r1, r2 和 r3 包含的值如下图所示:
基寄存器r0 在上个字长加载以后,现在指向内存地址 0x8001c。

LDMIA 指令 Post-condition 图形表示 指令执行后
  • LDMIB指令示例

使用和上面相同的LDMIA 指令 中的Per-condition,寄存器r0指向的第一个字长忽略,寄存器r1从下一个内存地址加载,如下图所示:

LDMIB 指令 Post-condition 图形表示

多寄存器传输LDMIB指令执行后,寄存器r0 现在指向最后一次被加载后的内存地址 0x8001c,和LDMIA指向下一个内存地址相反

LDMDALDMDB 指令从起始地址减少并存储到上升的内存地址。

使用增加和减少的多寄存器传输指令,可以前向和后向访问数组,允许堆栈的push和pull操作。

堆栈操作

ARM结构用多存储器传输指令执行堆栈操作。
pop : 从堆栈中移除数据
push: 数据放入堆栈
在使用堆栈时要决定是 ascending(A)还是 descending(D): 升序是堆栈朝着高地址增长,降序是朝着低地址增长。
堆栈3个属性,堆栈基址、堆栈指针(sp)、堆栈限制;
当使用full stack(F),sp指向最后一个地址或满地址;
当使用empty stack(E),sp指向第一个或空的地址。
ARM-Thumb过程调用标准(ATPCS)定义了例程如何被调用和寄存器如何分配;
ATPCS定义堆栈为递减式满堆栈(Descending-Full stack);
堆栈检查enable时,ATPCS定义r10为堆栈限制或sl(stack limit); 备注:push堆栈溢出错误,pop堆栈下溢(stack underflow)错误。
下表为支持堆栈操作的可用寻址方式:


支持堆栈操作的可用寻址方式

3. 交换指令

  • 概念:交换指令是一个特殊的访存指令。它交换内存个寄存器的内容。是原子操作,会占据总线,直至交换完成。
  • 常用的交换指令 及其 语法:


    交换指令 及其 语法

交换不能被其他指令或总线访问中断,这是系统占用总线直到完成。

  • 示例:Swap指令从内存加载一个字长到寄存器r0,然后用寄存器r1覆写内存。


    Swap指令示例

这个指令在一个操作系统中当生成信号量semaphore和互斥时特别有用。

相关文章

网友评论

    本文标题:ARM System Developer's Guide 学习笔

    本文链接:https://www.haomeiwen.com/subject/gqydvhtx.html