关于这个LEAL指令,0x10的功能是什么?它是一个乘法或加法还是其他东西?
leal 0x10(%ebx), %eax
有人可以澄清一下吗?这是Linux机器上的x86汇编程序。
答案 0 :(得分:71)
leal,或者lea全名是“加载有效地址”,它的确如此:它进行地址计算。
在您的示例中,地址计算非常简单,因为它只是向ebx添加了一个偏移量并将结果存储在eax中:
eax = ebx + 0x10
lea可以做更多事情。它可以添加寄存器,将寄存器与常数2,4和8相乘,用于字,整数和双精度的地址计算。它还可以添加偏移量。请注意,lea的特殊之处在于它永远不会修改标志,即使您将其用作上述示例中的简单添加项。编译器有时会利用此功能并用lea替换添加以帮助调度程序。由于这个原因,看到lea指令在编译代码中进行简单算术并不罕见。
答案 1 :(得分:4)
lea
代表“加载有效地址”;这是一种使用IA32指令集的复杂地址模式进行算术运算的方法。 l
后缀是一种区分GNU语法中指令操作数大小的方法,就像你在Linux机器上一样。
所以,简而言之,是的,这是一种加法指令。它还可以同时处理乘法2,4或8。
另请参阅this related question(他们使用英特尔语法讨论相同的指令):
答案 2 :(得分:2)
GNU as 2.18 docs
https://sourceware.org/binutils/docs-2.18/as/i386_002dMemory.html
AT& T:-4(%ebp),英特尔:[ebp - 4]
然后英特尔语法不言自明。
更重要的是,文档还解释了一般情况:
表格
的英特尔语法间接内存引用
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当你看到它时,会清楚为什么地址的某些部分可能会被省略,以及每个表格将编译成什么。
答案 3 :(得分: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。
本质上,操作:
leal 来源,目的地 => 目的地 = 地址 来源
如果您熟悉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 (%eax,%eax,2),%eax会将值3x分配给寄存器%eax
希望这有帮助