变址寻址方式和隐式寻址方式

2024-01-25

索引寻址模式通常用于访问数组,因为数组是连续存储的。我们有一个索引寄存器,它在每次迭代中都会递增,当添加到基地址时,它会给出数组元素地址。 我不明白这种寻址模式的实际需要。为什么我们不能通过直接寻址来做到这一点?我们有了基地址,每次访问的时候加1就可以了。为什么我们需要索引寻址模式,它有索引寄存器的开销?

我不确定隐式寻址模式的指令格式。假设我们有一条指令 INC AC。指令中是否指定了 AC 的地址,或者是否有一个特殊的操作码表示“INC AC”并且我们不包括 AC(累加器)的地址?


我不明白这种寻址模式的实际需要。为什么我们不能通过直接寻址来做到这一点?

你可以; MIPS 只有一种寻址模式,编译器仍然可以为其生成代码。但有时必须使用额外的shift +add计算地址的指令(如果它不仅仅是循环遍历数组)。

寻址模式的要点是保存指令和保存寄存器,特别是在像 x86 这样的 2 操作数指令集中,其中add eax, ecx覆盖eax结果(eax += ecx),与 MIPS 或其他 3 指令 ISA 不同,其中addu $t2, $t1, $t0 does t2 = t1 + t0。在 x86 上,这需要一个副本 (mov) 和add。 (或者在那种特殊情况下,lea edx, [eax+ecx]:x86 可以使用与内存操作数相同的指令编码进行复制和添加(和移位)。)

考虑一个直方图问题:您以不可预测的顺序生成数组索引,并且必须对数组进行索引。在 x86-64 上,add dword [rbx + rdi*4], 1将使用单个 4 字节指令递增内存中的 32 位计数器,该指令解码为仅 2 个微指令,以便前端将其发送到现代 Intel CPU 上的无序核心。 (http://agner.org/optimize/ http://agner.org/optimize/). (rbx是基址寄存器,rdi是一个缩放指数)。有一个scaled索引非常强大; x86 16 位寻址模式支持 2 个寄存器,但不支持缩放索引。

经典 MIPS 仅具有单独的移位和加法指令,尽管 MIPS32 确实添加了用于地址计算的缩放加法指令。这样就可以在这里节省一条指令。作为加载-存储机器,加载和存储始终必须是单独的指令(与 x86 不同,在 x86 上,add 解码为微融合加载+添加和存储。请参阅INC 指令与 ADD 1:重要吗? https://stackoverflow.com/questions/36510095/inc-instruction-vs-add-1-does-it-matter).

与 MIPS 相比,ARM 可能是一个更好的比较:它也是一个加载存储 RISC 机器。但它确实有多种寻址模式可供选择,包括使用桶形移位器的缩放索引。因此,您不需要为每个数组索引单独进行移位/添加,而是使用LDR R0, [R1, R2, LSL #2] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABCAEDD.html, add r0, r0, #1 / str具有相同的寻址方式。

通常,在循环数组时,最好只增加 x86 上的指针。但使用索引也是一种选择,特别是对于使用相同索引的多个数组的循环,例如C[i] = A[i] + B[i]。索引寻址模式有时可以是硬件效率稍低 https://stackoverflow.com/questions/26046634/micro-fusion-and-addressing-modes不过,因此当编译器展开循环时,它通常应该使用指针,即使它必须分别递增所有 3 个指针而不是一个索引。


指令集设计的重点不仅仅是图灵完备,而是能够实现高效的代码可以用更少的时钟周期和/或更小的代码大小完成更多的工作,或者让程序员可以选择实现这些目标中的任何一个。

计算机可编程的最低门槛非常低,参见例如各种一台指令集计算机 https://en.wikipedia.org/wiki/One_instruction_set_computer架构。 (没有真正实现,只是在纸上设计,以表明可以只使用小于零的减法和分支指令来编写程序,并将内存操作数编码在指令中。

在易于解码(尤其是并行解码)与紧凑之间需要权衡。 x86 很可怕,因为它是作为一系列扩展而演变的,通常没有太多规划为未来的扩展留出空间。如果您对 ISA 设计决策感兴趣,请查看 Agner Fog 的博客,了解有关为高性能 CPU 设计 ISA 的有趣讨论,该 ISA 结合了 x86 的优点(一条指令可完成大量工作,例如,内存操作数作为指令的一部分) ALU指令)具有RISC的最佳特性(易于解码,大量寄存器):理想的可扩展指令集的提案 http://www.agner.org/optimize/blog/read.php?i=421.

在指令字中如何使用位也需要权衡,特别是在像大多数 RISC 一样的固定指令宽度 ISA 中。不同的ISA做出了不同的选择。

  • PowerPC 使用大量编码空间来执行强大的位域指令,例如rlwinm https://stackoverflow.com/questions/30896622/understanding-powerpc-rlwinm-instruction(向左旋转并屏蔽位窗口)和大量操作码。我不知道那些通常难以发音且难以记住的助记符是否与此有关......
  • ARM 使用高 4 位根据条件代码来预测执行任何指令。它使用更多的位桶式移位器 http://www.davespace.co.uk/arm/introduction-to-arm/barrel-shifter.html(第二个源操作数可以选择通过立即数或来自另一个寄存器的计数进行移位或循环)。
  • MIPS 的立即数比较大,而且基本上比较简单。

x86 32/64 位寻址模式使用可变长度编码,当存在索引时会带有额外的字节 SIB(缩放/索引/基址)字节,以及可选的 disp8 或 disp32 立即位移。 (例如。add esi, [rax + rdx + 12340]需要 2 + 1 + 4 字节进行编码,而编码则需要 2 字节add esi, [rax].

x86 16 位寻址模式受到更多限制,并将除可选 disp8/disp16 位移之外的所有内容打包到 ModR/M 字节中。


假设我们有一条指令 INC AC。指令中是否指定了 AC 的地址,或者是否有一个特殊的操作码表示“INC AC”并且我们不包括 AC(累加器)的地址?

是的,某些 ISA 中某些指令的机器代码格式包含隐式操作数。很多机器都有push / pop隐式使用特定寄存器作为堆栈指针的指令。例如,在 x86-64 中push rax, RAX 是显式寄存器操作数 (使用以下方式编码在一字节操作码的低 3 位中push r64简写 https://github.com/HJLebbink/asm-dude/wiki/PUSH),而 RSP 是隐式操作数。

较旧的 8 位 CPU 通常具有 DECA 等指令(用于递减累加器 A)。即该寄存器有一个特定的操作码。这可能与 DEC 指令相同,操作码字节中的某些位指定哪个寄存器(就像 x86 在 x86-64 重新调整寄存器用途之前所做的那样)短 INC/DEC 编码 https://github.com/HJLebbink/asm-dude/wiki/DEC作为 REX 前缀:请注意 64 位模式列中的“N.E”(不可编码)dec r32)。但如果没有规则模式,那么它绝对可以被视为隐式操作数。

有时,将事物归入整齐的类别会失败,因此不必太担心对于 x86 是否使用带有操作码字节计数的位是隐式的还是显式的。这是一种花费更多操作码空间来节省常用指令的代码大小的方法,同时仍然允许与不同的寄存器一起使用。

一些 ISA 按照惯例仅使用某个寄存器作为堆栈指针,没有隐式使用。 MIPS是这样的。

ARM32(在 ARM 中,而不是 Thumb 模式)也在压入/弹出中使用显式操作数。它的push/pop助记符只是store-multiple decrement-before / load-multipleincrement-after (LDMIA / STMDB)的别名,用于实现全降序堆栈。看ARM 的文档 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABCAEDD.html对于LDM/STM,它解释了这一点,以及您可以使用这些说明的一般情况做什么,例如LDMDB 递减指针然后加载(与 POP 的方向相反)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

变址寻址方式和隐式寻址方式 的相关文章

  • 由谁决定 I/O 映射和内存映射 I/O (x86)

    在 x86 架构中 我们使用 I O 指令 例如 IN 和 OUT 来进行 I O 映射 I O 据我所知 我们在内存映射 I O 中使用 MOV 等内存指令 这一切都很好 但是谁决定使用哪种 I O 方法呢 如果我想构建自己的设备 外围设
  • 执行长字传输到 CPU 需要多少个周期和大小

    该任务针对架构 ColdFire 处理器 MCF5271 我不明白执行到 CPU 的长字传输或字传输需要多少个周期以及什么大小的周期 我正在阅读图表 但不明白其中有何联系 非常感谢任何评论 我附上了两个例子和答案 数据总线大小 https
  • 检测目标 CPU 上的对齐内存要求

    我目前正在尝试构建一个可以在多种机器上运行的代码 从手持口袋和传感器到数据中心的大型服务器 这些架构之间的 许多 差异之一是对齐内存访问的要求 标准 x86 CPU 不需要对齐内存访问 但许多其他 CPU 需要它 如果不遵守规则 就会产生异
  • 机器码对齐

    我正在尝试了解机器代码对齐的原理 我有一个汇编器实现 可以在运行时生成机器代码 我在每个分支目标上使用 16 字节对齐 但看起来这不是最佳选择 因为我注意到 如果我删除对齐 有时相同的代码会运行得更快 我认为这与缓存线宽度有关 因此某些命令
  • 为什么我的处理器没有内置 BigInt 支持?

    据我了解 BigInts通常在大多数编程语言中实现为包含数字的数组 例如 当添加其中两个数字时 每个数字都会像我们在学校学到的那样被一个接一个地添加 例如 246 816 1062 其中 标记存在溢出 我在学校是这样学的 我实现的所有 Bi
  • 零寄存器如何提高性能?

    在 MIPS ISA 中 有一个零寄存器 r0 始终给出零值 这允许处理器 任何产生要被丢弃的结果的指令都可以将其目标定向到该寄存器 成为一个来源0 据说在这source https web archive org web 20170328
  • 嵌入式领域“软复位”和“硬复位”有什么区别?

    在我看来 软复位 从复位向量启动 硬重置 拉cpu的电平 硬复位当然意味着整个CPU芯片及其所有外设都被复位 造成这种情况的原因可能有很多 复位引脚被外部拉动 时钟故障 片上低电压检测 看门狗 非法指令陷阱等 软复位可能意味着返回复位向量的
  • 通过修改LLVM Backend来Clobber X86寄存器

    我正在尝试稍微改变 X86 目标的 LLVM 后端 以产生一些所需的行为 更具体地说 我想模拟一个像 gcc 的 fcall used 这样的标志reg option https gcc gnu org onlinedocs gcc Cod
  • 考虑到指令具有不同的长度,CPU 如何知道下一条指令应该读取多少字节?

    所以我正在读一篇论文 其中他们说静态反汇编二进制代码是不可判定的 因为一系列字节可以用多种可能的方式表示 如图所示 其 x86 所以我的问题是 那么CPU是如何执行这个的呢 例如 在图中 当我们到达 C3 之后时 它如何知道下一条指令应该读
  • 屏障/栅栏以及获取、释放语义是如何在微架构上实现的?

    很多问题以及文章 书籍 例如https mirrors edge kernel org pub linux kernel people paulmck perfbook perfbook 2018 12 08a pdf https mirr
  • Intel x86 与 AMD x86 CPU 上的访问性能不一致

    我已经实现了一个带有结构内存布局数组的简单线性探测哈希图 该结构包含键 值和指示条目是否有效的标志 默认情况下 该结构体由编译器填充 因为键和值是 64 位整数 但该条目仅占用 8 个布尔值 因此 我也尝试以未对齐访问为代价来打包结构 由于
  • L2 逐出时从 L1 缓存逐出缓存

    我有一个关于内存系统遵循的策略的基本问题 考虑具有私有 L1 和 L2 缓存的核心 在二级缓存之后 我们有一个总线 一致性流量在该总线上运行 现在 如果地址 X 的缓存线从二级缓存中逐出 是否有必要从一级缓存中逐出该地址 驱逐的原因可能是它
  • 现代 x86 CPU 使用什么缓存一致性解决方案?

    我对缓存一致性系统在现代多核 CPU 中的功能有些困惑 我已经看到基于侦听的协议 例如基于 MESIF MOESI 侦听的协议 已在 Intel 和 AMD 处理器中使用 另一方面 基于目录的协议对于多核来说似乎更加高效 因为它们不广播而是
  • 为什么64位cpu不存在高端内存?

    当我试图了解 32 位 cpu 和 Linux 的高内存问题时 为什么没有高内存问题 https en wikipedia org wiki High memory对于64位CPU 特别是 虚拟内存分为内核空间和用户空间的划分是如何改变的
  • 可以直接使用程序集访问缓存吗?

    就效率而言 缓存是一个核心问题 我知道缓存通常会自动发生 但是 我想自己控制缓存的使用 因为我认为我可以比一些不知道确切程序的启发式方法做得更好 因此 我需要汇编指令来直接移入或移出高速缓存单元 like movL1 address con
  • 在单周期数据路径中加载半字和加载字节

    有人询问如何在单周期数据路径中实现加载字节而无需更改数据存储器 解决方案如下 替代文本 http img214 imageshack us img214 7107 99897101 jpg http img214 imageshack us
  • 查看x86架构中的cpu缓存内容

    如何查看或转储基于 x86 的架构的 cpu 缓存内容 每次进行缓存刷新时 我如何才能看到刷新了什么 在哪里 你不能 真的 CPU 缓存被设计为对于 CPU 上运行的代码是透明的 它具有加快代码执行速度的效果 但 CPU 管理有关缓存的所有
  • C 易失性变量和高速缓存

    缓存是由缓存硬件对处理器透明地控制的 因此如果我们在C程序中使用易失性变量 如何保证我的程序每次都从指定的实际内存地址读取数据而不是缓存 我的理解是 Volatile 关键字告诉编译器不应优化变量引用 而应按照代码中的编程方式读取变量引用
  • 现代缓存中的方式预测

    我们知道 就缓存命中时间而言 直接映射缓存优于集合关联缓存 因为不涉及特定标签的搜索 另一方面 组关联缓存通常比直接映射缓存具有更好的命中率 我读到 现代处理器试图通过使用一种称为路径预测的技术来结合两者的优点 他们预测给定集合中最有可能发
  • 为什么x86分页没有特权环的概念?

    早在 1982 年 当 Intel 发布 80286 时 他们在分段方案中添加了 4 个特权级别 环 0 3 由全局描述符表 GDT 和局部描述符表 LDT 中的 2 位指定 在 80386 处理器中 Intel 添加了分页功能 但令人惊讶

随机推荐

  • 如何在没有用户和登录的情况下使用JWT?

    我正在 Node js 中制作一个简单的文件转换器 API 并且希望避免请求中的滥用 所以我正在寻找一种无需 userModel 登录等即可使用 JWT 的方法 但我不能在网上做事 谢谢 我们不需要用户或登录来创建 JWT 我们可以使用任何
  • Mercurial 删除历史记录

    Mercurial 有没有办法从数据库中删除旧的变更集 我有一个 60GB 的存储库 这使得克隆变得非常痛苦 我想在某个日期之前删除所有内容 并将庞大的数据库收起来以收集灰尘 没有简单 推荐的方法可以直接对现有存储库执行此操作 但是 您可以
  • 为什么 PDO 异常错误没有被捕获?

    我有一个 PHP 脚本 在 SQL 查询语句中存在两个故意的拼写错误 try stmt dbh gt prepare SELECT COUNT FROM Product WHERE non existent column stmt gt b
  • 如何使用javascript的reduce函数来计算满足特定条件的项目的平均值?

    因此 假设我有以下对象数组 var arr name John score 8 8 name John score 8 6 name John score 9 0 name John score 8 3 name Tom score 7 9
  • 如何用纯css凹出一条直线

    diamond width 40px height 40px transform rotate 45deg background red div div 我正在尝试用 css 创建一个菱形 然而 我想要创建的菱形不是由直线组成的 而是由四条
  • 如何读取 .docx 文件? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个 docx 文件 它包含许多我想要批量发送邮件的电子邮件地址 如何通过c 读取docx文件 最简单的方法可能是使用 Get 举
  • Delphi 编程中的枚举、常量、类常量

    我在 ClientDataSet 中有一个整数字段 我需要与一些值进行比较 如下所示 我可以使用常量 const mvValue1 1 mvValue2 2 if ClientDataSet Field AsInteger mvValue1
  • 为什么空行中的缩进不好?

    我知道的每个自由开源项目都有针对代码中尾随空格的规则 但我认为在下一行继续当前的缩进是很自然的 int main int a 42 return a 但 git 无论如何都会抛出警告 所以我的问题是 为什么这些选项卡inside目前的缩进不
  • GACUtil“程序集已成功添加到缓存”但“项目数 = 0”

    为什么 当我跑步时 gacutil i myAssembly dll 我得到 Assembly successfully added to the cache 但当我跑步时 gacutil l myAssembly dll I get Nu
  • Google 地图 KML:8 位十六进制代码

    我是 Google 地图和 KML 的新手 我的 KML 文件在地图上渲染多边形 但我想更改多边形上的填充颜色和多边形的线条颜色 问题是我无法以 8 位十六进制创建颜色 每当我认为我的颜色正确时 它的渲染效果就不像我想象的那样 我似乎无法在
  • 如何在 SQL 中取消透视? (SAP HANA)(列到行)

    我需要取消透视 SAP HANA 中的一些数据 我设置了一个示例表来尝试一下 但我仍然一无所获 实际的表包含 1000 个 ID 和大约 50 个列 但我想对许多表执行此操作 因此虽然我可以指定 FieldNames 原始列 但如果有一个自
  • Office.js 选择文本并将其替换为 ContentControl

    我使用 Office js 有以下用例 搜索一些文本body search 找到文本后 可以多次出现 迭代它们并将它们替换为具有不同内容的 ContentControl 搜索部分很简单 但我不确定第二部分 将 ContentControl
  • 在scala中将两个元组组合成一个新的更大元组的干净方法?

    假设我有以下元组 scala gt val t1 Tuple2 abcd efg t1 java lang String java lang String abcd efg scala gt val t2 Tuple2 1234 lmnop
  • ios - 资源文件大小超过 2GB 的企业应用程序

    我正在开发一个用于企业分发的 ipad 应用程序 仅由我公司人员使用 它有很多视频文件 图像 pdf等 制作应用程序后 ipa的大小约为2 2 GB 我想知道该应用程序是否可以在所有 iPad 上有效运行 或者这样做会很麻烦吗 期待一些不会
  • 无法在 keras 中的 BERT 之上添加 CRF 层以进行 NER

    我在训练 NER 的 BERT CRF 模型时遇到了一个未知问题 我使用 keras contrib 作为 CRF 模型 这是导入的库 pip install transformers pip install git https www g
  • Flutter:如何在不复制整个文件的情况下调整/覆盖 Flutter 核心代码的属性?

    这个问题与以下 StackOverflow 问题相关 底部工作表的初始高度为屏幕的一半 如果滚动 则高度会增加到全屏 https stackoverflow com questions 52028107 bottom sheet with
  • nodejs - 如何比较 bcrypt 的两个哈希密码

    您好 在我搜索解决方案后 我需要一些关于这个问题的帮助 但我还没有找到 我想将2个哈希密码与相同密码的bcrypt进行比较 我该怎么做 例如 我有这 2 个哈希密码 它们来自 bcrypt 中的相同密码 var password E Js
  • 有没有办法保证Java中的接口扩展类?

    假设我有以下情况 public abstract class Vehicle public void turnOn public interface Flier public void fly 有没有一种方法可以保证任何实现的类Flier还
  • 如何将文件从旧文件夹结构移动到新文件夹结构?

    我想修改现有的文件夹结构 我有一个按以下方式组织的文件树 Client Name State Province City Order Number 但我对其进行了修改 在订单号之前添加一个地址 并用连字符分隔 如下所示 Client Nam
  • 变址寻址方式和隐式寻址方式

    索引寻址模式通常用于访问数组 因为数组是连续存储的 我们有一个索引寄存器 它在每次迭代中都会递增 当添加到基地址时 它会给出数组元素地址 我不明白这种寻址模式的实际需要 为什么我们不能通过直接寻址来做到这一点 我们有了基地址 每次访问的时候