ARM的指令系统中关于栈指令的内容比较容易引起迷惑,这是因为准确描述一个栈的特点需要两个参数:

  • 栈地址的增长方向:ARM将向高地址增长的栈称为递增栈(Descendent Stack),将向低地址增长的栈称为递减栈(Acendant Stack)
  • 栈指针的指向位置:ARM将栈指针指向栈顶元素位置的栈称为满栈(Full Stack),讲栈指针指向即将入栈的元素位置的栈称为空栈(Empty Stack)

1. 栈类型

根据栈地址增长方向雨栈指针指向位置的不同,自然可以将栈分为四类:

  递增栈 递减栈
空栈 EA栈 ED栈
满栈 FA栈 FD栈

图1描述了四种不同类型的栈,其中虚线部分表示即将入栈的元素。

图1 栈类型

2. 栈指令

栈的操作指令无非两种:入栈和出栈,由于ARM描述了四种不同类型的栈,因此对应的栈指令一共有8条。

  入栈 出栈
EA栈 STMEA LDMEA
ED栈 STMED LDMED
FA栈 STMFA LDMFA
FD栈 STMFD LDMFD

这些指令具有相似的前缀:

  • STM:(STore Multiple data)表示存储数据,即入栈
  • LDM:(LoaD Multiple data)表示加载数据,即出栈

一般情况下,可以将栈操作指令分解为两步微指令:数据存取和栈指针移动。这两步操作的先后顺序和栈指针的移动方式由栈的类型决定。

  第一步 第二步 等价指令
STMEA 写[SP] SP增加 STMIA
LDMEA SP减少 读[SP] LDMDB
STMED 写[SP] SP减少 STMDA
LDMED SP增加 读[SP] LDMIB
STMFA SP增加 写[SP] STMIB
LDMFA 读[SP] SP减少 LDMDA
STMFD SP减少 写[SP] STMDB
LDMFD 读[SP] SP增加 LDMIA

ARM中存在一组缓冲区操作指令和栈指令是一一对应的,他们完成相同的功能。这些指令含义的区别来源于对存取操作的缓冲区指针地址增长方向,以及存取操作和缓冲区指针移动的先后顺序决定的。这个和前面描述的栈类型的分类原则十分相似。

  指针递增(Increase) 指针递减(Decrease)
存取前移动指针(Before) IB DB
存取后移动指针(After) IA DA

3. 使用举例

虽然ARM的栈类型和相关的操作指令比较繁琐,但是实际上最常用的还是和x86指令集相同的栈类型:栈向低地址方向增长,且栈指针指向栈顶元素的位置,即ARM的FD栈。因此最常见的ARM栈指令操作是STMFD和LDMFD。

  x86 ARM
入栈 PUSH STMFD/STMDB
出栈 POP LDMFD/LDMIA

例如入栈指令:

STMFD SP,{R0-R3}

实际的微指令操作为:

[SP-4]  <=  R3
[SP-8] <= R2
[SP-12] <= R1
[SP-16] <= R0

在ARM的指令系统中,递减栈入栈操作的参数入栈顺序是从右到左依次入栈,而参数的出栈顺序则是从左到右的逆操作。对于递增栈,相应的操作则全部取反。 例如出栈指令:

LDMFD SP,{R4-R7}

实际的微指令操作为:

[SP]    =>  R4
[SP+4] => R5
[SP+8] => R6
[SP+12] => R7

上述的入栈和出栈指令其实仅仅对栈做了存取操作,并未真正改变SP指针的值。正常情况下,我们希望对栈操作后能自动修改栈指针SP的值,使用如下指令可以达到该目的。

STMFD SP!,{R0-R3}

对应的微指令操作为:

[SP-4]  <=  R3
[SP-8] <= R2
[SP-12] <= R1
[SP-16] <= R0
SP = SP - 16

同样的:

LDMFD SP!,{R4-R7}

对应的微指令操作为:

[SP]    =>  R4
[SP+4] => R5
[SP+8] => R6
[SP+12] => R7
SP = SP + 16

希望通过本文对你理解ARM的栈指令有所帮助。

原文地址: http://www.cnblogs.com/fanzhidongyzby/p/5250116.html

ARM的栈指令(转)的更多相关文章

  1. ARM的栈指令

    ARM的指令系统中关于栈指令的内容比较容易引起迷惑,这是因为准确描述一个栈的特点需要两个参数: 栈地址的增长方向:ARM将向高地址增长的栈称为递增栈(Descendent Stack),将向低地址增长 ...

  2. ARM指令集—SWP指令

    ARM指令集-SWP指令 SWP和SWPB是ARM指令集中对存储单元的原子操作.即对存储单元的一次读和一次不可被切割. SWP和SWPB分别完毕存储器和寄存器之间 一个字(32bit)和一个字节(8b ...

  3. (二十三)ARM平台NEON指令的编译和优化

    ARM平台NEON指令的编译和优化 本文介绍了ARM平台基于ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7,Cortex-A8, Cortex-A9 ...

  4. JVM 字节码之 int 入栈指令

    本文转载自JVM 字节码之 int 入栈指令(iconst.bipush.sipush.ldc) 前言 本文介绍 int 入栈指令 iconst.bipush.sipubh.Idc. 当 int 取值 ...

  5. ARM汇编基础指令

    Cortex-A7 常用汇编指令 一.处理器内部数据传输指令 1.mov 将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄存器里面 MOV R0,R1 @将寄存器 R1 中的数据传递给 ...

  6. ARM 异常处理过程,指令[ swi ]

    1.  发生异常: 程序正常执行,突然被一个不正常的事件打断正在执行的程序,执行相应的异常事件对应的程序 2.  5 种异常模式对应着 7 种异常源:   异常工作模式      异常源 FIR   ...

  7. JVM字节码之整型入栈指令(iconst、bipush、sipush、ldc)

    官网:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html 原文地址:http://www.linmuxi.com/2016/02 ...

  8. ARM指令集----杂项指令

    ARM指令集可以分为6类,即是跳转指令,数据处理指令,程序状态传输指令,Load.Store指令,协处理器指令和异常中断指令 跳转指令: 在ARM中有两种方式可以实现程序的跳转,一种是跳转指令,另一种 ...

  9. ARM指令集——数据处理指令

    ARM汇编指令集 ARM汇编文件的组成 指令:编译完成后作为一条指令(机器码)存储在内存单元中,CPU执行时能够完成处理的操作 伪指令:在编译时替换成能被识别的ARM指令 伪操作:知道编译器进行编译, ...

随机推荐

  1. iOS 正则表达式(一)

    在iOS开发中,正则一直是最常用的,但也是一直记不住的,现在做一些简单的总结 我们在网上找的正则,要有'\',这个在iOS是转义符,需要'\\'这样 int main(int argc, const ...

  2. ####### Scripts Summary #######

    Scripts Summary Version: 1.0.1 issueDate: 2017-11-11 modifiedDate: 2017-11-28 0.configuration 1.oper ...

  3. obv15 案例4,待日后分析

    obv

  4. Mysql8.0.11安装以及注意事项

    一.环境配置 首先在官网下载最新的mysql8.0.11数据库,解压到你需要放置的盘符最好不要有中文,然后新建MYSQL_HOME,参数为mysql解压后安装文件的bin文件路径如我的:变量名:MYS ...

  5. spark-shell下有提示了,但是发现不能退格

    配好了Spark集群后,先用pyspark写了两个小例子,但是发现Tab键没有提示,于是打算转到scala上试试,在spark-shell下有提示了,但是发现不能退格,而且提示也不是复写,而是追加,这 ...

  6. <4>Cocos Creator基本概念(场景树 节点 坐标 组件 )

    1.场景树 Cocos Creator是由一个一个的游戏场景组成,场景是一个树形结构,场景由 有各种层级关系的节点(下一节有具有介绍)组成: 如创建一个HelloWorld的默认项目NewProjec ...

  7. 2.sklearn库中的标准数据集与基本功能

    sklearn库中的标准数据集与基本功能 下面我们详细介绍几个有代表性的数据集: 当然同学们也可以用sklearn机器学习函数来挖掘这些数据,看看可不可以捕捉到一些有趣的想象或者是发现: 波士顿房价数 ...

  8. python 简单了解namedtuple

    namedtuple类位于collections模块,有了namedtuple后通过属性访问数据能够让我们的代码更加的直观更好维护 namedtuple能够用来创建类似于元祖的数据类型,除了能够用索引 ...

  9. python os.path.basename()方法

    返回path最后的文件名.如果path以/或\结尾,那么就会返回空值.即os.path.split(path)的第二个元素. >>> import os >>> p ...

  10. flask 使用Flask-SQLAlchemy管理数据库(连接数据库服务器、定义数据库模型、创建库和表)

    使用Flask-SQLAlchemy管理数据库 扩展Flask-SQLAlchemy集成了SQLAlchemy,它简化了连接数据库服务器.管理数据库操作会话等各种工作,让Flask中的数据处理体验变得 ...