x86-64 指令集、AT&T 语法、关于 lea 和括号的混淆 [英] x86-64 instruction set, AT&T syntax, confusion regarding lea and brackets

查看:88
本文介绍了x86-64 指令集、AT&T 语法、关于 lea 和括号的混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被告知 lea %rax, %rdx 是无效的语法,因为来源需要在括号中,即 lea (%rax), %rdx

I’ve been told that lea %rax, %rdx is invalid syntax as the source needs to be in brackets, i.e lea (%rax), %rdx

我想我显然误解了 lea 和括号的用途.

I think I’ve clearly misunderstood both lea and the purpose of brackets.

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

I thought that lea %rax, %rdx would move the memory address stored in %rax, to %rdx, but apparently this is what lea (%rax), %rdx does?

令我困惑的是,我认为括号表示访问内存中的地址,并获取该地址处的值.因此,通过使用方括号,lea 会将一个值从存储在 %rax 中的内存地址移动到目标寄存器中.

What confuses me is that I thought brackets signify going to an address in memory, and taking the value at that address. So by using brackets lea would be moving a value from the memory address stored in %rax into the destination register.

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

Hence why I thought lea %rax, %rdx would be used if you just wanted to move the address stored in %rax into %rdx

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

Could someone explain to me the significance of brackets in the case of the lea instruction?

推荐答案

从不实际使用 lea (%rax), %rdx.使用 mov %rax, %rdx 代替,因为 CPU 运行它更有效,并且两种方式都复制寄存器 (无论该值是否为有效指针).

Never actually use lea (%rax), %rdx. Use mov %rax, %rdx instead because CPUs run it more efficiently, and both ways copy a register value (regardless of whether that value is a valid pointer or not).

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

LEA can only work on a memory addressing mode, not a bare register. LEA kind of "undoes" the brackets, taking the result of the address calculation instead of the value from memory at that address. This can't happen if there wasn't a memory operand in the first place.

这让您可以使用它对任意值进行移位/添加操作,无论它们是否是有效指针:对不是地址/指针的值使用 LEA? LEA 使用 内存操作数语法和机器代码来编码移位/加法操作使用 x86 的正常寻址模式编码,CPU 硬件已经知道如何解码.

This lets you use it to do shift/add operations on arbitrary values, whether they're valid pointers or not: Using LEA on values that aren't addresses / pointers? LEA uses memory-operand syntax and machine code to encode the shift/add operation into a single instruction, using x86's normal addressing-mode encoding that the CPU hardware already knows how to decode.

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

Compared to mov, it's like a C & address-of operator. And you can't take the address of a register. (Or in C, of a register variable.) You can only use it to undo a dereference.

  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,而不是 lea (%rax), %rdi,即使它没有优化掉代码.这是概念上的等价物,使用 C 语法和运算符来解释 asm,而不是展示任何东西实际上会或应该如何编译.

Of course if you asked an actual C compiler to compile that, you'd get mov %rax, %rdi, not lea (%rax), %rdi, even if it didn't optimize away the code. This is in terms of conceptual equivalents, using C syntax and operators to explain asm, not to show how anything would or should actually compile.

这篇关于x86-64 指令集、AT&T 语法、关于 lea 和括号的混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆