首页 > 解决方案 > 汇编器使用段寄存器

问题描述

最近我在写汇编,我写的程序在DOSBox下运行没有任何问题。现在我需要将相同的程序移植到使用 DOS 的真实计算机中,但出现了一些问题。

首先,在 DOSBox 下,我使用 ML 进行编译,但在真正的 PC 上,一旦我输入 ML,它就会显示:

该程序不能在 DOS 模式下运行。

因此,我一直在寻找解决方案,发现 MASM 可以毫无问题地编译 asm 程序。不幸的是,我需要移植的程序在编译时报告了严重错误(仅限一种)。

错误 A2061:段寄存器使用不当

出现这些问题的线路如下

...
CARLOC EQU $-2
...
MOV [WORD PTR DS:CARLOC],DX
...

以下代码也会出现同样的问题

...
MOV ES,CX
MOV AL, [BYTE PTR ES:0017H]
...

到目前为止,我已尝试将这个 BYTE PTR 更改为 BYTE PTR [ES:0017H] 产生相同错误的

并将代码成功编译到 BYTE PTR ES:0017H 其中,程序运行但无法正常工作

注意:我不知道目前在哪种架构下工作。并且可能无法物理访问机器,但如果我可以输入一些代码以查看屏幕上的信息,我会很乐意这样做。

代码在这里,如果我需要将它粘贴在这里,那么这里太长了,但在那之前https://pastecode.xyz/view/5f332efc

PC说它运行MSDOS 6

标签: assemblyx86masmaddressing-modememory-segmentation

解决方案


(更新:Michael Petch 说一些MASM 或 MASM 兼容的汇编器允许在括号内覆盖大小和段但 update2:不是全部,所以这实际上可能是问题所在。它至少是更标准的风格,所以我建议总是这样做.)


在您想要的正常 MASM 语法MOV [CARLOC], DX中。 根据您声明的方式carloc,您可能仍然需要mov word ptr [CARLOC], dx,但DS:已经是默认段。

如果您想明确说明,MOV word ptr ds:[CARLOC], dx但我建议在 asm 源代码中省略冗余 DS 前缀,因为某些汇编程序在机器代码中包含冗余 DS 前缀!DS: 唯一不冗余的情况是与ds:[bp]or ebp, or一起使用时ds:[esp],这意味着 SS 作为默认段。

使用 MASM,ds:前缀也需要数字绝对地址。否则,这将被视为立即(无论括号如何),当然不能成为目的地。有了类似的定义CARLOC equ $-2,您将需要ds:[CARLOC]. 显然 MASM 不会ds在机器代码中放置无用的前缀,因此您不必担心该汇编程序。

如果您需要 CS/DS/ES/FS/GS/SS 前缀,标准语法是将其放在括号外:

MOV AL, ES:[0017H]

AL 目标意味着byte ptr操作数大小,它也在括号之外。例如,查看反汇编程序输出。

BYTE PTR ES:0017H并将代码成功编译到其中,

是的,这是有效的语法:括号在某些情况下是可选的(包括绝对地址或符号)。许多人建议始终在内存操作数(而不是OFFSET symbol立即数)周围使用括号,以使人类读者更清楚。

如果您要使用括号,它们会在size ptrseg:覆盖之后。

程序运行但没有正常工作

然后,您的代码除了语法错误之外还有其他错误。

或者,如果您尝试将其构建到 Windows 可执行文件中:当然,将为 DOS 编写的代码(实模式,控制整个机器)构建为 32 位或 64 位是行不通的Windows 可执行文件(保护模式或 64 位模式,操作系统下的 ring 3)。系统调用 ABI 甚至 API 也完全不同:它们是不同的操作系统,并且 DOS API 不适用于 Windows 可执行文件。

Michael 还建议 USE32 或其他指令可能会使 MASM 尝试将您从自己手中拯救出来,并拒绝在应该使用平面内存模型运行的代码中使用分段。但如果es:[17H]有效,那么可能不是这样。


推荐阅读