34

关于这条 LEAL 指令,0x10 的功能是什么?是乘法还是加法还是别的什么?

leal 0x10(%ebx), %eax

有人可以澄清一下吗?这是 Linux 机器上的 x86 汇编程序。

4

4 回答 4

73

leal 或 lea 全名是“加载有效地址”,它正是这样做的:它进行地址计算。

在您的示例中,地址计算非常简单,因为它只是将偏移量添加到 ebx 并将结果存储在 eax 中:

eax = ebx + 0x10

lea 可以做的更多。它可以添加寄存器,将寄存器与常数 2、4 和 8 相乘,用于字、整数和双精度数的地址计算。它还可以添加偏移量。

请注意, lea 的特殊之处在于它永远不会修改标志,即使您将其用作上面示例中的简单添加也是如此。编译器有时会利用此功能并用 lea 替换添加以帮助调度程序。出于这个原因,经常看到 lea 指令在编译代码中执行简单的算术运算。

于 2010-10-23T12:21:52.417 回答
4

lea代表“加载有效地址”;这是一种使用 IA32 指令集的复杂寻址模式进行算术运算的方法。后缀是一种区分 GNU 语法中指令操作数大小的l方法,就像你在 Linux 机器上的那样。

所以,简而言之,是的,它是一种加法指令。它还可以同时处理乘以 2、4 或 8 的乘法。

另请参阅此相关问题(他们使用英特尔语法来讨论相同的指令):

于 2010-10-23T12:20:58.937 回答
2

GNU 2.18 文档

https://sourceware.org/binutils/docs-2.18/as/i386_002dMemory.html

AT&T:-4(%ebp),英特尔:[ebp - 4]

然后英特尔语法是不言自明的。

更重要的是,文档还解释了一般情况:

形式为 Intel 语法间接内存引用

 section:[base + index*scale + disp]

被翻译成 AT&T 语法

 section:disp(base, index, scale)

其中 base 和 index 是可选的 32 位基址和索引寄存器,disp 是可选的位移,而 scale 取值 1、2、4 和 8,乘以 index 以计算操作数的地址

当我们省略地址的某些部分时,AT&T 中的事情确实会变得有点混乱,例如-4(%ebp),但是通过文档中的示例,我们可以轻松推断出所有语法案例。

要真正了解发生了什么,我建议您查看指令的编码方式。这是一个很好的教程:http ://www.c-jump.com/CIS77/CPU/x86/lecture.html当您看到它时,就会清楚为什么地址的某些部分可能会被省略,以及每种形式是什么将编译为。

于 2015-09-21T20:58:39.577 回答
0

要添加到 Nils 的响应中,

作为复习,IA32 汇编器中的寻址模式通常是以下形式:

IO(Rb, Ri, s),其中:

IO = 立即偏移

Rb = 基址寄存器

Ri = 索引寄存器

s = 比例因子 {1, 2, 4, 8}

所以有效地址计算为*IO + [Eb] + [Ei] s

leal看起来与其他指令如 movl 类似,但有点特殊。它不是从源读取到目标,而是将源的有效地址复制到目标。

因此,正如 Nils 所指出的,它可以用于为以后的内存引用生成指针,也可以用于基本的算术运算。

例如:

让寄存器 %edx 包含一个值 x

leal 1(%edx, %edx, 8), %eax

将 1 + x + 8*x = 1 + 9x 的有效地址加载到寄存器 %eax。

本质上,操作:

真正的 来源目的地 => 目的地=来源地址

如果您熟悉 C,它相当于:

字符 * b = &a;

其中 char a 的地址分配给 char 指针 b

更多示例:

让寄存器 %eax 保存值 x,寄存器 %ecx 保存值 y

leal (%eax, %ecx, 4), %edx 将 x + 4y 赋值给寄存器 %edx

leal 0xB(, %ecx, 5), %edx 会将值 0xB + 5y = 11 + 5y 分配给 %edx

leal (%eax, %eax,2), %eax 会将值 3x 分配给寄存器 %eax

希望这可以帮助

于 2015-09-05T09:08:06.063 回答