确定NASM何时可以推断mov操作的大小

有些东西让我在x86程序集中感到困惑了一段时间,NASM推断操作的大小是多少/什么时候的,这里有一个例子:

mov ebx, [eax]

在这里,我们将保存在eax中的地址中的4个字节移动到ebx中。 由于寄存器是32位,所以操作的大小被传送到4个字节。

但是,此操作不会被推断并引发编译错误:

mov [eax], 123456

当然,解决方案是这样的:

mov dword [eax], 123456

这会将数字123456的32位转换为存储在eax中保存的地址处的字节。

但是这让我困惑,它肯定会看到eax是32位的,所以不应该假设我想将它存储为32位值,而不必在mov之后指定dword。

当然,如果我想把12345的16位表示(是的,我把它降低一个,只是意识到它对于一个16位大的寄存器来说太大了),我会这样做:

mov ax, 12345

引用你在评论另一个答案时所说的话,因为我认为这是你的困惑的核心:

我期望mov [eax], 1将保存在内存地址eax中的4个字节设置为1的32位表示形式

BYTE / WORD / DWORD [PTR]注释与存储器地址的大小无关; 这是关于该地址内存中变量的大小。 假设平面32位寻址,地址总是4个字节长,因此必须放在Exx寄存器中。 因此,目标操作数的dword(或其他)注释是汇编程序能够知道是否应该修改1,2或4个字节的RAM的唯一方法。

如果我在机器码上演示这些注释的效果,它可能会有所帮助:

$ objdump -d -Mintel test.o
...
   0:      c6 00  01             mov    BYTE PTR  [eax], 0x1
   3:   66 c7 00  01 00          mov    WORD PTR  [eax], 0x1
   8:      c7 00  01 00 00 00    mov    DWORD PTR [eax], 0x1

(与objdump实际打印它的方式相比,我调整了一些空格。)

注意两件事:(1)三个不同的操作数前缀产生三个不同的机器指令,(2)使用不同的前缀改变源操作数的长度,使其发射到机器代码中。


mov [eax],123456

该指令将使用源操作数的立即寻址和目标操作数的间接寻址,即如指出的那样将十进制数123456放入存储在寄存器eax中的存储器地址中,但eax点本身不必为32的存储器地址位大小。 NASM无法推断目标操作数的大小。 寄存器eax中指针的大小是32位。

当然,如果我想把123456的16位重映射到eax中,我会这么做:mov ax,123456

是的,但是在这里,您正在使用目标操作数的源操作数和寄存器寻址的立即寻址。 汇编器可以根据目标寄存器的大小推断你希望移动的数据量(在ax寄存器的情况下为16位)。

编译错误

我认为你的意思是组装错误:)


在你的第一个案例中,它可以确定它没有问题,因为EBX是一个32位寄存器。 但在第二个中,您使用EAX作为地址,而不是目的地寄存器,所以nasm开发人员采用了安全路线并让开发人员选择大小。

如果你确实使用了mov [eax], 1 ,那么nasm可以从中判断出什么? 你是否想将字节,16位或32位的存储器块设置为1? 这完全是未知的。 这就是为什么强迫开发人员说明其大小的原因。

如果你说mov eax, 123456就完全不同了mov eax, 123456因为目的地是寄存器。

链接地址: http://www.djcxy.com/p/72425.html

上一篇: Determining when NASM can infer the size of the mov operation

下一篇: Memory refrencing Assembly Language