c - 在不是地址/指针的值上使用LEA吗?

标签 c assembly x86 memory-address

我试图了解地址计算指令的工作原理,尤其是使用leaq命令。然后,当我看到使用leaq进行算术运算的示例时,我会感到困惑。例如,以下C代码,

long m12(long x) {
return x*12;
}

在组装中
leaq (%rdi, %rdi, 2), %rax
salq $2, $rax

如果我的理解是正确的,则leaq应该将地址(%rdi, %rdi, 2)(应该为2*%rdi+%rdi)移动到%rax中。我感到困惑的是,因为值x存储在%rdi中,它只是内存地址,为什么将%rdi乘以3然后将该内存地址左移2等于x乘以12?难道当我们将%rdi乘以3时,我们跳到另一个不保存值x的内存地址吗?

最佳答案

leaq不必对内存地址进行操作,它可以计算一个地址,它实际上不会从结果中读取数据,因此,直到mov等尝试使用它,这只是添加一个数字的深奥方式,再加上1、2、4或8倍于另一个数字(在这种情况下为相同数字)。如您所见,出于数学目的,它经常被“滥用”†。 2*%rdi+%rdi只是3 * %rdi,因此它在计算x * 3时不涉及CPU上的乘法器单元。
类似地,由于二进制数的工作方式(对于十进制数,向右加零乘以10),对于整数,向左移对于整数(每向右加零)会使值加倍。
因此,这是在滥用leaq指令以完成3的乘法运算,然后将结果移位以进一步实现4的乘法运算,从而最终获得12的乘法结果,而实际上并未使用过乘法指令(它认为运行速度会更慢,就我所知,这可能是正确的;再次猜测编译器通常是一场失败的游戏)。
†:清楚一点,它不是滥用,而是以与您的名字所暗示的隐含目的不符的方式使用。以这种方式使用它是100%可以的。

关于c - 在不是地址/指针的值上使用LEA吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46597055/

相关文章:

c - 如何将 YUYV 图像压缩成 jpeg

c - 在文件描述符上使用 fwrite/将文件描述符转换为文件指针

assembly - 没有保护模式的 CPU 中的保护

linux - 如何使用 RF24 通过 USB 在普通 PC (Linux) 上与 nRF24L01+ 通信?

video - 汇编 x86 视频模式

c++ - 从另一个 dll 内的 dll 获取字符串

c++ - 没有输入/输出的函数是过程吗?

assembly - 我不明白 SBC 是怎么回事

对 malloc 的调用永远不会在嵌入式系统上返回——奇怪的是

c - x86 过程调用内存分配