为什么即使DPMI主机处于活动状态,INT31H也没有正确设置?

我在 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

所以有些东西显然不起作用。

我再试一次,使用Trace 命令而不是Proceed。这样它实际上会进入中断处理程序,而不是跳过它。

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]AL105 次中将字节增加 105 次,之后将字节增加 77 字节BL一次,最后重新启动 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 客户端的示例。进入保护模式的相关代码:

        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:

保护模式通常通过执行 PM 中断 21h 服务 4Ch 退出(随后也传递给 DOS 86M 处理程序,从而终止 DOS 进程)。

顺便说一句,要调试 DPMI 客户端,您可能需要使用 FreeDOS DebugX 或我的 fork lDebugX。


以上是为什么即使DPMI主机处于活动状态,INT31H也没有正确设置?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>