%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