Почему INT 31H не настроен должным образом даже при активном хосте DPMI?

Я много экспериментировал с программированием на ассемблере в MS-DOS. Я читал, что Windows 3.1 действует как хост DPMI для программ DOS и что DPMI использует прерывание 31h для вызовов функций.

Итак, давайте попробуем. Я открываю приглашение DOS в Windows 3.1...

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

И вдруг я снова в Windows с окном ошибки: Это приложение нарушило целостность системы из-за выполнения недопустимой инструкции и будет завершено. Закройте все приложения, выйдите из Windows и перезагрузите компьютер.

Значит что-то явно не работает.

Я пытаюсь снова, используя команду 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 ("c" в Oracle), и это приведет к ошибке недопустимой инструкции. В качестве альтернативы, если флаг переноса установлен, он совершит переход и встретит то, что интерпретируется как инструкция JGE FF85. Если флаги таковы, что он не выполняет переход, он в конечном итоге достигнет другой недопустимой инструкции. В противном случае он увеличит байт в [BX+SI] на значение в AL 105 раз, увеличит байт 77 байт после этого на значение в BL один раз и, наконец, перезагрузит виртуальную машину, потому что следующая инструкция — это сброс в реальном режиме. вектор. (В режиме v86, но, думаю, Windows 3.1 это позволяет.)

Короче говоря, ясно, что в INT 31H не установлен обработчик DPMI, как, по-видимому, должно быть. Несколько дополнительных битов информации:

  • Вы могли заметить, что я набрал только int 31, а не int 31h. Это не ошибка; debug везде использует и ожидает шестнадцатеричный код. И, как вы видели, он не пытался выполнить растровый шрифт графического режима как код. :П

  • Я попробовал это с Qualitas MAX вместо Windows 3.1, а также вообще без хоста DPMI, и в обоих случаях получил одинаковый результат. (Конечно, кроме диалогового окна ошибки Windows 3.1.)

Имея это в виду, может ли кто-нибудь сказать мне, что я делаю неправильно?


person flarn2006    schedule 26.03.2021    source источник
comment
Вы работаете в расширенном режиме 386, да? Заголовок retrocomputing.stackexchange.com/questions/11242/   -  person Nate Eldredge    schedule 27.03.2021
comment
@NateEldredge Да, и я установил флажок «О программе» в диспетчере программ для подтверждения.   -  person flarn2006    schedule 27.03.2021
comment
Интерфейс Real/Virtual 86 Mode для DPMI представляет собой только службу прерывания 2Fh 1687h. Это возвращает точку входа, которую вы можете использовать для входа в защищенный режим. Службы прерывания 31h доступны только в защищенном режиме. Вот пример небольшого клиента DPMI. Кстати, для отладки клиента DPMI вы можете использовать FreeDOS DebugX или мой форк lDebugX.   -  person ecm    schedule 27.03.2021
comment
@ecm Спасибо за объяснение! Почему бы не опубликовать это как ответ?   -  person flarn2006    schedule 27.03.2021


Ответы (1)


Интерфейс Real/Virtual 86 Mode для DPMI представляет собой только службу прерывания 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 или мой форк lDebugX.

person ecm    schedule 27.03.2021