dosemu2/test/ecm/dpmitest/dpmims.asm
geos_one 91736529d5
Some checks failed
Master / Scheduled (FULL) (push) Has been cancelled
Master / Triggered (push) Has been cancelled
Master / Triggered (ASAN) (push) Has been cancelled
Master / Triggered (FULL) (push) Has been cancelled
New upstream version 2.0pre9.2
2025-08-10 12:35:43 +02:00

236 lines
4.6 KiB
NASM

%if 0
Example of using DPMI raw-mode switching
Public Domain
%endif
;%include "CMMACROS.MAC"
%define _4digitshex(h) ((((h)/1000h)% 10h)+'0' +(('A'-'9'-1)*((((h)/1000h)% 10h)/0Ah))), \
((((h)/100h)% 10h)+'0' +(('A'-'9'-1)*((((h)/100h)% 10h)/0Ah))), \
((((h)/10h)% 10h)+'0' +(('A'-'9'-1)*((((h)/10h)% 10h)/0Ah))), \
(((h)% 10h)+'0' +(('A'-'9'-1)*(((h)% 10h)/0Ah)))
; ASCIZ string
;
; %1+ = Optional string
%imacro asciz 0-1+.nolist
%if %0 >= 1
db %1
%endif
db 0
%endmacro
%assign _AUXBUFFSIZE 8192
cpu 386
org 100h
bits 16
start:
pop ax ; get word saved on stack for COM files
mov bx, sp
shr bx, 4
jnz .smallstack
mov bx, 1000h ; it was a full 64 KiB stack
.smallstack:
mov ah, 4Ah ; free unused memory
int 21h
xor ax, ax
xchg ax, word [2Ch]
mov es, ax
mov ah, 49h
int 21h ; free environment if any
mov word [pspdbg], cs
mov ax, 1687h
int 2Fh
or ax, ax ; DPMI host installed?
jnz nohost
push es ; save DPMI entry address
push di
or 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:
mov si, msg.debuginfo
call printstring
int3
mov bp, sp
mov ax, 0001h ; start a 32-bit client
call far [bp] ; initial switch to protected-mode
jnc initsuccessful
initfailed:
mov si, msg.initfailed
jmp short rmerror
nohost:
mov si, msg.nohost
jmp short rmerror
nomemory:
mov si, msg.nomemory
rmerror:
call printstring
mov ax, 4CFFh
int 21h
initsuccessful:
initsuccessful_ofs equ (initsuccessful-$$+100h)
; now in protected mode
mov word [ data.pspsel ], es
push ds
pop es
mov si, msg.welcome
call printstring
mov word [code_sel], cs
mov word [dssel], ds
xor edi, edi
mov ax, 0305h ; get raw mode-switch save state addresses
int 31h
jc .cannotswitch
cmp ax, _AUXBUFFSIZE ; fits into auxbuff ?
ja .cannotswitch ; no -->
test ax, ax
jz .nobuffer
mov word [dpmi_rmsav+0], cx
mov word [dpmi_rmsav+2], bx
mov dword [dpmi_pmsav], edi
mov word [dpmi_pmsav+4], si
jmp .gotbuffer
.nobuffer:
mov word [dpmi_rmsav+0], ..@retf
push word [pspdbg]
pop word [dpmi_rmsav+2]
mov dword [dpmi_pmsav+0], ..@retf
mov word [dpmi_pmsav+4], cs
.gotbuffer:
xor edi, edi ; clear edih
mov ax, 0306h ; get raw mode-switch addresses
int 31h
jc .cannotswitch
mov word [dpmi_rm2pm+0], cx
mov word [dpmi_rm2pm+2], bx
mov dword [dpmi_pm2rm], edi
mov word [dpmi_pm2rm+4], si
mov al, 0
call sr_state_pm
call switchmode_pm2rm
mov si, msg.rm
call printstring
call switchmode_rm2pm
mov al, 1
call sr_state_pm
mov si, msg.pmagain
call printstring
.cannotswitch:
mov ax, 4C00h
int 21h ; normal client exit (terminates DOS process too)
..@retf:
retf
switchmode_pm2rm:
;--- raw switch:
;--- si:e/di: new cs:e/ip
;--- dx:e/bx: new ss:e/sp
;--- ax: new ds
;--- cx: new es
xor ebx, ebx ; clear ebxh
mov bx, sp
xor edi, edi ; clear edih
mov di, .back_after_switch
mov ax, [pspdbg] ; switch pm -> rm
mov si, ax
mov dx, ax
mov cx, ax
jmp far dword [dpmi_pm2rm]
.back_after_switch:
retn
switchmode_rm2pm:
xor ebx, ebx ; clear ebxh
mov bx, sp
xor edi, edi ; clear edih
mov di, .back_after_switch
mov ax, [dssel] ; switch rm -> pm
mov si, [code_sel]
mov dx, ax
mov cx, ax
jmp far [dpmi_rm2pm]
.back_after_switch:
retn
sr_state_rm:
mov edi, auxbuff
push ds
pop es
call far [dpmi_rmsav]
retn
sr_state_pm:
mov edi, auxbuff
push ds
pop es
call far dword [dpmi_pmsav]
retn
; Print a string with simple instructions. Don't use
; pointers or instructions depending on the default operation
; size, this is called in both 16- and 32-bit modes.
printstring.next:
mov dl, al
mov ah, 2
int 21h
printstring:
lodsb
or al, al
jnz .next
retn
align 4
data:
.pspsel: dw 0
dssel: dw 0
code_sel: dw 0
pspdbg: dw 0
dpmi_rm2pm: dd 0
dpmi_rmsav: dd 0
dpmi_pm2rm: times 3 dw 0
dpmi_pmsav: times 3 dw 0
align 16
auxbuff: times _AUXBUFFSIZE db 0
msg:
.nohost: asciz "No DPMI host installed.",13,10
.nomemory: asciz "Not enough DOS memory for child process creation or client initialization.",13,10
.initfailed: asciz "DPMI initialization failed.",13,10
.debuginfo: db "Protected mode breakpoint at ",_4digitshex(initsuccessful_ofs),"h.",13,10
asciz 13,10
.welcome: asciz "Welcome in protected mode.",13,10
.rm: asciz "Mode-switched to real mode.",13,10
.pmagain: asciz "In protected mode again.",13,10