只有 EAX 的低半部分归零? (MASM 使用 .486 / .model flat,stdcall)
Posted
技术标签:
【中文标题】只有 EAX 的低半部分归零? (MASM 使用 .486 / .model flat,stdcall)【英文标题】:Only the low half of EAX is zeroed? (MASM using .486 / .model flat,stdcall) 【发布时间】:2021-10-05 22:50:33 【问题描述】:在 VS2019 中运行下面的代码,令我惊讶的是寄存器 EAX 没有被指令 xor eax, eax
归零。
_text SEGMENT
.486
.model flat,stdcall
.stack 4096
.code
main PROC
xor eax, eax
ret
main ENDP
_text ENDS
END
P.S.:我期望 EAX 寄存器在指令 xor eax, eax
之后为零。在ret
指令中使用断点调试代码我可以在Registers 窗口中看到只有AX 被归零。 EAX 中的 16-31 位没有任何反应。在 x64 中,指令 xor eax, eax
正确执行,按预期将整个 RAX 寄存器归零。
【问题讨论】:
如果该指令实际执行,肯定会如此。因此,我怀疑该指令实际上并未在您的测试中执行,或者您错误地观察了 eax 中的值。您正在做哪些确切的测试来得出结论? 您能解释一下您是如何构建和运行该程序的吗?听起来好像在途中某处可能存在 16/32 位模式不匹配。 同意@Nate,这听起来像是汇编器发出了66
操作数大小前缀,因为它认为指令将以16位模式执行,但实际上它以32位模式执行该前缀使其成为xor ax,ax
,即非默认操作数大小。将.486
放在 .model flat,stdcall
之后有帮助吗?在其他一些 SO 答案中,我隐约记得那些对 MASM 很重要的指令的顺序。您可以查看反汇编,并尝试像push eax
这样的指令(可能只会将 ESP 更改 2)。
@PeterCordes 关于66
,您也是正确的。查看指令xor ax, ax
的地址,我看到了用于指令的编码字节66 33 C0
。再次,很好的答案!
我对 MASM 不是很熟悉,但我见过的其他 32 位 MASM 程序示例不包含 SEGMENT
指令。如果你把它拿出来会发生什么?
【参考方案1】:
根据您的 cmets,SEGMENT
指令似乎以某种方式说服了汇编器,它正在汇编代码以在 16 位模式下运行。
在 16 位模式下,对 32 位寄存器(如 eax
)进行操作的指令需要 66
操作数大小前缀,因此汇编器发出 66 33 C0
。然而,程序实际上是在 32 位模式下运行的,其中 66
操作数大小前缀的含义是相反的:32 位操作数是默认值,66
选择 16 位操作数。所以当程序运行时,指令以xor ax, ax
执行,并且没有将eax
的高位归零。
您说删除 SEGMENT
指令修复了它。我不知道它为什么会产生这种效果,但是其他 32 位 MASM 程序的例子无论如何都不包含这个指令,所以它可能根本就不应该存在。
【讨论】:
我如何确定计算机在哪种模式下运行?我相信这与@Peter Cordes here 提供的链接有关,但这对我来说太高级了,无法理解。但是,例如,我想知道在给定的特定模式下我可以使用哪个指令来组装代码。我应该如何进行? 模式由可执行文件的格式和标题设置,因此您依赖汇编器和链接器(通过指令、命令行选项等)生成可执行文件,并在其中设置正确方式。我对 MASM 的了解也不够充分,无法完全解释该过程。但作为开始,我会说只是寻找 32 位或 64 位程序的示例,并在更改代码的同时使用它们的指令。我不确定现代 Windows 甚至可以在 16 位模式下运行程序,而且您可能也不想这样做。 来自 MASM 文档(强调我的):“SEGMENT
指令中的 use 类型指定了 80386/486 处理器上的段字长。段字长 确定段中所有项的默认操作数和地址大小。如果在.MODEL
指令之前指定.386
或.486
指令,则USE32
是默认值”。由于 OP 在 .486
/.model
之前放置了 SEGMENT
指令并且没有指定 size 属性,这可能给了该段一个 USE16
属性。
无论如何,我不确定何时需要在平面模型程序中使用SEGMENT
指令。你已经得到了简化的段指令(.code
、.data
、.data?
等),这应该足够了。
@Michael 我在当前的 Microsoft Macro Assembler Reference.pdf 中找不到您提到的 above 的任何内容。以上是关于只有 EAX 的低半部分归零? (MASM 使用 .486 / .model flat,stdcall)的主要内容,如果未能解决你的问题,请参考以下文章
带 masm 的寄存器 edx::eax 中的 mul 和内存分配