ARM立即数详解

在ARM汇编的数据处理指令中经常会使用到常数,而ARM汇编中规定使用的常数必 须是立即数;为什么会有立即数这样的规定呢?

答:这是由于所有的ARM指令是精简指令集,指令长度固定都是32位,对于ARM数据处理指令自然也是一样。数据处理指令大致可包含3类,数据传送指令、数据算术逻辑运算指令和数据比较指令。在一条ARM数据处理指令中,除了要包含处理的数据值外,还要标识ARM命令名称,控制位,寄存器等其他信息。这样在一条ARM数据处理指令中,能用于表示要处理的数据值的位数只能小于32位;

一条ARM指令语法格式分为如下几个部分:

<opcode>{<cond>}{S} <Rd>,<Rn>{,<shifter_operand>}

其中,<>内的项是必须的,{}内的项是可选的,如<opcode>是指令助记符,是必须的,而{<cond>}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行)。

Opcode   指令助记符,如LDR,STR 等

Cond       执行条件,如EQ,NE 等

       S           是否影响CPSR 寄存器的值,书写时影响CPSR,否则不影响

       Rd          目标寄存器

Rn          第一个操作数的寄存器

shifter_operand      第二个操作数(第二操作数有三种形式: 1-- 立即数 add r1,r2,#10 ; 2-- 寄存器 addeqs r1,r2,r3 @ r1=r2+r3 ; 3-- 寄存器移位 add r1,r2,r3,LSL #2 @ r1 = r2 +r3*4)


 ARM在指令格式中设定,只能用指令机器码32位中的低12位来表示要操作的常数。ARM处理器是按32位来处理数据的,ARM处理器处理的数据是32位,如果简单的用这12位来表示,显然范围太小了,为了扩展到32位,因此使用了构造的方法,在12位中用8位表示基本数据值,用4位表示位移值,通过用8位基本数据值往右循环移动4位位移值*2次,来表示要操作的常数。这里要强调最终的循环次数是4位位移值乘以2得到的,所以得到的最终循环次数肯定是一个偶数,为什么要乘以2呢,实质还是因为范围不够,4位表示位移次数,最大才15次(移位值==0:等于没有循环,不算),加上8位数据还是不够32位,这样只能通过ALU的内部结构设计将4位位移次数乘以2,这样就能用12位表示32位常数了。

立即数表示方法:立即数(#immed_8r) = X循环右移Y*2; //为何要*2 ? 答:红色。为何要移偶数位? 因为要*2 构造成32位

[31     11][11   8]  Y:移位值最大 1111b = 15[7  0] X:8bit常数


所以对#immed_8r常数表达式的限制是解决指令编码的第二个操作数位数不足以表示32位操作数的无奈之举,但总比只有12位所表达的数大。
所以:一个8bit常数循环右移(Y*2 = {0,2,4,6,8, ...,26, 28, 30})就得到一个立即数了;


转自:https://blog.csdn.net/linkedin_35878439/article/details/79252808 

 

 

二、如何判断一个数是否是合法立即数?

  1. 首先将这个数转换为32bit16进制形式,例如218=0xDA=0x000000DA
  2. 零外,仅有位数为合法立即数。
  3. 除零外,仅有二位数,并且相邻(包括首尾,如0x1000000A)的为合法立即数。
  4. 零外,仅有三位数,并且相邻(包括中间有0相间,例如0x10800000,包括首尾相邻,如:0x14000003),这三位数中,最高位取值仅能为1、2、3,最低位取值仅能为4、8、C,中间位0x0~0xF。这种组合的为合法立即数。
  5. 除了以上三种,其他基本是非法立即数。

三、非法立即数如何输入?

利用LDR伪指令可将任意32bit的立即数赋给寄存器。

格式:LDR RD,=#Imm32

编译时,编译器会优先使用MOV或者MVN指令来加载立即数,以便提高代码运行效率,如不行,则一般编译成如下形式:

LDR RD,[PC,#offset]

....

PC+OFFSET:.word Imm32

 

转自:http://blog.sina.com.cn/s/blog_9bad4f090101e14d.html

  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ARM嵌入式系统软件开发实例(一) 周立功 北京航天航空大学出版社》(PDF) 目录第1章 ZLG/FS原理与应用 1.1 概述 1.1.1 ZLG/FS简介 1.1.2 ZLG/FS的特点 1.1.3 已实现的特性 1.1.4 暂时未实现的特性 1.2 使用 1.2.1 使用示例 1.2.2 Config.h和fat.h 1.2.3 与编译器无关的数据类型 1.2.4 初始化ZLG/FS 1.2.5 目录相关操作 1.2.6 文件相关操作 1.2.7 关闭ZLG/FS 1.2.8 在多任务环境下使用ZLG/FS 1.3 ZLG/FS的结构视图 1.3.1 概述 1.3.2 应用程序 1.3.3 文件管理与目录管理 1.3.4 文件分配表管理与文件目录表管理 1.3.5 逻辑盘管理模块 1.3.6 高速缓存管理模块 1.3.7 底层驱动程序 1.3.8 实用程序 1.3.9 源代码文件说明 1.4 驱动程序设计指南 1.4.1 一个驱动程序的例子 1.4.2 参数 1.4.3 逻辑盘初始化 1.4.4 卸载逻辑盘 1.4.5 读/写扇区 1.5 FAT文件系统基础知识 1.5.1 简介 1.5.2 本节的约定 1.5.3 概述(适用于各类型的FAT文件系统) 1.5.4 引导扇区和BPB 1.5.5 FAT数据结构 1.5.6 FAT类型的确定 1.5.7 FAT卷的初始化 1.5.8 FAT32 FSInfo扇区结构和备份引导扇区 1.5.9 FAT的目录结构(FDT表) 1.5.10 FAT的长目录项 1.5.11 命名限制和字符集 1.5.12 短文件名和长文件名的名字映射 1.5.13 命名惯例和长文件名 1.5.14 长目录项对旧版FAT的影响 1.5.15 验证目录的内容 1.5.16 与FAT目录项相关的其他注意事项 1.6 逻辑盘信息管理 1.6.1 用户接口函数 1.6.2 内部使用函数 1.6.3 逻辑盘和卷的区别 1.6.4 逻辑盘信息登录项 1.6.5 初始化 1.6.6 加载底层驱动程序 1.6.7 卸载底层驱动程序 1.6.8 获取逻辑盘信息 1.6.9 获取空闲登录项 1.7 Cache管理 1.7.1 用户接口函数 1.7.2 内部使用函数 1.7.3 原理 1.7.4 初始化 1.7.5 通过Cache读/写逻辑扇区 1.7.6 把Cache数据写回逻辑盘 1.8 文件分配表管理 1.8.1 FAT简介 1.8.2 接口函数 1.8.3 获取簇的下一个簇号 1.8.4 设置下一个簇号 1.8.5 为簇链增加一个簇 1.8.6 删除一个簇链 1.9 文件目录表管理 1.9.1 FDT简介 1.9.2 用户接口函数 1.9.3 内部接口函数 1.9.4 数据结构 1.9.5 读取FDT信息 1.9.6 保存FDT信息 1.9.7 获取指定目录指定FDT信息 1.9.8 设置指定目录指定FDT信息 1.9.9 在指定目录查找指定FDT 1.9.10 指定目录查增加FDT 1.9.11 在指定目录删除指定FDT 1.9.12 改变指定目录指定FDT属性 1.9.13 察看指定目录是否为空 1.9.14 在指定目录查看指定FDT是否存在 1.10 目录操作 1.10.1 用户接口函数 1.10.2 内部接口函数 1.10.3 获取指定目录的逻辑盘号 1.10.4 改变当前逻辑盘 1.10.5 建立目录 1.10.6 删除目录 1.10.7 改变当前目录 1.10.8 用户文件/目录名转换为系统名 1.10.9 获取指定文件/目录所在的目录的开始簇号及系统内名称 1.10.10 获取指定目录开始簇号 1.11 文件操作 1.11.1 用户接口函数 1.11.2 数据结构 1.11.3 初始化 1.11.4 删除文件 1.11.5 打开文件 1.11.6 查看指定的文件是否处于打开状态 1.11.7 关闭文件 1.11.8 从文件中读数据 1.11.9 把数据写入文件 1.11.10 判断文件是否读/写到文件尾 1.11.11 移动文件读/写位置 1.12 实用程序 第2章 USB驱动程序开发 2.1 USB1.1协议简介 2.1.1 USB系统构成 2.1.2 USB设备的枚举过程 2.1.3 USB的分组标识 2.1.4 USB标准设备请求 2.1.5 USB设备描述符 2.2 PDIUSBD12器件简介 2.3 硬件电路设计 2.4 软件设计总体思想 2.5 USB设备控制层 2.6 USB接口控制驱动 2.7 应用层 2.7.1 初始化PDIUSBD12 2.7.2 控制传输处理 2.7.3 端点1和端点2数据接收与发送设计思想 2.7.4 从端点接收数据 2.7.5 往端点发送数据 2.8
ARM嵌入式系统软件开发实例(一) 周立功 北京航天航空大学出版社》(PDF) 目录第1章 ZLG/FS原理与应用 1.1 概述 1.1.1 ZLG/FS简介 1.1.2 ZLG/FS的特点 1.1.3 已实现的特性 1.1.4 暂时未实现的特性 1.2 使用 1.2.1 使用示例 1.2.2 Config.h和fat.h 1.2.3 与编译器无关的数据类型 1.2.4 初始化ZLG/FS 1.2.5 目录相关操作 1.2.6 文件相关操作 1.2.7 关闭ZLG/FS 1.2.8 在多任务环境下使用ZLG/FS 1.3 ZLG/FS的结构视图 1.3.1 概述 1.3.2 应用程序 1.3.3 文件管理与目录管理 1.3.4 文件分配表管理与文件目录表管理 1.3.5 逻辑盘管理模块 1.3.6 高速缓存管理模块 1.3.7 底层驱动程序 1.3.8 实用程序 1.3.9 源代码文件说明 1.4 驱动程序设计指南 1.4.1 一个驱动程序的例子 1.4.2 参数 1.4.3 逻辑盘初始化 1.4.4 卸载逻辑盘 1.4.5 读/写扇区 1.5 FAT文件系统基础知识 1.5.1 简介 1.5.2 本节的约定 1.5.3 概述(适用于各类型的FAT文件系统) 1.5.4 引导扇区和BPB 1.5.5 FAT数据结构 1.5.6 FAT类型的确定 1.5.7 FAT卷的初始化 1.5.8 FAT32 FSInfo扇区结构和备份引导扇区 1.5.9 FAT的目录结构(FDT表) 1.5.10 FAT的长目录项 1.5.11 命名限制和字符集 1.5.12 短文件名和长文件名的名字映射 1.5.13 命名惯例和长文件名 1.5.14 长目录项对旧版FAT的影响 1.5.15 验证目录的内容 1.5.16 与FAT目录项相关的其他注意事项 1.6 逻辑盘信息管理 1.6.1 用户接口函数 1.6.2 内部使用函数 1.6.3 逻辑盘和卷的区别 1.6.4 逻辑盘信息登录项 1.6.5 初始化 1.6.6 加载底层驱动程序 1.6.7 卸载底层驱动程序 1.6.8 获取逻辑盘信息 1.6.9 获取空闲登录项 1.7 Cache管理 1.7.1 用户接口函数 1.7.2 内部使用函数 1.7.3 原理 1.7.4 初始化 1.7.5 通过Cache读/写逻辑扇区 1.7.6 把Cache数据写回逻辑盘 1.8 文件分配表管理 1.8.1 FAT简介 1.8.2 接口函数 1.8.3 获取簇的下一个簇号 1.8.4 设置下一个簇号 1.8.5 为簇链增加一个簇 1.8.6 删除一个簇链 1.9 文件目录表管理 1.9.1 FDT简介 1.9.2 用户接口函数 1.9.3 内部接口函数 1.9.4 数据结构 1.9.5 读取FDT信息 1.9.6 保存FDT信息 1.9.7 获取指定目录指定FDT信息 1.9.8 设置指定目录指定FDT信息 1.9.9 在指定目录查找指定FDT 1.9.10 指定目录查增加FDT 1.9.11 在指定目录删除指定FDT 1.9.12 改变指定目录指定FDT属性 1.9.13 察看指定目录是否为空 1.9.14 在指定目录查看指定FDT是否存在 1.10 目录操作 1.10.1 用户接口函数 1.10.2 内部接口函数 1.10.3 获取指定目录的逻辑盘号 1.10.4 改变当前逻辑盘 1.10.5 建立目录 1.10.6 删除目录 1.10.7 改变当前目录 1.10.8 用户文件/目录名转换为系统名 1.10.9 获取指定文件/目录所在的目录的开始簇号及系统内名称 1.10.10 获取指定目录开始簇号 1.11 文件操作 1.11.1 用户接口函数 1.11.2 数据结构 1.11.3 初始化 1.11.4 删除文件 1.11.5 打开文件 1.11.6 查看指定的文件是否处于打开状态 1.11.7 关闭文件 1.11.8 从文件中读数据 1.11.9 把数据写入文件 1.11.10 判断文件是否读/写到文件尾 1.11.11 移动文件读/写位置 1.12 实用程序 第2章 USB驱动程序开发 2.1 USB1.1协议简介 2.1.1 USB系统构成 2.1.2 USB设备的枚举过程 2.1.3 USB的分组标识 2.1.4 USB标准设备请求 2.1.5 USB设备描述符 2.2 PDIUSBD12器件简介 2.3 硬件电路设计 2.4 软件设计总体思想 2.5 USB设备控制层 2.6 USB接口控制驱动 2.7 应用层 2.7.1 初始化PDIUSBD12 2.7.2 控制传输处理 2.7.3 端点1和端点2数据接收与发送设计思想 2.7.4 从端点接收数据 2.7.5 往端点发送数据 2.8
ARM嵌入式系统软件开发实例(一) 周立功 北京航天航空大学出版社》(PDF) 目录第1章 ZLG/FS原理与应用 1.1 概述 1.1.1 ZLG/FS简介 1.1.2 ZLG/FS的特点 1.1.3 已实现的特性 1.1.4 暂时未实现的特性 1.2 使用 1.2.1 使用示例 1.2.2 Config.h和fat.h 1.2.3 与编译器无关的数据类型 1.2.4 初始化ZLG/FS 1.2.5 目录相关操作 1.2.6 文件相关操作 1.2.7 关闭ZLG/FS 1.2.8 在多任务环境下使用ZLG/FS 1.3 ZLG/FS的结构视图 1.3.1 概述 1.3.2 应用程序 1.3.3 文件管理与目录管理 1.3.4 文件分配表管理与文件目录表管理 1.3.5 逻辑盘管理模块 1.3.6 高速缓存管理模块 1.3.7 底层驱动程序 1.3.8 实用程序 1.3.9 源代码文件说明 1.4 驱动程序设计指南 1.4.1 一个驱动程序的例子 1.4.2 参数 1.4.3 逻辑盘初始化 1.4.4 卸载逻辑盘 1.4.5 读/写扇区 1.5 FAT文件系统基础知识 1.5.1 简介 1.5.2 本节的约定 1.5.3 概述(适用于各类型的FAT文件系统) 1.5.4 引导扇区和BPB 1.5.5 FAT数据结构 1.5.6 FAT类型的确定 1.5.7 FAT卷的初始化 1.5.8 FAT32 FSInfo扇区结构和备份引导扇区 1.5.9 FAT的目录结构(FDT表) 1.5.10 FAT的长目录项 1.5.11 命名限制和字符集 1.5.12 短文件名和长文件名的名字映射 1.5.13 命名惯例和长文件名 1.5.14 长目录项对旧版FAT的影响 1.5.15 验证目录的内容 1.5.16 与FAT目录项相关的其他注意事项 1.6 逻辑盘信息管理 1.6.1 用户接口函数 1.6.2 内部使用函数 1.6.3 逻辑盘和卷的区别 1.6.4 逻辑盘信息登录项 1.6.5 初始化 1.6.6 加载底层驱动程序 1.6.7 卸载底层驱动程序 1.6.8 获取逻辑盘信息 1.6.9 获取空闲登录项 1.7 Cache管理 1.7.1 用户接口函数 1.7.2 内部使用函数 1.7.3 原理 1.7.4 初始化 1.7.5 通过Cache读/写逻辑扇区 1.7.6 把Cache数据写回逻辑盘 1.8 文件分配表管理 1.8.1 FAT简介 1.8.2 接口函数 1.8.3 获取簇的下一个簇号 1.8.4 设置下一个簇号 1.8.5 为簇链增加一个簇 1.8.6 删除一个簇链 1.9 文件目录表管理 1.9.1 FDT简介 1.9.2 用户接口函数 1.9.3 内部接口函数 1.9.4 数据结构 1.9.5 读取FDT信息 1.9.6 保存FDT信息 1.9.7 获取指定目录指定FDT信息 1.9.8 设置指定目录指定FDT信息 1.9.9 在指定目录查找指定FDT 1.9.10 指定目录查增加FDT 1.9.11 在指定目录删除指定FDT 1.9.12 改变指定目录指定FDT属性 1.9.13 察看指定目录是否为空 1.9.14 在指定目录查看指定FDT是否存在 1.10 目录操作 1.10.1 用户接口函数 1.10.2 内部接口函数 1.10.3 获取指定目录的逻辑盘号 1.10.4 改变当前逻辑盘 1.10.5 建立目录 1.10.6 删除目录 1.10.7 改变当前目录 1.10.8 用户文件/目录名转换为系统名 1.10.9 获取指定文件/目录所在的目录的开始簇号及系统内名称 1.10.10 获取指定目录开始簇号 1.11 文件操作 1.11.1 用户接口函数 1.11.2 数据结构 1.11.3 初始化 1.11.4 删除文件 1.11.5 打开文件 1.11.6 查看指定的文件是否处于打开状态 1.11.7 关闭文件 1.11.8 从文件中读数据 1.11.9 把数据写入文件 1.11.10 判断文件是否读/写到文件尾 1.11.11 移动文件读/写位置 1.12 实用程序 第2章 USB驱动程序开发 2.1 USB1.1协议简介 2.1.1 USB系统构成 2.1.2 USB设备的枚举过程 2.1.3 USB的分组标识 2.1.4 USB标准设备请求 2.1.5 USB设备描述符 2.2 PDIUSBD12器件简介 2.3 硬件电路设计 2.4 软件设计总体思想 2

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值