假设我想在运行汇编程序之前定义一个初始化的变量字符串(在 section.data
中)。我选择创建的变量名为 Digits
,它是一个包含所有十六进制符号的字符串。
Digits: db "0123456789ABCDEF"
我用db
定义了变量,这意味着定义字节。这是否意味着 Digits
变量的长度为 8 位?这对我来说似乎没有意义,因为:
字符串中的每个字符都是 ASCII 字符,因此每个字符需要 2 个字节。整个字符串总共需要 32 个字节!
那么当我将变量定义为字节时,这意味着什么? 词? 双字?我看不出有什么区别。由于我的误解,告诉字符串所需的数据类型似乎是多余的。
PD:This question 没有帮助我理解。
最佳答案
NASM 答案,MASM 完全不同
链接问题的答案之一引用了 NASM 手册的示例,它确实回答了您的问题。根据要求,我将针对所有三种情况对其进行扩展(并更正小写与大写 ASCII 编码错误!):
db 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 (5 bytes)
dw 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 (6 bytes, 3 words)
dd 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 0x00 0x00 (8 bytes, 2 doublewords)
dq 'ABCDE' ; 0x41 0x42 0x43 0x44 0x45 0x00 0x00 0x00 (8 bytes, 1 quadword)
所以区别在于,当您使用 dd
时,它会用零填充到元素大小的倍数或dw
而不是db
.
根据@Jose's comment ,某些汇编器可能对 dd
使用不同的字节顺序。或dw
字符串常量。在 NASM 语法中,字符串始终按照其在引用常量中出现的顺序存储在内存中。
您可以使用 NASM 对其进行组装(例如,将其组装到默认的平面二进制输出中)并使用 hexdump -C
或者确认字节顺序和填充量的东西。
请注意,元素大小的填充适用于每个逗号分隔的元素。所以看似无辜的dd '%lf', 10, 0
实际上是这样组装的:
;dd '%lf', 10, 0
db '%lf',0, 10,0,0,0, 0,0,0,0 ;; equivalent with db
注意0
换行符之前;如果将指向此的指针传递给 printf
,C 字符串就是 "%lf"
,由第一个 0
终止字节。
( write
系统调用或 fwrite
具有显式长度的函数将打印整个内容,包括 0
字节,因为这些函数适用于二进制数据,而不是 C 隐式长度字符串。)
另请注意,在 NASM 中,您可以执行类似 mov dword [rdi], "abc"
的操作将“abc\0”存储到内存中。即多字 rune 字在 NASM 中的任何上下文中都可以用作数字文字。
MASM 非常不同
参见When using the MOV mnemonic to load/copy a string to a memory register in MASM, are the characters stored in reverse order?了解更多。即使在 dd "abcd"
,MASM 会破坏您的字符串,与源顺序相比,反转 block 内的字节顺序。
关于string - dw 和 dd 与字符串的 db 指令有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38860174/