当前位置: 首页 > news >正文

ARM 汇编寻址方式

ARM支持9种寻址方式:立即数寻址,寄存器寻址,寄存器偏移寻址,寄存器间接寻址,基址变址寻址,多寄存器寻址,相对寻址,堆栈寻址,块拷贝寻址。

立即数寻址

将数据直接存放的指令中发给CPU,首先由于ARM的一条指令占了32bit,而操作码本身也要占据一些位,所以留给立即数的位数肯定不到32bit,其次并不是满足指定位数的数字都是立即数,ARM中的立即数必须可以通过某个8bit的数据经过循环右移得到

MOV R0,#255     ;R0 <- #255,#0~#255都是立即数
ADD R0, R0, #1  ;R0 <- (R0+#1)

寄存器直接寻址

将寄存器中的数据用作操作数

MOV R0, R1          ;R0 <- R1
ADD R0,R1, R2     ;R0 <- (R1 + R2)

寄存器间接寻址

将寄存器中的数据作为主存中操作数的地址,去到相应的主存地址取得操作数,用[R0]表示将R0中的数据当作操作数的地址...,[R0]!表示将R0中的数据当作操作数的地址并将操作后的结果地址给R0

LDR R0,[R1]        ;将R1指向的数据加载到R0中 
STR R0, [R1]!        ;将R0存储的数据加载到R1指向的主存地址中,加载完毕R1中为操作后的地址
ADD R0,R1,[R2]

寄存器偏移寻址

现将寄存器的值进行移位,再将移位后的数据当作操作数

MOV R0,R2,LSL  #1   ;R2的值左移1位,结果赋给R0。
MOV R0,R2,LSL  R1 ;R2的值左移R1位,结果放入R0。

有6种移位操作:

LSL:逻辑左移(Logical Shift Left),寄存器中字的低端空出的位补0。
LSR:逻辑右移(Logical Shift Right),寄存器中字的高端空出的位补0。
ASL:算术左移(Arithmetic Shift Left),和逻辑左移LSL相同。
ASR:算术右移(Arithmetic Shift Right),移位过程中符号位不变,即如果源操作数是正数,则字的高端空出的位补0,否则补1。
ROR:循环右移(Rotate Right),由字的低端移出的位填入字的高端空出的位。
RRX:带扩展的循环右移(Rotate Right eXtended),操作数右移一位,高端空出的位用进位标志C的值来填充,低端移出的位填入进位标志位。

寄存器基址变址寻址

可以看作寄存器间接寻址的增强版,不再直接从寄存器指向的地址中取操作数,而是从寄存器指向的地址再偏移一个量之后再取操作数

LDR R0,[R1,#4]    ;取R1的内容当作主存的地址,在此基础上+4byte,从该地址处取操作数。
LDR R0,[R1,#4]!  ;同上,操作完毕后,!表示指令执行完毕把最后的数据地址写到R1,即R1原来的地址+4
LDR R0,[R1,R2]    ;将寄存器R1的内容加上寄存器R2的内容形成操作数的地址,取得的操作数存入寄存器R0中。
STR R0, [R1,#-4];将R1中的数值减4作为地址,把R0中的数据存放到这个地址中。
LDR R0,[R1],#4   ;把R1指向的数据放到R0中,操作完成后[R1]自增4byte

批量寄存器寻址

LDMIA  R0,{R1,R2,R3,R4}     ;将R1,R2,R3,R4中的数据依次放入R0指向的内存地址,R0+4指向的内存地址...
LDMIA  R0,{R1-R4}  ;同上。

相对寻址

通过使用语句的中的标号进行寻址,通常配合跳转指令使用

    BL   FCN  ;相对寻址,跳转到NEXT处执行。
    ...
FCN:
    ...

堆栈寻址

堆栈即Stack,因为CPU的寄存器总是及其有限的,很多时候我们不得不使用内存来存储数据,比如进行多级跳转的时候,这时候堆栈就是一个很好的工具,每次跳转就将当前函数的返回地址存储到内存,最底层被调用的子函数会最先返回,就先将压入栈的现场返回,以此类推...,ARM使用SP(R13)作为栈指针,ARM设计的内存栈模型有2×2=4种
按照栈在内存增长的方向分为递增栈递减栈
递增(Increase)堆栈:向堆栈写入数据时,堆栈由低地址向高地址生长。
递减(Descend)堆栈:向堆栈写入数据时,堆栈由高地址向低地址生长。

根据堆栈指针SP指向的位置,又可以把堆栈分为满堆栈空堆栈两种。
满堆栈(Full Stack):SP始终指向栈顶元素,压栈的时候先移动SP,再将数据放入SP指向的地址。
空堆栈(Empty Stack):SP始终指向下一个将要放入元素的位置,压栈时先将数据放入SP指向的地址,再移动SP
最后,可以得到4种基本的堆栈类型:

满增栈(FA):堆栈指针指向最后压入的数据,且由低地址向高地址生长。
满减栈(FD):堆栈指针指向最后压入的数据,且由高地址向低地址生长。常用这种
空增栈(EA):堆栈指针指向下一个将要压入数据的地址,且由低地址向高地址生长。
空减栈(ED):堆栈指针指向下一个将要压入数据的地址,且由高地址向低地址生长。

STMFD  SP!,{R1-R7, LR} ;将R1-R7和LR的数据按照压入FD栈
LDMFD  SP!,{R1-R7, PC} ;从FD栈中取得数据依次放入R1-R7,PC

块拷贝寻址

块拷贝寻址提供了一块内存和一组寄存器之间的拷贝,按照内存使用方式的不同,可以分为2×2=4种。地址增方向/地址减方向×先偏移/后偏移。堆栈寻址就可以看作是块拷贝寻址的的一个实例。
即:
IB:Increment Before Operating
IA:Increment After Operating
DB:Decrement Before Operating
DA:Decrement After Operating

STMIA  R0!,{R1—R7}  ;将R1-R7的寄存器中的值放入R0指向的地址,R0自动更新,指向操作后的地址

相关文章:

  • C#多线程应用技术面对面探讨
  • 简单的多人聊天(C#.Socket)
  • Direct3D极速入门宝典
  • 正则语言(转的 大额_skylar )
  • ASP.NET 2.0中直接将Access数据库导入到Excel文件中
  • 读书笔记1
  • 安然公司特殊目的实体(SPEs)解读
  • 双击本地磁盘会出现比如C:\不是有效的Win32应用程序
  • findbugs eclipse 插件 及使用
  • 数字通讯基础:同步与异步
  • Contiki Ctimer模块
  • 人生的抉择
  • (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...
  • phalcon模型查询几种方法
  • 在DotNetNuke中通过修改ascx文件源码自定义界面
  • 0x05 Python数据分析,Anaconda八斩刀
  • Angular6错误 Service: No provider for Renderer2
  • Apache Spark Streaming 使用实例
  • Django 博客开发教程 16 - 统计文章阅读量
  • Docker 笔记(2):Dockerfile
  • dva中组件的懒加载
  • IDEA 插件开发入门教程
  • JavaScript DOM 10 - 滚动
  • k8s 面向应用开发者的基础命令
  • Spring Cloud Feign的两种使用姿势
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • vue-loader 源码解析系列之 selector
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 浮现式设计
  • 使用 Docker 部署 Spring Boot项目
  • 一道面试题引发的“血案”
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 原生Ajax
  • hi-nginx-1.3.4编译安装
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • # Panda3d 碰撞检测系统介绍
  • #pragma预处理命令
  • #Ubuntu(修改root信息)
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (1)(1.11) SiK Radio v2(一)
  • (2015)JS ES6 必知的十个 特性
  • (23)Linux的软硬连接
  • (70min)字节暑假实习二面(已挂)
  • (HAL库版)freeRTOS移植STMF103
  • (多级缓存)缓存同步
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (强烈推荐)移动端音视频从零到上手(下)
  • (三)mysql_MYSQL(三)
  • (三)模仿学习-Action数据的模仿
  • (四)鸿鹄云架构一服务注册中心
  • .NET Core WebAPI中封装Swagger配置
  • .Net IOC框架入门之一 Unity
  • .NET 简介:跨平台、开源、高性能的开发平台