我目前正在使用MASM在DOSBox上进行汇编编程(16位)。
var1 dd 'abcd'
对于上面的代码,MASM正在生成错误:
A2010:语法错误
语法有什么问题?我只是在一个双字中存储4个字符。
我正在执行16位汇编,所以有问题吗?因为其他变量大于16位,我只能使用db
和dw
吗?
答案 0 :(得分:3)
var1 db 'abcd'
按照zx485的说明,将所需的字节按照所需的顺序放入内存中。
拥有db以外的变量的目的是什么?
方便编写初始化程序,dd 1234h
比db 34h, 12h, 0, 0
更方便。
@MichaelPetch says,MASM的更高版本确实接受dd 'abcd'
,但它们不像NASM那样进行endian翻转。
NASM会接受mov eax, 'abcd'
或dd 'abcd'
就好了:多字符字面量只是整数字面量的另一种形式,第一个字节在内存中优先(最低有效),因为x86的字节序是低位的。也就是说,在NASM中,多字符整数文字的存储顺序与其源顺序相匹配。
但是,当与dd
或dw
一起使用时,MASM会将它们反转,因此第一个字符成为整数的 most 有效字节,并且存储顺序与源代码相反订购。即使在支持该语法的MASM版本中也应避免使用它,并使用十六进制ASCII码加上注释。
在MASM中,如果将其声明为变量而不是标签,它还会设置用于访问数据的默认操作数大小。
使用var1 db ...
意味着您每次要使用dword ptr
访问所有4个字节时都必须使用显式的mov eax, [var1]
。如果没有dword ptr [var1]
,MASM将抱怨操作数大小不匹配。
但是,如果您仅将其声明为普通标签,而不是将字节组装到内存中的任何db或dd指令绑定,则我认为您可以自由使用任意大小的标签。
(更新:显然,带有:
的标签是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'
请注意,mov eax, var1
与MASM语法中的mov eax, [var1]
等效,但是我更喜欢使用[]
使内存引用显式。