New upstream version 2.0pre9.2
This commit is contained in:
5
test/ecm/dpmitest/Makefile
Normal file
5
test/ecm/dpmitest/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
all: dpmialoc.com dpmimini.com dpmims.com dpmipsp.com
|
||||
|
||||
%.com: %.asm
|
||||
nasm -f bin -I../lmacros/ -o $@ $<
|
||||
595
test/ecm/dpmitest/dpmialoc.asm
Normal file
595
test/ecm/dpmitest/dpmialoc.asm
Normal file
@@ -0,0 +1,595 @@
|
||||
|
||||
%if 0
|
||||
|
||||
Example of an application running in DPMI-allocated memory
|
||||
Public Domain
|
||||
|
||||
%endif
|
||||
|
||||
%include "lmacros3.mac"
|
||||
|
||||
|
||||
cpu 386
|
||||
org 100h
|
||||
addsection R86M_MEM_SECTION, start=100h
|
||||
addsection DPMI_MEM_SECTION, vstart=0 follows=R86M_MEM_SECTION align=16
|
||||
|
||||
usesection R86M_MEM_SECTION
|
||||
bits 16
|
||||
r86m_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 bx, 80h >> 4
|
||||
mov ah, 48h
|
||||
int 21h ; allocate memory for child process
|
||||
jc nomemory
|
||||
|
||||
; ax:0-> DOS memory allocated for child process
|
||||
mov es, ax
|
||||
xor di, di ; es:di->
|
||||
xor si, si ; cs:si = ds:si -> our PSP
|
||||
mov cx, 128 >> 1 ; PSP size
|
||||
rep movsw ; copy process segment prefix into newly allocated block
|
||||
dec ax
|
||||
mov ds, ax ; ds = MCB of allocated block
|
||||
inc ax ; ax = allocated block!
|
||||
mov word [ 8 ], "DP"
|
||||
mov word [ 8+2 ], "MI"
|
||||
mov word [ 8+4 ], "PS"
|
||||
mov word [ 8+6 ], "PC" ; Force MCB string to "DPMIPSPC"
|
||||
; mov word [ 1 ], ax ; Set owner to itself
|
||||
; (leave owner as us)
|
||||
|
||||
mov es, ax ; es = new PSP
|
||||
mov dx, cs
|
||||
mov ds, dx ; ds = old PSP
|
||||
mov di, 18h
|
||||
mov cx, 20
|
||||
mov word [ es:32h ], cx
|
||||
mov word [ es:34h ], di
|
||||
mov word [ es:34h+2 ], ax ; fix the new PSP's PHT pointer
|
||||
mov word [ es:0Ah ], childterminated
|
||||
mov word [ es:0Ah+2 ], dx ; set termination address
|
||||
mov word [ es:16h ], dx ; set parent PSP to current one
|
||||
|
||||
; The stack address set on the child's termination
|
||||
; is that of the last Int21 call to a usual function
|
||||
; (such as Int21.48 or .45) from the parent process.
|
||||
; All registers will be lost though, because we don't
|
||||
; build a fake stack frame.
|
||||
|
||||
push di
|
||||
mov al, -1
|
||||
rep stosb ; initialize new PHT with empty entries
|
||||
pop di
|
||||
mov cx, word [ 32h ] ; = number of current process handles
|
||||
jcxz .phtdone ; (weird, but handle this correctly)
|
||||
cmp cx, 20
|
||||
jbe .normalpht
|
||||
mov cx, 20
|
||||
.normalpht:
|
||||
lds si, [ 34h ] ; -> current process handle table
|
||||
xor bx, bx
|
||||
.phtloop:
|
||||
mov dl, -1
|
||||
cmp byte [si+bx], dl ; source PHT handle used?
|
||||
je .phtnext ; no -->
|
||||
mov ah, 45h
|
||||
int 21h ; DUP
|
||||
jc nohandle
|
||||
xchg ax, bx
|
||||
xchg dl, byte [si+bx] ; get DUPed handle and kill PHT entry
|
||||
xchg ax, bx
|
||||
mov byte [es:di+bx], dl ; write into PHT of new process
|
||||
.phtnext:
|
||||
inc bx ; next handle
|
||||
loop .phtloop
|
||||
.phtdone:
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov bx, es
|
||||
mov ah, 50h
|
||||
int 21h ; set current PSP to new
|
||||
; mov ah, 1Ah
|
||||
; mov ds,
|
||||
; mov dx, 80h
|
||||
; int 21h ; set DTA
|
||||
|
||||
; Now executing in the child process's environment.
|
||||
; Terminating will return to label childterminated.
|
||||
|
||||
mov ax, cs
|
||||
mov word [rmcallstruc0.cs], ax
|
||||
mov word [rmcallstruc0.ds], ax
|
||||
mov word [rmcallstruc0.es], ax
|
||||
mov word [rmcallstruc0.ss], ax
|
||||
pushf
|
||||
pop word [rmcallstruc0.flags] ; setup with RM values
|
||||
|
||||
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 ; alloc DOS memory
|
||||
int 21h
|
||||
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
|
||||
nohandle:
|
||||
cmp cx, 20
|
||||
je .no_handles_duplicated_yet
|
||||
; In this case, there may be some already duplicated
|
||||
; file handles. Switch to the child process and then
|
||||
; terminate it, in order to close the handles.
|
||||
mov word [ es:0Ah ], .half_initialised_child_terminated
|
||||
; set Parent Return Address to ours
|
||||
mov bx, es
|
||||
mov ah, 50h
|
||||
int 21h
|
||||
mov ax, 4C00h
|
||||
int 21h
|
||||
|
||||
.half_initialised_child_terminated:
|
||||
cld
|
||||
.no_handles_duplicated_yet:
|
||||
push cs
|
||||
pop ds
|
||||
mov si, msg.nohandle
|
||||
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 bx, cs
|
||||
mov cx, cs
|
||||
lar cx, cx
|
||||
shr cx, 8
|
||||
or ch, 40h ; make a 32-bit cs
|
||||
mov ax, 9
|
||||
int 31h
|
||||
; now in 32-bit PM
|
||||
bits 32
|
||||
now32bit:
|
||||
now32bit_ofs equ (now32bit-$$+100h)
|
||||
mov word [ data.pspsel ], es
|
||||
push ds
|
||||
pop es
|
||||
|
||||
mov esi, msg.welcome
|
||||
call printstring
|
||||
|
||||
mov [r86m_end + dpmi_to_r86m_code_sel - dpmi_start], cs
|
||||
mov [r86m_end + dpmi_to_r86m_data_sel - dpmi_start], ds
|
||||
|
||||
xor eax, eax
|
||||
mov cx, 2
|
||||
int 31h ; allocate 2 selectors
|
||||
jc @F
|
||||
xchg eax, ebx
|
||||
|
||||
mov eax, 3
|
||||
int 31h
|
||||
jc @F
|
||||
|
||||
mov dword [r86m_end + dpmi_dpmi_code_sel - dpmi_start], ebx
|
||||
push ebx
|
||||
add ebx, eax
|
||||
mov dword [r86m_end + dpmi_dpmi_data_sel - dpmi_start], ebx
|
||||
mov ax, 8
|
||||
or ecx, -1
|
||||
mov edx, ecx
|
||||
int 31h ; set limit to -1
|
||||
pop ebx
|
||||
jc @F
|
||||
|
||||
mov ax, 8
|
||||
int 31h ; set limit to -1
|
||||
jc @F
|
||||
|
||||
mov ax, 9
|
||||
mov cx, 1100_1111_1_11_1_1011b
|
||||
int 31h ; set to 32-bit readable code segment
|
||||
jc @F
|
||||
|
||||
mov ax, 0501h
|
||||
mov bx, (dpmi_end - dpmi_start) >> 16
|
||||
mov cx, (dpmi_end - dpmi_start) & 0FFFFh
|
||||
int 31h
|
||||
jc @F
|
||||
|
||||
push bx
|
||||
push cx
|
||||
pop dword [data.dpmi_block_address]
|
||||
push si
|
||||
push di
|
||||
pop dword [data.dpmi_block_handle]
|
||||
|
||||
mov ebx, dword [r86m_end + dpmi_dpmi_data_sel - dpmi_start]
|
||||
mov edx, dword [data.dpmi_block_address]
|
||||
mov ecx, dword [data.dpmi_block_address + 2]
|
||||
mov ax, 7
|
||||
int 31h
|
||||
jc @F
|
||||
|
||||
push ecx
|
||||
mov es, ebx
|
||||
xor edi, edi
|
||||
mov esi, r86m_end
|
||||
mov ecx, dwords(dpmi_end - dpmi_start)
|
||||
rep movsd
|
||||
pop ecx
|
||||
|
||||
mov ebx, dword [r86m_end + dpmi_dpmi_code_sel - dpmi_start]
|
||||
mov ax, 7
|
||||
int 31h
|
||||
jc @F
|
||||
|
||||
mov esi, msg.info2.1
|
||||
call printstring
|
||||
mov eax, dword [data.dpmi_block_address]
|
||||
call disp_eax_hex
|
||||
mov esi, msg.info2.2
|
||||
call printstring
|
||||
mov eax, ebx
|
||||
call disp_ax_hex
|
||||
mov esi, msg.info2.3
|
||||
call printstring
|
||||
mov eax, ebx
|
||||
call disp_ax_hex
|
||||
mov esi, msg.info2.4
|
||||
call printstring
|
||||
mov eax, ebx
|
||||
call disp_ax_hex
|
||||
mov esi, msg.info2.5
|
||||
call printstring
|
||||
|
||||
int3
|
||||
push ebx
|
||||
push dpmi_start
|
||||
retf
|
||||
|
||||
@@:
|
||||
push ss
|
||||
pop ds
|
||||
mov esi, msg.error
|
||||
call printstring
|
||||
or eax, -1
|
||||
|
||||
pmend:
|
||||
push ss
|
||||
pop ds
|
||||
push eax
|
||||
mov ebx, dword [r86m_end + dpmi_dpmi_code_sel - dpmi_start]
|
||||
mov ax, 1
|
||||
int 31h
|
||||
mov ebx, dword [r86m_end + dpmi_dpmi_data_sel - dpmi_start]
|
||||
mov ax, 1
|
||||
int 31h
|
||||
mov edi, dword [data.dpmi_block_handle]
|
||||
mov esi, dword [data.dpmi_block_handle + 2]
|
||||
cmp edi, -1
|
||||
je @F
|
||||
mov ax, 0502h
|
||||
int 31h
|
||||
@@:
|
||||
pop eax
|
||||
mov ah, 4Ch ; normal client exit
|
||||
int 21h
|
||||
|
||||
disp_eax_hex:
|
||||
rol eax, 16
|
||||
call disp_ax_hex
|
||||
rol eax, 16
|
||||
disp_ax_hex:
|
||||
xchg al, ah
|
||||
call disp_al_hex
|
||||
xchg al, ah
|
||||
disp_al_hex:
|
||||
rol al, 4
|
||||
call disp_al_nybble_hex
|
||||
rol al, 4
|
||||
disp_al_nybble_hex:
|
||||
push eax
|
||||
and al, 0Fh
|
||||
add al, '0'
|
||||
cmp al, '9'
|
||||
jbe @F
|
||||
add al, -'9' -1 +'A'
|
||||
@@:
|
||||
call disp_al
|
||||
pop eax
|
||||
retn
|
||||
|
||||
disp_al:
|
||||
push edx
|
||||
push eax
|
||||
mov dl, al
|
||||
mov ah, 2
|
||||
int 21h
|
||||
pop eax
|
||||
pop edx
|
||||
retn
|
||||
|
||||
|
||||
bits 16
|
||||
|
||||
callrm:
|
||||
; int3 ; int 03h or int3 traps (in real or V86 mode) don't cause any problems.
|
||||
int strict byte 03h
|
||||
xor ax, ax
|
||||
push ax
|
||||
push ax
|
||||
call -1:-1
|
||||
.callback equ $-4
|
||||
pop ax
|
||||
pop ax
|
||||
; int3
|
||||
int strict byte 03h
|
||||
iret
|
||||
|
||||
|
||||
; 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
|
||||
test al, al
|
||||
jnz .next
|
||||
retn
|
||||
|
||||
|
||||
; The (DPMIed) child process has terminated.
|
||||
childterminated:
|
||||
childterminated_ofs equ (childterminated-$$+100h)
|
||||
cld
|
||||
push cs
|
||||
pop ds
|
||||
mov ah, 4Dh
|
||||
int 21h
|
||||
mov si, msg.backsuccess
|
||||
test al, al
|
||||
jz .success
|
||||
mov si, msg.backerror
|
||||
.success:
|
||||
call printstring
|
||||
mov ax, 4C00h
|
||||
int 21h ; terminate DOS process
|
||||
|
||||
|
||||
align 4
|
||||
data:
|
||||
.dpmi_block_address: dd 0
|
||||
.dpmi_block_handle: dd -1
|
||||
.pspsel: dw 0
|
||||
|
||||
align 4
|
||||
; This one is used to call down to our RM part
|
||||
; from the 32-bit PM code. All values are filled
|
||||
; in either here or in our RM initialization.
|
||||
rmcallstruc0:
|
||||
.edi: dd 0
|
||||
.esi: dd 0
|
||||
.ebp: dd 0
|
||||
dd 0
|
||||
.ebx: dd 0
|
||||
.edx: dd 0
|
||||
.ecx: dd 0
|
||||
.eax: dd 0
|
||||
.flags: dw 0
|
||||
.es: dw 0
|
||||
.ds: dw 0
|
||||
.fs: dw 0
|
||||
.gs: dw 0
|
||||
.ip: dw callrm
|
||||
.cs: dw 0
|
||||
.sp: dw rmcallsp
|
||||
.ss: dw 0
|
||||
|
||||
align 4
|
||||
; This one is utilized by the DPMI host and
|
||||
; our RM callback when called from RM. All
|
||||
; values are filled in by the DPMI host.
|
||||
rmcallstruc1:
|
||||
.edi: dd 0
|
||||
.esi: dd 0
|
||||
.ebp: dd 0
|
||||
dd 0
|
||||
.ebx: dd 0
|
||||
.edx: dd 0
|
||||
.ecx: dd 0
|
||||
.eax: dd 0
|
||||
.flags: dw 0
|
||||
.es: dw 0
|
||||
.ds: dw 0
|
||||
.fs: dw 0
|
||||
.gs: dw 0
|
||||
.ip: dw 0
|
||||
.cs: dw 0
|
||||
.sp: dw 0
|
||||
.ss: dw 0
|
||||
|
||||
msg:
|
||||
.backsuccess: asciz "Child process terminated okay, back in real mode.",13,10
|
||||
.backerror: asciz "Child process terminated with error, back in real mode.",13,10
|
||||
.error: asciz "Error during allocation setup.",13,10
|
||||
.info2.1: asciz "DPMI allocation at "
|
||||
.info2.2: asciz "h.",13,10,"DPMI allocation entrypoint at "
|
||||
.info2.3: db "h:00000000h.",13,10
|
||||
asciz "Real mode procedure called at "
|
||||
.info2.4: db "h:",_8digitshex(dpmi_start.callingrm - dpmi_start),"h.",13,10
|
||||
asciz "DPMI allocation exit at "
|
||||
.info2.5: asciz "h:",_8digitshex(dpmi_start.return - dpmi_start),"h.",13,10
|
||||
|
||||
.nohost: asciz "No DPMI host installed.",13,10
|
||||
.nohandle: asciz "No free DOS file handle for child process creation.",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
|
||||
db "32-bit code segment breakpoint at ",_4digitshex(now32bit_ofs),"h.",13,10
|
||||
db "Return from child process at ",_4digitshex(childterminated_ofs),"h.",13,10
|
||||
asciz 13,10
|
||||
.welcome: asciz "Welcome in 32-bit protected mode.",13,10
|
||||
|
||||
align 16
|
||||
times 256 db 26h
|
||||
align 2
|
||||
rmcallsp:
|
||||
|
||||
align 16
|
||||
r86m_end:
|
||||
usesection DPMI_MEM_SECTION
|
||||
bits 32
|
||||
dpmi_start:
|
||||
nop
|
||||
mov ds, [cs:dpmi_dpmi_data_sel]
|
||||
mov esi, dpmi_msg.hello
|
||||
call dpmi_printstring
|
||||
|
||||
mov ax, 0303h
|
||||
push cs
|
||||
pop ds
|
||||
mov esi, dpmi_callback ; ds:esi-> called procedure
|
||||
push ss
|
||||
pop es
|
||||
mov edi, rmcallstruc1 ; es:edi-> (inreentrant) real mode call structure
|
||||
int 31h ; allocate RM callback
|
||||
push ss
|
||||
pop ds
|
||||
jc .nocallback
|
||||
mov dword [callrm.callback], edx
|
||||
mov word [callrm.callback+2], cx
|
||||
|
||||
mov ax, 0302h
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
mov edi, rmcallstruc0
|
||||
.callingrm:
|
||||
int 31h ; call RM procedure with interrupt stack
|
||||
nop
|
||||
jc .callrmfailed
|
||||
|
||||
mov ecx, dword [callrm.callback+2]
|
||||
mov edx, dword [callrm.callback]
|
||||
mov ax, 0304h
|
||||
int 31h ; free RM callback
|
||||
mov ds, [cs:dpmi_dpmi_data_sel]
|
||||
mov esi, dpmi_msg.bye
|
||||
call dpmi_printstring
|
||||
.return:
|
||||
nop
|
||||
xor eax, eax
|
||||
.ret_al:
|
||||
jmp far [cs:dpmi_return_address]
|
||||
|
||||
|
||||
.callrmfailed:
|
||||
mov esi, dpmi_msg.callrmfailed
|
||||
jmp short @F
|
||||
.nocallback:
|
||||
mov esi, dpmi_msg.nocallback
|
||||
@@:
|
||||
push cs
|
||||
pop ds
|
||||
call dpmi_printstring
|
||||
push ss
|
||||
pop ds
|
||||
movzx ecx, word [callrm.callback+2]
|
||||
movzx edx, word [callrm.callback]
|
||||
mov eax, edx
|
||||
and eax, ecx
|
||||
inc ax
|
||||
jnz @F
|
||||
mov ax, 0304h
|
||||
int 31h ; free RM callback
|
||||
@@:
|
||||
or eax, -1
|
||||
jmp .ret_al
|
||||
|
||||
|
||||
; This is a RM callback. Called from RM, executed in PM.
|
||||
;
|
||||
; INP: es:edi-> RM call structure
|
||||
; ds:esi-> RM stack
|
||||
; ss:esp-> DPMI host internal stack
|
||||
; CHG: all (?) except es:edi
|
||||
; read/write RM call structure to communicate with RM code
|
||||
dpmi_callback:
|
||||
push dword [esi]
|
||||
pop dword [es:edi+2Ah] ; set RM cs:ip
|
||||
add word [es:edi+2Eh], byte 4 ; pop 4 byte from the stack
|
||||
int strict byte 03h
|
||||
nop
|
||||
int3
|
||||
nop
|
||||
iret
|
||||
|
||||
|
||||
; Print a string with simple instructions.
|
||||
dpmi_printstring.next:
|
||||
mov dl, al
|
||||
mov ah, 2
|
||||
int 21h
|
||||
dpmi_printstring:
|
||||
lodsb
|
||||
test al, al
|
||||
jnz .next
|
||||
retn
|
||||
|
||||
|
||||
dpmi_msg:
|
||||
.hello: asciz "Hello from DPMI memory section!",13,10
|
||||
.nocallback: asciz "Could not allocate real mode callback.",13,10
|
||||
.callrmfailed: asciz "Calling real mode procedure failed.",13,10
|
||||
.bye: asciz "Calling real mode procedure which called callback successful.",13,10
|
||||
|
||||
|
||||
align 4
|
||||
dpmi_return_address: dd pmend
|
||||
dpmi_to_r86m_code_sel: dd 0
|
||||
dpmi_to_r86m_data_sel: dd 0
|
||||
dpmi_dpmi_code_sel: dd 0
|
||||
dpmi_dpmi_data_sel: dd 0
|
||||
|
||||
align 16
|
||||
dpmi_end:
|
||||
125
test/ecm/dpmitest/dpmimini.asm
Normal file
125
test/ecm/dpmitest/dpmimini.asm
Normal file
@@ -0,0 +1,125 @@
|
||||
|
||||
%if 0
|
||||
|
||||
Example of entering 32-bit protected mode using DPMI
|
||||
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
|
||||
|
||||
|
||||
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 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 bx, cs
|
||||
mov cx, cs
|
||||
lar cx, cx
|
||||
shr cx, 8
|
||||
or ch, 40h ; make a 32-bit cs
|
||||
mov ax, 9
|
||||
int 31h
|
||||
; now in 32-bit PM
|
||||
bits 32
|
||||
now32bit:
|
||||
now32bit_ofs equ (now32bit-$$+100h)
|
||||
mov word [ data.pspsel ], es
|
||||
push ds
|
||||
pop es
|
||||
|
||||
mov esi, msg.welcome
|
||||
call printstring
|
||||
|
||||
mov ax, 4C00h
|
||||
int 21h ; normal client exit (terminates DOS process too)
|
||||
|
||||
; 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 2
|
||||
data:
|
||||
.pspsel: dw 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
|
||||
db "32-bit code segment breakpoint at ",_4digitshex(now32bit_ofs),"h.",13,10
|
||||
asciz 13,10
|
||||
.welcome: asciz "Welcome in 32-bit protected mode.",13,10
|
||||
235
test/ecm/dpmitest/dpmims.asm
Normal file
235
test/ecm/dpmitest/dpmims.asm
Normal file
@@ -0,0 +1,235 @@
|
||||
|
||||
%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
|
||||
393
test/ecm/dpmitest/dpmipsp.asm
Normal file
393
test/ecm/dpmitest/dpmipsp.asm
Normal file
@@ -0,0 +1,393 @@
|
||||
|
||||
%if 0
|
||||
|
||||
Example of a DPMI fake child process returning
|
||||
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
|
||||
|
||||
|
||||
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 bx, 80h >> 4
|
||||
mov ah, 48h
|
||||
int 21h ; allocate memory for child process
|
||||
jc nomemory
|
||||
|
||||
; ax:0-> DOS memory allocated for child process
|
||||
mov es, ax
|
||||
xor di, di ; es:di->
|
||||
xor si, si ; cs:si = ds:si -> our PSP
|
||||
mov cx, 128 >> 1 ; PSP size
|
||||
rep movsw ; copy process segment prefix into newly allocated block
|
||||
dec ax
|
||||
mov ds, ax ; ds = MCB of allocated block
|
||||
inc ax ; ax = allocated block!
|
||||
mov word [ 8 ], "DP"
|
||||
mov word [ 8+2 ], "MI"
|
||||
mov word [ 8+4 ], "PS"
|
||||
mov word [ 8+6 ], "PC" ; Force MCB string to "DPMIPSPC"
|
||||
; mov word [ 1 ], ax ; Set owner to itself
|
||||
; (leave owner as us)
|
||||
|
||||
mov es, ax ; es = new PSP
|
||||
mov dx, cs
|
||||
mov ds, dx ; ds = old PSP
|
||||
mov di, 18h
|
||||
mov cx, 20
|
||||
mov word [ es:32h ], cx
|
||||
mov word [ es:34h ], di
|
||||
mov word [ es:34h+2 ], ax ; fix the new PSP's PHT pointer
|
||||
mov word [ es:0Ah ], childterminated
|
||||
mov word [ es:0Ah+2 ], dx ; set termination address
|
||||
mov word [ es:16h ], dx ; set parent PSP to current one
|
||||
|
||||
; The stack address set on the child's termination
|
||||
; is that of the last Int21 call to a usual function
|
||||
; (such as Int21.48 or .45) from the parent process.
|
||||
; All registers will be lost though, because we don't
|
||||
; build a fake stack frame.
|
||||
|
||||
push di
|
||||
mov al, -1
|
||||
rep stosb ; initialize new PHT with empty entries
|
||||
pop di
|
||||
mov cx, word [ 32h ] ; = number of current process handles
|
||||
jcxz .phtdone ; (weird, but handle this correctly)
|
||||
cmp cx, 20
|
||||
jbe .normalpht
|
||||
mov cx, 20
|
||||
.normalpht:
|
||||
lds si, [ 34h ] ; -> current process handle table
|
||||
xor bx, bx
|
||||
.phtloop:
|
||||
mov dl, -1
|
||||
cmp byte [si+bx], dl ; source PHT handle used?
|
||||
je .phtnext ; no -->
|
||||
mov ah, 45h
|
||||
int 21h ; DUP
|
||||
jc nohandle
|
||||
xchg ax, bx
|
||||
xchg dl, byte [si+bx] ; get DUPed handle and kill PHT entry
|
||||
xchg ax, bx
|
||||
mov byte [es:di+bx], dl ; write into PHT of new process
|
||||
.phtnext:
|
||||
inc bx ; next handle
|
||||
loop .phtloop
|
||||
.phtdone:
|
||||
push cs
|
||||
pop ds
|
||||
|
||||
mov bx, es
|
||||
mov ah, 50h
|
||||
int 21h ; set current PSP to new
|
||||
; mov ah, 1Ah
|
||||
; mov ds,
|
||||
; mov dx, 80h
|
||||
; int 21h ; set DTA
|
||||
|
||||
; Now executing in the child process's environment.
|
||||
; Terminating will return to label childterminated.
|
||||
|
||||
mov ax, cs
|
||||
mov word [rmcallstruc0.cs], ax
|
||||
mov word [rmcallstruc0.ds], ax
|
||||
mov word [rmcallstruc0.es], ax
|
||||
mov word [rmcallstruc0.ss], ax
|
||||
pushf
|
||||
pop word [rmcallstruc0.flags] ; setup with RM values
|
||||
|
||||
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 ; alloc DOS memory
|
||||
int 21h
|
||||
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
|
||||
nohandle:
|
||||
cmp cx, 20
|
||||
je .no_handles_duplicated_yet
|
||||
; In this case, there may be some already duplicated
|
||||
; file handles. Switch to the child process and then
|
||||
; terminate it, in order to close the handles.
|
||||
mov word [ es:0Ah ], .half_initialised_child_terminated
|
||||
; set Parent Return Address to ours
|
||||
mov bx, es
|
||||
mov ah, 50h
|
||||
int 21h
|
||||
mov ax, 4C00h
|
||||
int 21h
|
||||
|
||||
.half_initialised_child_terminated:
|
||||
cld
|
||||
.no_handles_duplicated_yet:
|
||||
push cs
|
||||
pop ds
|
||||
mov si, msg.nohandle
|
||||
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 bx, cs
|
||||
mov cx, cs
|
||||
lar cx, cx
|
||||
shr cx, 8
|
||||
or ch, 40h ; make a 32-bit cs
|
||||
mov ax, 9
|
||||
int 31h
|
||||
; now in 32-bit PM
|
||||
bits 32
|
||||
now32bit:
|
||||
now32bit_ofs equ (now32bit-$$+100h)
|
||||
mov word [ data.pspsel ], es
|
||||
push ds
|
||||
pop es
|
||||
|
||||
mov esi, msg.welcome
|
||||
call printstring
|
||||
|
||||
mov ax, 0303h
|
||||
push cs
|
||||
pop ds
|
||||
mov esi, callback ; ds:esi-> called procedure
|
||||
mov edi, rmcallstruc1 ; es:edi-> (inreentrant) real mode call structure
|
||||
int 31h ; allocate RM callback
|
||||
push ss
|
||||
pop ds
|
||||
jc nocallback
|
||||
mov dword [callrm.callback], edx
|
||||
mov word [callrm.callback+2], cx
|
||||
|
||||
mov ax, 0302h
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
mov edi, rmcallstruc0
|
||||
callingrm:
|
||||
callingrm_ofs equ (callingrm-$$+100h)
|
||||
int 31h ; call RM procedure with interrupt stack
|
||||
jc callrmfailed
|
||||
|
||||
mov ecx, dword [callrm.callback+2]
|
||||
mov edx, dword [callrm.callback]
|
||||
mov ax, 0304h
|
||||
int 31h ; free RM callback
|
||||
mov esi, msg.bye
|
||||
call printstring
|
||||
mov ax, 4C00h ; normal client exit
|
||||
int 21h
|
||||
|
||||
callrmfailed:
|
||||
mov esi, msg.callrmfailed
|
||||
jmp short pmerror
|
||||
nocallback:
|
||||
mov esi, msg.nocallback
|
||||
pmerror:
|
||||
call printstring
|
||||
movzx ecx, word [callrm.callback+2]
|
||||
movzx edx, word [callrm.callback]
|
||||
mov eax, edx
|
||||
and eax, ecx
|
||||
inc ax
|
||||
jnz .done
|
||||
mov ax, 0304h
|
||||
int 31h ; free RM callback
|
||||
.done:
|
||||
mov ax, 4CFFh
|
||||
int 21h
|
||||
|
||||
; This is a RM callback. Called from RM, executed in PM.
|
||||
;
|
||||
; INP: es:edi-> RM call structure
|
||||
; ds:esi-> RM stack
|
||||
; ss:esp-> DPMI host internal stack
|
||||
; CHG: all (?) except es:edi
|
||||
; read/write RM call structure to communicate with RM code
|
||||
callback:
|
||||
push dword [esi]
|
||||
pop dword [es:edi+2Ah] ; set RM cs:ip
|
||||
add word [es:edi+2Eh], byte 4 ; pop 4 byte from the stack
|
||||
; The int3 trap used not to work here in the then-current
|
||||
; lDebugX development version. int 03h however did. Note that
|
||||
; both might crash the DPMI host if no debugger is installed.
|
||||
int strict byte 03h
|
||||
nop
|
||||
int3
|
||||
nop
|
||||
iret
|
||||
|
||||
bits 16
|
||||
|
||||
callrm:
|
||||
; int3 ; int 03h or int3 traps (in real or V86 mode) don't cause any problems.
|
||||
int strict byte 03h
|
||||
xor ax, ax
|
||||
push ax
|
||||
push ax
|
||||
call -1:-1
|
||||
.callback equ $-4
|
||||
pop ax
|
||||
pop ax
|
||||
; int3
|
||||
int strict byte 03h
|
||||
iret
|
||||
|
||||
|
||||
; 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
|
||||
test al, al
|
||||
jnz .next
|
||||
retn
|
||||
|
||||
|
||||
; The (DPMIed) child process has terminated.
|
||||
childterminated:
|
||||
childterminated_ofs equ (childterminated-$$+100h)
|
||||
cld
|
||||
push cs
|
||||
pop ds
|
||||
mov ah, 4Dh
|
||||
int 21h
|
||||
mov si, msg.backsuccess
|
||||
test al, al
|
||||
jz .success
|
||||
mov si, msg.backerror
|
||||
.success:
|
||||
call printstring
|
||||
mov ax, 4C00h
|
||||
int 21h ; terminate DOS process
|
||||
|
||||
|
||||
align 2
|
||||
data:
|
||||
.pspsel: dw 0
|
||||
|
||||
align 4
|
||||
; This one is used to call down to our RM part
|
||||
; from the 32-bit PM code. All values are filled
|
||||
; in either here or in our RM initialization.
|
||||
rmcallstruc0:
|
||||
.edi: dd 0
|
||||
.esi: dd 0
|
||||
.ebp: dd 0
|
||||
dd 0
|
||||
.ebx: dd 0
|
||||
.edx: dd 0
|
||||
.ecx: dd 0
|
||||
.eax: dd 0
|
||||
.flags: dw 0
|
||||
.es: dw 0
|
||||
.ds: dw 0
|
||||
.fs: dw 0
|
||||
.gs: dw 0
|
||||
.ip: dw callrm
|
||||
.cs: dw 0
|
||||
.sp: dw rmcallsp
|
||||
.ss: dw 0
|
||||
|
||||
align 4
|
||||
; This one is utilized by the DPMI host and
|
||||
; our RM callback when called from RM. All
|
||||
; values are filled in by the DPMI host.
|
||||
rmcallstruc1:
|
||||
.edi: dd 0
|
||||
.esi: dd 0
|
||||
.ebp: dd 0
|
||||
dd 0
|
||||
.ebx: dd 0
|
||||
.edx: dd 0
|
||||
.ecx: dd 0
|
||||
.eax: dd 0
|
||||
.flags: dw 0
|
||||
.es: dw 0
|
||||
.ds: dw 0
|
||||
.fs: dw 0
|
||||
.gs: dw 0
|
||||
.ip: dw 0
|
||||
.cs: dw 0
|
||||
.sp: dw 0
|
||||
.ss: dw 0
|
||||
|
||||
msg:
|
||||
.callrmfailed: asciz "Calling real mode procedure failed.",13,10
|
||||
.bye: asciz "Calling real mode procedure which called callback successful.",13,10
|
||||
.backsuccess: asciz "Child process terminated okay, back in real mode.",13,10
|
||||
.backerror: asciz "Child process terminated with error, back in real mode.",13,10
|
||||
.nocallback: asciz "Could not allocate real mode callback.",13,10
|
||||
.nohost: asciz "No DPMI host installed.",13,10
|
||||
.nohandle: asciz "No free DOS file handle for child process creation.",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
|
||||
db "32-bit code segment breakpoint at ",_4digitshex(now32bit_ofs),"h.",13,10
|
||||
db "Real mode procedure called at ",_4digitshex(callingrm_ofs),"h.",13,10
|
||||
db "Return from child process at ",_4digitshex(childterminated_ofs),"h.",13,10
|
||||
asciz 13,10
|
||||
.welcome: asciz "Welcome in 32-bit protected mode.",13,10
|
||||
|
||||
align 2
|
||||
rmcallsp:
|
||||
Reference in New Issue
Block a user