【问题标题】:declaration of constant strings in x86 assembly languagex86 汇编语言中常量字符串的声明
【发布时间】:2017-01-05 15:51:14
【问题描述】:

今天,在声明常量字符串时(在 win 10 中使用 Visual Studio community 2015)我遇到了一个问题。 书上说,

String BYTE "HELLO",0

当我输入相同的内容时,MASM 会抛出如下错误:

语法错误:,

然后,我删除了 ,然后显示为 0:

表达式中缺少运算符

如何消除此错误? 声明常量字符串的正确方法是什么?

【问题讨论】:

  • 你在看什么书?也许它没有教你 MASM 语法? BYTE 在这里是非法的(虽然它是其他地方使用的关键字)。这应该是 String db "HELLO",0 并且可能位于 .data 段中。
  • @Cody Gray 我正在阅读 kip Irvine 的 x86 汇编编程。您的符号是在遗留数据指令下给出的,并且同样正确。它确实在 .data 段中。谢谢。
  • 我的问题解决了,但很奇怪.. 更新我的电脑并重新启动后.. 它现在接受这两种表示法。但是大多数汇编程序支持的标准符号是什么?谢谢。
  • 没有“大多数汇编程序”。每个人都有自己的语法。对于 MASM,该行应为 String db "HELLO",0
  • 现代版本的 MASM 也支持 BYTE 指令(作为旧好的 DB 的替代品),事实上 DB 现在已经“过时”了......我希望有很多在接下来的十年中,对 SO 的 MASM 问题很有趣,好像 16/32/64b 模式和 MASM/TASM vs NASM/FASM/YASM vs gas/AT&T 之间的歧义还不够……玩得好 MS,玩得好。 :D

标签: assembly x86 masm


【解决方案1】:

用于声明常量字符串的“标准”MASM 语法是:

VarName DB "String Contents",0

这声明了一个字节数组 (db == declare byte),符号名称为 VarName。该数组的内容由括在引号中的值 ("String Contents") 给出,并且该数组以 NUL 字符 (0) 结束。显然,这给你的是一个标准的 C 风格的 NUL 终止字符串,几乎可以与任何 C API 一起使用。

我将其称为 MASM 的“标准”语法,因为它是我使用的一种,大多数编译器/反汇编器使用的一种,并且您会看到大多数代码示例都是用这种语法编写的。

然而,正如Ped7g points out in a comment,MASM 的现代版本实际上支持在声明中使用BYTE 指令。它实际上是DB 的同义词。这将使本书作者的代码正确,并且适​​用于与任何现代版本的 Visual Studio 捆绑的 MASM 版本:

VarName BYTE "String Contents",0

你可以使用任何你想要的。如果您正在从使用后者的书中学习,您可能会为了方便而坚持使用它。但是,您也应该注意前者,因为正如我所提到的,您会到处看到它。


以下是您将在数据定义中看到的类型说明符(关键字)的完整列表:

  • DB(Declare Byte),相当于BYTE
    (与AL 寄存器大小相同的8 位 值)
  • DWDeclare Word),相当于WORD
    (与AX 寄存器大小相同的16 位 值)
  • DDDeclare DoubleWord),相当于DWORD
    (与EAX 寄存器大小相同的32 位 值)
  • DFDeclare Float),相当于FWORD
    (用于存储单精度浮点值的48 位值)
  • DQDeclare QuadWord),相当于QWORD
    (当面向 64 位模式 x86-64 时,64 位值与 RAX 寄存器大小相同,并且还用于存储双精度浮点值)
  • DTDeclare Ten-byte),相当于TBYTE
    80 位值与 x87 FPU 的基于堆栈的寄存器大小相同;用于将值从那里直接溢出到内存而不会丢失精度)

【讨论】:

  • 你有引用 DB 代表 Declare 字节吗?我认为它代表“数据字节”;其目的是将字节直接组装到输出文件中。
  • 手头没有引用,@Peter。只是一致性,我头脑简单的妖精。
【解决方案2】:

好的,在 MASM 中声明字符串有几种方法: 首先,您可以在数据段中声明字符串并在整个代码中使用该变量。

stringName    BYTE   "Hello, this is a string", 0 

要声明一个字符串常量,您可以使用 EQU 或 TEXTEQU 指令。两者都在全局范围内的数据段之前声明。

constantString  EQU      <"Hello, string content", 0>

棘手的部分是,您需要在数据段中声明一个具有常量值的变量。像这样:

.data
variableName    BYTE    constantString

然后您可以继续在其余代码中使用您的命名变量。

TEXTEQU 可能有点棘手。它创建了一个“文本宏”。它可以简单地分配文本、分配另一个现有文本宏的内容或 const 整数表达式。例如,这里是文本。同样,必须将常量分配给数据段中的变量。

constantName    TEXTEQU    <"string content">

.data
variableName    BYTE   constantName

希望这会有所帮助。注意:字符串末尾的零字节对于字符串声明很重要,但在 TEXTEQU 中,您定义的是 MACRO,而不仅仅是字符串。

【讨论】:

  • TEXTEQU 是一个汇编时指令,类似于 C 中的 #define。它不会将任何字节汇编到输出文件中。
  • 是 EQU 或 TEXTEQU 工作实际需要的数据周围的 &lt;&gt; 吗?我不认为这看起来像正常的 MASM 语法。
  • 是的,但通常在 .data 段中声明字符串。使用 时,常量在全局范围内声明
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-05
相关资源
最近更新 更多