如何解决为什么即使 DPMI 主机处于活动状态,INT 31H 也没有正确设置?
我一直在尝试在 MS-DOS 中进行汇编编程。我读过 Windows 3.1 充当 DOS 程序的 DPMI 主机,并且 DPMI 使用中断 31h 进行函数调用。
所以让我们试一试。我在 Windows 3.1 中打开 DOS 提示符...
C:\WINDOWS>debug
-a100
23A4:0100 mov ax,0400
23A4:0103 int 31
23A4:0105
-r
AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=23A4 ES=23A4 SS=23A4 CS=23A4 IP=0100 NV UP EI PL NZ NA PO NC
23A4:0100 B80004 MOV AX,0400
-p
AX=0400 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=23A4 ES=23A4 SS=23A4 CS=23A4 IP=0103 NV UP EI PL NZ NA PO NC
23A4:0103 CD31 INT 31
-p
所以有些东西显然不起作用。
我再试一次,使用 T
race 命令而不是 P
roceed。这样它实际上会进入中断处理程序,而不是跳过它。
AX=0400 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=23A4 ES=23A4 SS=23A4 CS=23A4 IP=0103 NV UP EI PL NZ NA PO NC
23A4:0103 CD31 INT 31
-t
AX=0400 BX=0000 CX=0000 DX=0000 SP=FFE8 BP=0000 SI=0000 DI=0000
DS=23A4 ES=23A4 SS=23A4 CS=F000 IP=FF01 NV UP DI PL NZ NA PO NC
F000:FF01 7261 JB FF64
-
让我们看看将要执行的内容...
-u
F000:FF01 7261 JB FF64
F000:FF03 63 DB 63
F000:FF04 6C DB 6C
F000:FF05 65 DB 65
F000:FF06 20564D AND [BP+4D],DL
F000:FF09 205669 AND [BP+69],DL
⋮
F000:FF18 53 PUSH BX
F000:FF19 0000 ADD [BX+SI],AL
F000:FF1B 0000 ADD [BX+SI],AL
F000:FF1D 0000 ADD [BX+SI],AL
F000:FF1F 0000 ADD [BX+SI],AL
-
...是的,这看起来不像是应该被执行的任何东西。事实上,字节码看起来很像 ASCII 文本。果然……
-df000:ff01
F000:FF00 72 61 63 6C 65 20 56-4D 20 56 69 72 74 75 61 racle VM Virtua
F000:FF10 6C 42 6F 78 20 42 49 4F-53 00 00 00 00 00 00 00 lBox BIOS.......
F000:FF20 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
F000:FF30 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
F000:FF40 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
F000:FF50 00 58 4D CF CF 89 C0 89-C0 89 C0 89 C0 89 C0 FC .XM.............
F000:FF60 5F 53 4D 5F 7D 1F 02 05-FF 00 00 00 00 00 00 00 _SM_}...........
F000:FF70 5F 44 4D 49 5F 58 C2 01-00 10 0E 00 0A 00 25 00 _DMI_X........%.
F000:FF80 00 .
-
这显然不是 DPMI 处理程序。无论如何,如果我越过 JB FF64
,它将进入 DB 63
(“Oracle”中的“c”),这就是导致无效指令错误的原因。或者,如果设置了进位标志,它将进行跳转并遇到它解释为 JGE FF85
指令的内容。如果标志是这样的,它不进行跳转,它最终会到达另一个无效指令。否则,它会将 [BX+SI]
处的字节增加 AL
中的值 105 次,之后将 BL
中的值增加一次 77 字节,最后重新启动VM,因为下一条指令是实模式复位向量。 (在 v86 模式下,但我猜 Windows 3.1 允许这样做。)
长话短说,很明显在 INT 31H 没有安装 DPMI 处理程序,就像显然应该有的那样。一些额外的信息:
-
您可能已经注意到我只输入了
int 31
,而不是int 31h
。这不是错误;debug
在任何地方都使用并期望十六进制。正如您所见,它并没有尝试将图形模式位图字体作为代码执行。 :P -
我尝试使用 Qualitas MAX 而不是 Windows 3.1,并且根本没有 DPMI 主机,并且在两种情况下都得到了相同的结果。 (当然,减去 Windows 3.1 错误对话框。)
考虑到这一点,谁能告诉我我做错了什么?
解决方法
DPMI 的 Real/Virtual 86 Mode 接口只有中断 2Fh 服务 1687h。这将返回一个入口点,您可以使用该入口点进入保护模式。中断 31h 服务仅在保护模式下可用。这是一个小型 DPMI 客户端的 an example。进入保护模式的相关代码:
mov ax,1687h
int 2Fh
test ax,ax ; DPMI host installed?
jnz nohost
push es ; save DPMI entry address
push di
test si,si ; host requires client-specific DOS memory?
jz .nomemneeded ; no -->
mov bx,si
mov ah,48h
int 21h ; allocate memory
jc nomemory
mov es,ax
.nomemneeded:
; (message and breakpoint omitted)
mov bp,sp
mov ax,0001h ; start a 32-bit client
call far [bp] ; initial switch to protected-mode
jnc initsuccessful
initfailed:
Protected Mode 通常通过执行 PM 中断 21h service 4Ch 退出(随后也传递给 DOS 86M 处理程序,从而终止 DOS 进程)。
顺便说一下,要调试 DPMI 客户端,您可能需要使用 FreeDOS DebugX 或 my fork lDebugX。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。