关于 [base + index*scale + disp] 和 AT&T disp(base,index,scale) 的几个问题

2024-03-19

Intel 和 AT&T 语法中内存寻址的一般形式如下:

[base + index*scale + disp]      # Intel, including GAS .intel_syntax noprefix
disp(base, index, scale)         # AT&T

我的问题如下:

  • Can base and index有什么寄存器吗?
  • 什么价值观可以scale请问,是 1、2、4 和 8(默认为 1)吗?
  • Are index and disp可互换(唯一的区别是index是一个寄存器,同时disp是一个立即值)?

Intel手册中对此有描述:

3.7.5 指定偏移量
内存地址的偏移部分可以直接指定为静态值(称为位移)或通过 由以下一个或多个组件组成的地址计算:

  • 移位— 8 位、16 位或 32 位值。
  • Base— 通用寄存器中的值。
  • Index— 通用寄存器中的值。 [不能是 ESP/RSP]
  • 比例因子— 值 2、4 或 8 乘以索引值。

添加这些组件所产生的偏移量称为有效地址。

比例因子被编码为 2 位移位计数 (0,1,2,3),比例因子为 1、2、4 或 8。是的,*1(shift count = 0) 是默认值,如果你写(%edi, %edx);这相当于(%edi, %edx, 1)


在 AT&T 语法中,它是disp(base, index, scale)- 常量位于括号之外。一些 Intel 语法汇编器也允许类似的语法1234[ebx],其他人则没有。但 AT&T 语法很严格;寻址模式的每个组件都可以only去它适当的地方。例如:

movzwl  foo-0x10(,%edx,2), %eax

从地址将零扩展 16 位(“字”)加载到 EAX 中foo-0x10 + edx*2。 EDX 是索引寄存器,比例因子为 2。没有基址寄存器。foo and -0x10都是位移的一部分,都是链接时间常数。foo是一个符号地址,链接器将填充该地址并从中减去 0x10(因为-0x10组装时间偏移)。

如果可以选择,请仅使用基数而不是小数位数为 1 的索引。索引需要 SIB 字节进行编码,从而使指令更长。这就是为什么编译器选择这样的寻址模式8(%ebp)访问堆栈内存,而不是8(,%ebp).

也可以看看引用内存位置的内容。 (x86 寻址模式) https://stackoverflow.com/questions/34058101/referencing-the-contents-of-a-memory-location-x86-addressing-modes有关何时可以使用基数和/或索引和/或位移的更多信息。


16 位位移只能在 16 位寻址模式下进行编码,该模式使用不同的格式 https://stackoverflow.com/questions/55657904/why-dont-x86-16-bit-addressing-modes-have-a-scale-factor-while-the-32-bit-vers不能包含比例因子,并且有一个非常寄存器的选择有限 https://stackoverflow.com/questions/12474010/nasm-x86-16-bit-addressing-modes可以是基数或索引。

所以像这样的模式1234(%edx)必须将 1234 编码为 32 位disp32在 32 位机器代码中。

-128 .. +127 的字节偏移可以使用短格式 8 位编码。您的汇编器将为您处理这个问题,使用最短的有效编码进行位移。


所有这些在 64 位寻址模式下的 64 位模式中都是相同的,disp32 也像 disp8 一样被符号扩展为 64 位。

64位模式确实添加了新的不同寻址模式,symbol(%rip)它不适用于任何通用寄存器,仅适用于 RIP 的 32 位偏移量。看x86-64 GAS Intel 语法中的 RIP 相对变量引用(如“[RIP + _a]”)如何工作? https://stackoverflow.com/questions/54745872/how-do-rip-relative-variable-references-like-rip-a-in-x86-64-gas-intel-sy其中还涵盖了 AT&T 语法。

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

关于 [base + index*scale + disp] 和 AT&T disp(base,index,scale) 的几个问题 的相关文章

  • MASM 字符串反转

    好吧 我正在讨论这个问题 可能是一个非常复杂的解决方案 但这是我脑海中浮现的第一件事 我需要编写一个汇编语言程序来反转 源 字符串 而不使用 目标 字符串 临时变量 这是我的尝试 INCLUDE Irvine32 inc data sour
  • C/C++ 中的简单“Hello World”内联汇编语言程序

    我使用 devcpp 和 borland c 编译器 asm mov ax 4 I O Func mov bx 1 Output func mov cx name address of the string mov dx 6 length
  • 为什么当设置为 TLS 选择器时,ES 和 DS 在 64 位内核上最终会归零?

    下面的 32 位程序调用set thread area 2 http linux die net man 2 set thread area在 GDT 中创建一个条目 该条目旨在用于 TLS 通常将结果选择器放入FS or GS并成功使用
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • 一条指令可以同时处于两种寻址模式吗?

    我在书中读到了以下内容从头开始编程 处理器有多种不同的访问数据的方式 称为 寻址模式 最简单的模式是立即模式 其中 要访问的数据嵌入在指令本身中 例如 如果我们想将寄存器初始化为 0 而不是给出 计算机要从中读取 0 的地址 我们将指定立即
  • 遍历内存编辑每个字节

    我正在编写汇编代码 提示用户输入一串小写字符 然后输出包含所有大写字符的相同字符串 我的想法是迭代从特定地址开始的字节 并从每个字节中减去 20H 将小写变为大写 直到到达具有特定值的字节 我对 Assembly 相当缺乏经验 所以我不确定
  • 为什么 SSE 对齐读取 + 随机播放在某些 CPU 上比未对齐读取慢,而在其他 CPU 上则不然?

    在尝试优化有限差分代码所需的未对齐读取时 我更改了未对齐的负载 如下所示 m128 pm1 mm loadu ps H k 1 进入这个对齐的读取 随机播放代码 m128 p0 mm load ps H k m128 pm4 mm load
  • AVX512 掩码寄存器(k1...k7)的 GNU C 内联 asm 输入约束?

    AVX512 为其算术命令引入了 opmask 功能 一个简单的例子 上帝螺栓 org https godbolt org z P7xWD8 include
  • 即使我确实为变量设置了初始值,数据段也没有被初始化

    我已经编写了一个代码 该代码应该生成某种数字列表 但是即使我为它们分配了初始值 我的数据段变量也没有被初始化 This is how DS 0000 looks when I run it 这是我的代码 但数据段只保留垃圾值 MODEL s
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • orpd等SSE2指令有什么意义?

    The orpd指令是 压缩双精度浮点值的按位逻辑或 这不是做完 全相同的事情吗por 按位逻辑或 如果是这样 拥有它还有什么意义呢 请记住 SSE1orps https www felixcloutier com x86 orps首先 实
  • 内联 asm 中不支持的指令“mov”将控制寄存器移动到 uint32_t

    我在 C 函数中使用汇编代码 但海湾合作委员会给出unsupported instruction mov 以下代码的错误 uint32 t faulting address asm volatile mov cr2 0 r faulting
  • 如何在汇编语言中换行打印多个字符串

    我试图在汇编中的不同行上打印多个字符串 但使用我的代码 它只打印最后一个字符串 我对汇编语言非常陌生 所以请耐心等待 section text global start start mov edx len mov edx len1 mov
  • 为什么 Visual Studio 使用 xchg ax,ax

    我正在查看程序的反汇编 因为它崩溃了 并注意到很多 xchg ax ax 我用谷歌搜索了一下 发现它本质上是一个 nop 但是为什么 Visual Studio 会执行 xchg 而不是 noop 该应用程序是一个C NET3 5 64位应
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • 尝试使用 x86 程序集 GNU GAS 在数组索引处赋值时出现错误

    我在用x86GNU 与 GCC 的程序集 并尝试实现相当于以下内容的程序集c c int x 10 x 0 5 但是 当我尝试运行 使用命令 a out 我的汇编代码如下 第一次编译后gcc filename s 错误Segmentatio
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 为什么 GCC 不将 a*a*a*a*a*a 优化为 (a*a*a)*(a*a*a)?

    我正在对科学应用程序进行一些数值优化 我注意到的一件事是 GCC 会优化调用pow a 2 通过将其编译成a a 但是调用pow a 6 没有优化 实际会调用库函数pow 这大大降低了性能 相比之下 英特尔 C 编译器 http en wi
  • Nasm 打印到下一行

    我用 nasm Assembly 编写了以下程序 section text global start start Input variables mov edx inLen mov ecx inMsg mov ebx 1 mov eax 4
  • 如何知道寄存器是否是“通用寄存器”?

    我试图了解寄存器必须具备什么标准才能被称为 通用寄存器 我相信通用寄存器是一个可以用于任何用途的寄存器 用于计算 将数据移入 移出等 并且是一个没有特殊用途的寄存器 现在我读到了ESP寄存器是通用寄存器 我猜是ESP寄存器可以用于任何事情

随机推荐