如何用汇编语言在定义双字中存储4个字符?

Has*_*aza 5 assembly masm x86-16

我目前正在使用 MASM 在 DOSBox 上进行汇编编程(16 位)。

var1 dd 'abcd'
Run Code Online (Sandbox Code Playgroud)

对于上述代码,MASM 生成错误:

A2010:语法错误

语法有什么问题?我只是将 4 个字符存储在一个双字中。

我正在做 16 位汇编,所以这是一个问题吗?我可以只使用dbanddw因为其他变量都大于 16 位吗?

Pet*_*des 4

var1 db 'abcd'(not dd) 将您想要的 4 个字节按源顺序放入内存中。

使用 db 以外的变量的目的是什么?

编写初始化程序dd 1234h很方便,比db 34h, 12h, 0, 0将相同的数据组装到输出文件中更方便。此外,当您使用符号时,MASM 将它们视为暗示操作数大小的方式。

更高版本的 MASM 确实接受dd 'abcd',但它们的字节序翻转。(而不是像 NASM 那样按源顺序将字节组装到内存中。)有关 MASM 详细信息,请参阅@RossRidge 的答案

NASM 会接受mov eax, 'abcd'或者dd 'abcd'很好:多字符文字只是整数文字的另一种形式,第一个字节首先在内存中(最低有效位),因为 x86 是小端字节序。即在 NASM 中,多字符整数文字的内存顺序与其源顺序相匹配。

但 MASM 在与dd或一起使用时会反转它们dw,因此第一个字符成为整数的最高有效字节,并且内存顺序与源顺序相反。即使在支持语法的 MASM 版本中也避免使用它可能是一个好主意,并使用十六进制 ASCII 代码加注释。


在 MASM 中,如果将其声明为变量而不是标签,则var1 ddvs.还会设置用于访问数据的默认操作数大小。db

使用意味着您在任何时候想要使用 访问所有 4 个字节时都var1 db ...必须使用显式。如果没有,MASM 将抱怨操作数大小不匹配。dword ptrmov eax, [var1]dword ptr [var1]

但是,如果您将其声明为只是一个普通标签,而不与任何将字节组装到内存中的 db 或 dd 指令绑定,我认为您可以自由地使用任何大小的它。

(更新:显然,带有 a 的标签:是 MASM 中代码部分之外的错误。我不确定是否有办法声明一个不是 MASM“变量”的数据标签。请参阅评论中的讨论。)

;; I'm not sure this is correct, I'm making this up from memory
;; and I've never actually used MASM.  I know the syntax from SO answers.
.data
    label1:         ; "Just" a label, no data
      db 'abcd'       

    ; little-endian 'abcd'
    var2  dd 64636261h        ; no : so the symbol becomes a variable with a size from the dd

.code
func:
    mov  eax, [label1]                ; legal I think
    mov  al, [label1]                 ; also legal
    mov  eax, dword ptr [label1]      ; always works
    movzx  eax,  byte ptr [label1+2]  ; zero extend the 'c' into EAX

    inc  [label1]                  ; ERROR: ambiguous operand-size

    mov  eax, [var1]               ; fine, both operands are dwords
    mov  al, [var1]                ; ERROR: operand-size mismatch
    mov  al, byte ptr [var1]       ; load the low byte of the dword

    inc  [var1]                   ; legal: the "variable" implies dword operand size
    inc  dword ptr [var1]         ; same as above
    and  byte ptr [var1], ~20h    ; upper-case just the first character, 'abcd' into 'Abcd'
Run Code Online (Sandbox Code Playgroud)

请注意,这mov eax, var1相当于mov eax, [var1]MASM 语法,但我更喜欢使用[].

  • 这可能会让您感到惊讶,但在数据部分中,单独一行上带有冒号(`label1:`)的标签是一个错误。实际上,标签应该与冒号一起出现的唯一位置是在代码部分中。经验法则是,在非代码部分的标签后面使用冒号基本上是错误的。这是旧编译器(TASM/MASM)的经验法则。这种行为在后来的版本中发生了变化,哈哈。但如果有人使用旧的 TASM/MASM,我不会依赖它实际组装而不会出现错误。如果你希望它在各种版本的汇编器上工作,它应该是 `label1 db 'abcd'` (不带 `:`) (2认同)
  • 如果您支持不同版本的汇编器,则单独一行上的“label1”(不带冒号)是不正确的。实际上,这可以归结为这一点。在非代码段中定义数据的最兼容的方法是永远不要使用“:”,并且标签(不带冒号)始终必须位于声明数据的行上。 (2认同)