Assembly 如何在汇编语言中定义双字中存储4个字符?
我目前正在使用MASM对DOSBox进行汇编编程(16位)Assembly 如何在汇编语言中定义双字中存储4个字符?,assembly,masm,x86-16,Assembly,Masm,X86 16,我目前正在使用MASM对DOSBox进行汇编编程(16位) var1 dd 'abcd' 对于上述代码,MASM正在生成错误: A2010:语法错误 语法有什么问题?我只是在一个双字中存储4个字符 我正在做16位组装,这是个问题吗?我只能使用db和dw,因为其他变量大于16位吗?var1 db'abcd'(而不是dd)将所需的4个字节按源代码顺序放入内存 使用db以外的变量的目的是什么 编写初始值设定项的方便性,dd1234h比db34h,12h,0,0更方便,但将相同的数据汇编到输出文件中。
var1 dd 'abcd'
对于上述代码,MASM正在生成错误:
A2010:语法错误
语法有什么问题?我只是在一个双字中存储4个字符
我正在做16位组装,这是个问题吗?我只能使用
db
和dw
,因为其他变量大于16位吗?var1 db'abcd'
(而不是dd
)将所需的4个字节按源代码顺序放入内存
使用db以外的变量的目的是什么
编写初始值设定项的方便性,dd1234h
比db34h,12h,0,0
更方便,但将相同的数据汇编到输出文件中。此外,MASM在使用符号时将其视为隐含操作数大小
MASM的更高版本确实接受dd'abcd'
,但它们会终止它。(而不是像NASM那样以源代码顺序将字节组装到内存中。)请参阅
NASM将接受mov eax,'abcd'
或dd'abcd'
很好:多字符文字只是整数文字的另一种形式,第一个字节在内存中排在第一位(最低有效),因为x86是小尾端。i、 在NASM中,多字符整数文字的内存顺序与其源顺序相匹配
但是当与dd
或dw
一起使用时,MASM会反转它们,因此第一个字符成为整数的最高有效字节,内存顺序与源顺序相反。即使在支持该语法并使用十六进制ASCII码加注释的MASM版本中,也最好避免这种情况
在MASM中,
var1 dd
vs.db
还设置了访问数据的默认操作数大小(如果将其声明为变量而不是标签)
使用var1 db…
意味着您必须在任何时候使用mov eax、[var1]
访问所有4个字节时使用显式dword ptr
。如果没有dword ptr[var1],MASM将抱怨操作数大小不匹配
但是,如果您将它声明为一个普通标签,而不是绑定到将字节组装到内存中的任何db或dd指令,那么我认为您可以自由地使用任意大小的标签
(更新:显然,带有:
的标签在MASM代码部分之外是一个错误。我不确定是否有方法仅声明一个不是MASM“变量”的数据标签。请参阅注释中的讨论。)
请注意,在MASM语法中,
mov eax,var1
相当于mov eax,[var1]
,但我更喜欢使用[]
明确内存引用,因为您正在存储4个字节,所以请尝试var1 db'abcd'
。在内存中也是一样的。我知道这一点,但我应该知道如何使用dd,或者使用db以外的变量的目的是什么?早期版本的MASM和TASM不支持将字符串放在db
以外的类型中的语法。某些汇编器的更高版本(以及其他兼容产品,如wasm和jwasm)确实支持您所做的工作。这很重要。即使对于支持它的汇编器,当在内存中查看大于单个字节(dw、dd、dq等)并加载字符数组的类型时,它们的顺序也会相反(因为x86是小端处理器)。因此,如果这确实起作用,当在内存中查看时,字节将显示为d
c
b
a
。您可能希望查看我的注释。MASM是否支持这一点取决于产品的使用年限。旧版本的MASM不支持它,但新版本支持它(不确定更改的截止点在哪里)@MichaelPetch:谢谢,是的,已经在更新:)如果我有这个权利,在NASM的MASM='dcba'
中,因为支持多字符整数文字的MASM版本在内存中的顺序与其源代码顺序相反?我可以在最新版本的MASM上确认,dd'abcd'
输出这些字节(这是一个32位程序的反汇编):00DB85D4 64 63 62 arpl word ptr fs:[edx+61h],sp
。所以MASM实际上是以相反的方式输出它们。JWASM和WASM(WASM=watcom assembler)也是如此。这可能会让您感到惊讶,但在数据段中,一行上带有冒号(label1:
)的标签本身就是一个错误。实际上,标签上唯一应该显示冒号的地方是在代码段中。经验法则是,在非代码部分的标签后面使用冒号基本上是错误的。这是旧编译器(TASM/MASM)的经验法则。这种行为在后来的版本lol中发生了变化。但如果有人使用旧的TASM/MASM,我不会依赖它来进行无错误的实际组装。如果您想让它在不同版本的汇编器上工作,它应该是label1 db'abcd'
(不带:
)label1
(不带冒号)如果您支持不同版本的汇编器,那么它本身就不正确。实际上,归根结底就是这个问题。在非代码段中定义数据的最兼容方式是永远不要使用:
,标签(不带冒号)必须始终位于声明数据的行上。
;; 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'