x86-64 指令集、AT&T 语法、lea 和括号的混淆

2024-02-10

有人告诉我 lea %rax, %rdx 是无效语法,因为源代码需要放在括号中,即 lea (%rax), %rdx

我想我显然误解了 lea 和括号的目的。

我以为 lea %rax, %rdx 会将 %rax 中存储的内存地址移动到 %rdx,但显然这就是 lea (%rax), %rdx 所做的?

让我感到困惑的是,我认为括号表示进入内存中的某个地址,并获取该地址处的值。因此,通过使用括号 lea 会将存储在 %rax 中的内存地址中的值移动到目标寄存器中。

因此,为什么我认为如果您只想将 %rax 中存储的地址移动到 %rdx 中,则可以使用 lea %rax, %rdx

有人可以向我解释一下 lea 指令中括号的重要性吗?


从未真正使用过lea (%rax), %rdx. Use mov %rax, %rdx相反,因为 CPU 运行效率更高,并且两种方式都会复制寄存器value(无论该值是否是有效的指针)。

LEA 只能工作在内存寻址模式下,不能工作在裸寄存器上。 LEA 有点“撤销”括号,获取地址计算的结果而不是该地址处内存中的值。如果一开始就没有内存操作数,这种情况就不会发生。

这使您可以使用它对任意值执行移位/添加操作,无论它们是否是有效的指针:对不是地址/指针的值使用 LEA? https://stackoverflow.com/questions/46597055/using-lea-on-values-that-arent-addresses-pointers LEA uses内存操作数语法和机器代码将移位/加法操作编码为单个指令,使用 CPU 硬件已经知道如何解码的 x86 正常寻址模式编码。


相比mov,就像一个C&地址运算符。而且你不能获取寄存器的地址。 (或者在 C 语言中,aregister多变的。)您只能使用它来撤消取消引用。

  register char *rax = ...;

  register char dl = *rax;       // mov   (%rax), %dl
  register char *rcx = rax;      // mov   %rax, %rcx
  register char *rdi = &rax[0];  // lea   (%rax), %rdi  // never do this, mov is more efficient
  register char *rbx = &rax[rdx*4 + 1234];  // lea 1234(%rax, %rdx, 4), %rbx  // a real use-case
  
  register char **rsi = &rax;    // lea %rax, %rsi   // ERROR: can't take the address of a register

当然,如果你要求一个实际的 C 编译器来编译它,你会得到mov %rax, %rdi, not lea (%rax), %rdi,即使它没有优化代码。这是概念上的等价物,使用 C 语法和运算符来解释汇编,而不是展示任何内容将如何或应该如何实际编译。

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

x86-64 指令集、AT&T 语法、lea 和括号的混淆 的相关文章

  • 将 C 转换为 MIPS - 嵌套数组

    我正在学习 MIPS 汇编语言 在书中看到了这个例子 对我来说这似乎是不正确的 如果是的话 这将不是我在本书中发现的第一个错误 变量f and g被分配寄存器 s0 and s1分别是数组的基地址A and B are s6 and s7分
  • 现代 x86 硬件不能将单个字节存储到内存中吗?

    说到 C 的并发内存模型 Stroustrup 的C 编程语言 第 4 版 第 1 节 41 2 1 说 就像大多数现代硬件一样 机器无法加载或存储小于单词的任何内容 然而 我的 x86 处理器已经有几年的历史了 它可以并且确实存储小于单词
  • 英特尔® 事务同步扩展新指令 (TSX-NI) 与英特尔 TSX 有何不同?

    我在Intel的页面上找到了 https ark intel com products 97123 Intel Core i5 7500 Processor 6M Cache up to 3 80 GHz https ark intel c
  • gcc 如何知道内联汇编中使用的寄存器大小?

    我有内联汇编代码 define read msr index buf asm volatile rdmsr d buf 1 a buf 0 c index 使用该宏的代码 u32 buf 2 read msr 0x173 buf 我发现反汇
  • DASM 汇编器中的 ASCII 到 C64 屏幕代码

    我正在通过 C64 模拟器学习 6502 micro 的汇编 目前正在尝试将字符串输出到屏幕 这是我的代码 processor 6502 org 1000 ldx 00 using x register as column counter
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • 编写 AMD64 SysV 程序集时使用哪些寄存器作为临时寄存器?

    我正在使用实现一个功能cpuid根据 AMD64 SysV ABI 进行组装 我需要在函数本身中使用 2 个临时寄存器 第一个用于累积返回值 第二个用作计数器 我的功能目前如下所示 zero argument function some c
  • 破坏/分解函数的函数

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

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

    该函数的目的是获取堆栈的起始地址 unsigned long find start void asm movq rsp eax 当我编译它时 出现错误 Error suffix or operands invalid for movq mo
  • 即使我确实为变量设置了初始值,数据段也没有被初始化

    我已经编写了一个代码 该代码应该生成某种数字列表 但是即使我为它们分配了初始值 我的数据段变量也没有被初始化 This is how DS 0000 looks when I run it 这是我的代码 但数据段只保留垃圾值 MODEL s
  • 汇编-符号标志和奇偶校验标志

    我不明白什么时候设置标志标志 什么时候设置奇偶校验 据我所知 符号标志表示运算结果的符号 0表示正数 1表示负数 那么为什么在下一个代码中 mov al 5 sub al 124 SF为零 结果是负数 关于PF 为什么a和b中设置了PF a
  • 减法进位标志

    我正在使用 MASM32 有了这个代码 mov eax 5 sub eax 10 CF 状态标志将被设置 但使用我的铅笔和纸 我实际上看到 MSB 没有任何进位 是的 我知道从较少的数字中减去大的数字集CF 但我想知道为什么 因为使用这段代
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 在 x86-64 CPU 上通过交叉修改代码重现意外行为

    Question 对于可能在 x86 或 x86 x64 系统上触发意外行为的交叉修改代码有哪些想法 在这些系统中 交叉修改代码中的所有操作均已正确完成 但在执行处理器之前执行序列化指令除外修改代码 如下所述 我有一个 Core 2 Duo
  • 汇编8086监听键盘中断

    我有与此完全相同的问题 边画边听键盘 https stackoverflow com questions 13970325 8086 listen to keyboard while drawing 但第一个答案 接受的答案 只听键盘一次
  • 为什么 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
  • 在 x86 ASM 中测试零通常哪个更快:“TEST EAX, EAX”与“TEST AL, AL”?

    测试 AL 中的字节是否为零 非零通常哪个更快 TEST EAX EAX TEST AL AL 假设之前有一个 MOVZX EAX BYTE PTR ESP 4 指令加载了一个带有零扩展的字节参数到 EAX 的其余部分 防止了我已经知道的组
  • 68HC11计算sin(x)的汇编代码

    68HC11 使用泰勒级数或查找表计算正弦值的汇编代码是什么 显示值只能是整数 查找表如何工作 在这种情况下 如何使用它来实现泰勒级数 http en wikipedia org wiki Taylor series 如果您正在寻找浮点解决
  • “rep stos”x86 汇编指令序列有什么作用?

    我最近偶然发现了以下汇编指令序列 rep stos dword ptr edi For ecx重复 存储内容eax到哪里edi指向 递增或递减edi 取决于方向标志 每次 4 个字节 通常 这用于memset型操作 通常 该指令简单地写成r

随机推荐