“leal 0x10(%ebx), %eax”中的 0x10 是什么? x86汇编指令?

发布于 2024-09-28 21:14:42 字数 134 浏览 0 评论 0原文

对于这条 LEAL 指令,0x10 的作用是什么?是乘法、加法还是其他什么?

leal 0x10(%ebx), %eax

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

What the function is of the 0x10 in regards to this LEAL instruction? Is it a multiply or addition or is something else?

leal 0x10(%ebx), %eax

Can someone please clarify? This is x86 assembler on a Linux box.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陪我终i 2024-10-05 21:14:42

leal 或 lea 全称是“加载有效地址”,它的作用正是如此:它进行地址计算。

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

eax = ebx + 0x10

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

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

leal, or lea full name is "Load effective address" and it does exactly this: It does an address calculation.

In your example the address calculation is very simple, because it just adds a offset to ebx and stores the result in eax:

eax = ebx + 0x10

lea can do a lot more. It can add registers, multiply registers with the constants 2, 4 and 8 for address calculations of words, integers and doubles. It can also add an offset.

Note that lea is special in the way that it will never modify the flags, even if you use it as a simple addition like in the example above. Compilers sometimes exploit this feature and replace an addition by a lea to help the scheduler. It's not uncommon to see lea instructions doing simple arithmetic in compiled code for that reason.

享受孤独 2024-10-05 21:14:42

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

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

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

lea stands for "load effective address"; it is a way to use the sophisticated adressing modes of the IA32 instruction set to do arithmetic. The l suffix is a way to distinguish the size of instruction operands in the syntax of GNU as, that you have on your Linux box.

So, in short, yes, it's a kind of addition instruction. It can also handle multiplications by 2, 4, or 8 at the same time.

See also this related question (where they are using the Intel syntax to discuss the same instruction):

浅暮の光 2024-10-05 21:14:42

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来计算操作数的地址

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

为了真正理解正在发生的事情,我建议您看一下指令是如何编码的。这是一个很好的教程:http://www.c-jump.com /CIS77/CPU/x86/lecture.html 当您看到这一点时,就会清楚为什么地址的某些部分可能被省略,以及每个表单将编译成什么。

GNU as 2.18 docs

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

AT&T: -4(%ebp), Intel: [ebp - 4]

and then the Intel Syntax is self explanatory.

More importantly, the docs also explain the general case:

An Intel syntax indirect memory reference of the form

 section:[base + index*scale + disp]

is translated into the AT&T syntax

 section:disp(base, index, scale)

where base and index are the optional 32-bit base and index registers, disp is the optional displacement, and scale, taking the values 1, 2, 4, and 8, multiplies index to calculate the address of the operand

Things do get a bit messy in AT&T when we omit some parts of the address, e.g. -4(%ebp), but with the examples in the docs we can easily deduce all the syntax cases.

To really understand what is going on, I recommend that you take a look at how instructions are encoded. This is a good tutorial: http://www.c-jump.com/CIS77/CPU/x86/lecture.html When you see that, it will become clear why some parts of the address may be omitted, and what each form will compile to.

分分钟 2024-10-05 21:14:42

为了补充 Nils 响应,

回顾一下,IA32 汇编器中的寻址模式通常采用以下形式:

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

IO = 立即偏移

Rb = 基址寄存器

Ri = 索引寄存器

s = 缩放因子 { 1, 2, 4, 8}

因此,有效地址计算为 *IO + [Eb] + [Ei]s

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

所以它可以用来生成以后内存引用的指针,也可以
正如尼尔斯指出的,用于基本算术运算。

例如:

让寄存器%edx包含x的值

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

将加载有效地址1 + x + 8*x = 1 + 9x注册%eax。

本质上,操作:

leal source, destination => 目的地 = 地址

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

char * 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 strong> (%eax, %eax,2), %eax 会将值 3x 分配给寄存器 %eax

希望这会有所帮助

To add to Nils response,

As a refresher, the addresing mode in IA32 assembler is generally of the form:

IO(Rb, Ri, s), where:

IO = Immediate Offset

Rb = Base Register

Ri = Index Register

s = Scaling Factor {1, 2, 4, 8}

So the effective address is computed as *IO + [Eb] + [Ei]s

leal looks similar to other instructions like movl, but it is a bit special.
Instead of reading from the source to the destination, it copies the effective
address of the source to the destination.

So it can be used to generate pointers for later memory references, and also
for basic arithmetic operations, as Nils pointed out.

For example:

let register %edx contain a value of x

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

will load the effective address of 1 + x + 8*x = 1 + 9x to register %eax.

In essence, the operation:

leal source, destination => destination = address of source

If you're familiar with C, it is the equivalent of :

char * b = &a;

where the address of char a is assigned to char pointer b

more examples:

Let register %eax hold value x, and register %ecx hold value y

leal (%eax, %ecx, 4), %edx will assign the value x + 4y to register %edx

leal 0xB(, %ecx, 5), %edx will assign the value 0xB + 5y = 11 + 5y to %edx

leal (%eax, %eax,2), %eax will assign the value 3x to register %eax

Hope this helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文