非常明智的问题,但我没有找到一个好的答案,所以我在这里问。
我看到有时为了添加我们使用ADD指令,有时我看到使用加号(+)
请看以下内容:
mov eax,[esi + TYPE DWORD]
嗯,我了解到为了添加数字,我应该使用ADD指令,但它似乎是这样工作的 我认为应该这样做:
add esi, TYPE DWORD
mov eax,[esi]
sub esi, TYPE DWORD
我的意思是,如何在不执行添加指令的情况下访问内存地址 esi + TYPE DWORD ?太奇怪了...
非常感谢你阅读(:
答案 0 :(得分:3)
为了更加通用,你在第一个例子中看到的是寻址模式的一部分,而不是操作码。
最简单的地址寄存器只是指向你感兴趣的东西(基地址)
[bx]
如果您正在查看数组或结构,则必须调整基址寄存器以查看其他任何内容。时间继续前进,寻址变得更加灵活。你可以有一个基数和一个索引:
[ebx+eax] ; add 2 registers to get the pointers - array + index
现在,如果你有一个字节数组,你可以保留基数并调整索引。如果您要查看2,4或8个字节,可以按目标大小调整索引:
[ebx+eax*2] ; 2 byte target, array + (index*2)
现在,如果您正在查看c风格的结构,那么您也可以在结果地址中添加位移:
[ebx+eax*2+16]
这些在编译时被编码到指令中,而不是变成汇编指令。熟悉寻址模式 - 如果您使用正确的模式获得正确的解决方案,它们将为您节省大量时间。
答案 1 :(得分:2)
首先,这些被编码为两个不同的东西 - ADD
是一个指令,将带有完整的操作码,而+
将由汇编程序转换为参考模式它附加的主要指令(在这种情况下为MOV
)。
然而,主要区别在于第一个将由存储器单元(或更准确地说 - 地址生成单元)执行,而不会在加载执行之上消耗任何额外的仲裁,而后者将通过ALU执行并相应地消耗所需的资源(取决于微架构,但在您的示例中,在任何现代无序CPU上至少需要几个队列条目,解码插槽,调度插槽,端口等等。) 。
从这个意义上说,第一个通常是“更便宜”,这就是为什么它经常被用于没有内存引用的正常算术运算,通过使用LEA
指令,正如Harold指出的那样。