代码之家  ›  专栏  ›  技术社区  ›  Piepypye

为什么x86汇编中的操作数必须在一行中有大小,而在另一行中没有大小

  •  0
  • Piepypye  · 技术社区  · 7 年前

    看着这张照片,我不得不在第34行写下 word ptr 为了让它起作用,而在44号线上我没有。
    为什么会这样? image

    编译器难道不能知道0020h是一个单词,就像0FF20h是一个单词一样吗?
    将0添加到0020h使其成为00020h或类似的任何操作也不起作用。

    我正在80x86上使用MASM。emu8086,也在dosbox v0上进行了试验。74

    1 回复  |  直到 7 年前
        1
  •  2
  •   Fifoernik    7 年前

    区别在于,您的汇编程序奇怪地、危险地接受 0FF20h 作为暗示 word 操作数大小。但即使对于你的汇编程序, 前导零并不意味着操作数大小 ,仅为实际值;它可能会检查最重要位的位置。

    对于像NASM这样设计良好且一致的汇编程序语法,情况并非如此:如果我尝试在16位模式下用 nasm -fbin foo.asm

    mov [es: si], 2
    mov [es: si], 0ff20H
    

    我发现以下错误:

    foo.asm:1: error: operation size not specified
    foo.asm:2: error: operation size not specified
    

    只有寄存器才能表示整个指令的操作数大小,而不是常数的宽度。( mov [si], ax 不含糊:没有 mov 其中目标宽度与源宽度不同,并且 ax 绝对是 单词 大小。)

    这同样适用于美国电话电报公司和;T和Intel语法模式。(其Intel语法模式与MASM非常相似。)

    没有 mov r/m16, sign_extended_imm8 编码,但有 add 和大多数ALU操作,所以汇编器没有理由假设 xyz [mem], 0 表示字节操作数大小。更有可能是程序员忘记了指定,所以它将其视为错误,而不是默默地接受不明确的内容。

    mov word [mem], 0 将内存中的单词归零是一种完全正常的方法。


    除此之外, x86支持16位代码中的32位操作数大小,使用 66h 操作数大小前缀 。这与地址大小无关。

    mov dword ptr es:[si], 0FF20h 也是可编码的,并且与 mov word ptr es:[si], 0FF20h 如果您省略 size ptr 说明符。

    正如Jester所说,如果前导零算作常量宽度的一部分, 0FF20h 很容易被认为是暗示 dword

    请注意,您必须 0FF20H 如果汇编程序真的依赖于文字的长度,那么它可能会认为这是一个dword。。。类似于 0FFH .这将是一场危险的比赛。注意,明智的汇编器甚至不允许第二种形式没有明确的大小。 这只是一个等待发生的bug

    (合理的汇编程序包括NASM和GAS,如我上面所示)。

    如果我是你,我会很不高兴我的装配工接受了 mov es:[si], 0FF20h 毫无怨言。我认为emu8086甚至比MASM更糟糕,通常会接受这样的东西 mov [si], 2 使用一些默认操作数大小而不是警告。

    我不太喜欢MASM如何从 symbol db 1, 2, 3 也可以,但这并不含糊,它只是意味着您必须查看符号是如何声明的,才能知道它将意味着什么操作数大小。