【问题标题】:What are the technical mechanics and operation of declaring variables in 32-bit MASM?在 32 位 MASM 中声明变量的技术机制和操作是什么?
【发布时间】:2019-08-01 10:48:04
【问题描述】:

在 MASM 版本 11 SDK 中使用 32 位 MASM 程序集,我在编译过程中发现了一个错误。该错误指向我声明具有双字 (dd) 大小的变量的行。该消息说该变量对于我尝试分配给它的字符串来说太小了。当我将变量定义为字节而不是(db)时,程序编译时没有错误。这意味着使用 db 指令声明变量可以比声明双倍数据大小允许更多的存储空间。下面是错误信息指向的双字变量的声明代码:

.data
msg_run dd "Ran a function.", 0

我把msg_run的数据大小改成了一个字节:

.data
msg_run db "Ran a function.", 0

当我尝试用第二行编译时,程序编译并运行没有问题。为什么该错误暗示声明为字节大小的变量比声明为双字大小的变量具有更大的容量?尾随的“,0”有影响吗?

我审查的来源:

https://www.cs.virginia.edu/~evans/cs216/guides/x86.html https://www.shsu.edu/~csc_tjm/fall2003/cs272/intro_to_asm.html

【问题讨论】:

  • “字符串”实际上只是一个以零结尾的字符数组。每个字符都是一个单字节(对于窄字符,C 中的char)。使用 dd 可以使数组的每个元素成为双字,即每个元素都是 32 位,这并不正确。
  • 当您使用db 时,MASM 会以特殊方式处理字符串(引号之间的内容)。 db 是单个字符(字节),因此 MASM 将获取每个字符并将其存储在一个字节中。对于大于字节的类型(dw 和 dd),这种类型的处理不会以相同的方式发生。在这些情况下,MASM 会尝试将您的字符串填充到单个 DWORD(32 位值)中。看看如果你使用dd 并让你的字符串长度

标签: assembly size declaration masm


【解决方案1】:

有一个严格的数据定义语法要求程序员编写每个元素用逗号分隔,这会使声明字符串变得乏味:

myString db 'M', 'y', ' ', 's', 't', 'r', 'i', 'n', 'g', 0

所以 MASM(以及所有其他主流汇编程序)放宽了

中的语法
myString db "My string", 0

注意,我使用引号 ' 表示字符(即数字)和双引号 " 表示字符串,我不知道 MASM 使用的确切语法,它可能会转换为 1 -char 字符串转char。

您在dd 案例中看到的内容看起来与上面的简写非常相似,但它不是声明字符串的语法,实际上,它创建了数字

当在预期数字的地方使用“ABCD”之类的字符串时(例如在dd 中或作为立即数),MASM 将其转换为0x44434241。这些是字符 D、C、B、A 的值。
之所以进行反转,是因为该语法主要用于指令立即数,例如 mov eax, "ABCD"cmp eax, "ABCD"
这样,由于 x86 字节序,将eax 存储到内存将创建字符串“ABCD”(以正确的顺序)。
这对于检查表的签名也很有效,因为这些签名旨在在内存中正确拼写,但当然,一旦加载到寄存器中就会反转。

在 NASM 中,您甚至可以用 mov eax, ("ABCD" + "EFGH") / 2 之类的东西激怒所有人,从而强化将这些字符串视为数字的观点。这也应该适用于 MASM。

我不记得我使用过myVar dd "ABCD" 的情况,但是当结构具有在内存中拼写为reversed 的固定字符串时,它可能很有用。


Michael Petch recapped MASM behaviour in a comment:

当您使用db 时,MASM 会以特殊方式处理字符串(引号之间的内容)。 db 是单个字符(字节),因此 MASM 将获取每个字符并将其存储在一个字节中。对于大于一个字节的类型(dwdd),这种类型的处理不会以同样的方式发生。在这些情况下,MASM 会尝试将您的字符串填充到单个 DWORD(32 位值)中。看看如果你使用dd 并让你的字符串长度

【讨论】:

  • 我认为你的意思是 myString db "My string", 0 而不是 myString "My string", 0
  • 是的,谢谢@MichaelPetch。我什至花了一些时间才看到您评论中字符串的不同:D
  • 这些说法正确吗? (1) 定义dd 生成一个32位的变量,并将未使用的位设置为0; (2) 使用db 定义变量将每个字母的值分别放在1 个字节中。 MASM 为每个字母创建一个字节。
  • @MichaelPetch 是否使用msg dd "tst" 定义 msg 3 32 位值,即双字,每个双字包含一个字符,零填充未使用的寄存器和 0 作为终止符?每个变量可以容纳多少空间?
  • @JoachimRives :不,因为您没有使用db,MASM 将尝试将tst 存储到双字中,但它会存储字符小端(向后)。如果您将 msg 定义为 msg dd "abc" 它应该以相反的顺序发出字节 bca 而不是 abc 。我建议不要发出除db 之外的任何字符串,因为这样做的理由很少。
猜你喜欢
  • 2018-01-05
  • 1970-01-01
  • 2010-12-29
  • 2013-10-31
  • 1970-01-01
  • 2012-03-22
  • 2013-04-15
  • 1970-01-01
  • 2017-11-23
相关资源
最近更新 更多