Laaca
Czech republic, 13.08.2010, 10:36 |
With DPMI into protect mode and back (Developers) |
I have a 16 bit realmode program. It would be nice for it to add possibility for writing a info about installed DPMI manager. But the problem is than I can't call the INT31h interrupts from real mode (nor from VM86 mode).
If I understand the documentation correct, I can switch into protect mode by calling address provided in INT2Fh/AX=1687h but there is no transparent way how to get back into real (VM86) mode.
The only way is just to terminate the application. But I don't want to terminate it. Maybe is possible to run some child process but I don't want to call any external EXE file.
So,
Japheth (or anybode else),
could you write for our, dummies, some example program which starts in real mode, somewhat switch into protect, writes some info about DPMI environment, switch back into real, writes "still alive" and only after it ends? --- DOS-u-akbar! |
ecm
Düsseldorf, Germany, 13.08.2010, 14:30 (edited by cm, 13.08.2010, 14:57)
@ Laaca
|
With DPMI into protect mode and back - EDIT: example |
> If I understand the documentation correct, I can switch into protect mode
> by calling address provided in INT2Fh/AX=1687h but there is no transparent
> way how to get back into real (VM86) mode.
> The only way is just to terminate the application.
Correct.
> But I don't want to
> terminate it. Maybe is possible to run some child process but I don't want
> to call any external EXE file.
This is correct too. To accomplish this without relying on files, create a fake process. You can do this manually, then set the PSP with Int21.50 or use Int21.26 or Int21.55.
EDIT: Here's an example program that switches to 32-bit PM within a child process, does some debugging/testing stuff then returns to its parent process in RM. Worked in NTVDM after assembling with NASM 2.08rc-something. Based on some TSR installation/relocation stuff and some DPMI test program.
;%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
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
mov cx, 8*8
rep cs 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
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
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
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 ; 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:
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 doesn't work here with the debugger.
; int 03h however does. Note that both might crash
; the DPMI host if no debugger is installed.
iret
bits 16
callrm:
int3 ; int 03h or int3 traps (in real or V86 mode)
; don't cause any problems.
xor ax, ax
push ax
push ax
call -1:-1
.callback equ $-4
pop ax
pop ax
int3
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
or al, al
jnz .next
retn
; The (DPMIed) child process has terminated.
childterminated:
childterminated_ofs equ (childterminated-$$+100h)
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
data:
.pspsel: dw 0
; 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
; 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: db "Not enough DOS memory for child process creation or"
asciz "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 "
db _4digitshex(childterminated_ofs),"h.",13,10
asciz 13,10
.welcome: asciz "Welcome in 32-bit protected mode.",13,10
align 2
rmcallsp:
--- l |
Japheth
Germany (South), 18.08.2010, 08:04
@ Laaca
|
With DPMI into protect mode and back |
> If I understand the documentation correct, I can switch into protect mode
> by calling address provided in INT2Fh/AX=1687h but there is no transparent
> way how to get back into real (VM86) mode.
> The only way is just to terminate the application. But I don't want to
> terminate it. Maybe is possible to run some child process but I don't want
> to call any external EXE file.
There a 3 methods to switch "back":
1. terminate the DPMI client
2. using Int 31h, ax=0300h/0301h/0302h
3. using raw mode switch (int 31h, ax=0306h)
Here's a sample using the int 31h, ax=0301h method - it's a slightly modified dpmicl16.asm which is supplied with FD DEBUG:
;--- DPMIBACK.ASM: 16bit DPMI application written in MASM syntax.
;--- this sample temporarily switches back to real-mode.
;--- assemble: JWasm -bin -Fo dpmiback.com dpmiback.asm
LF equ 10
CR equ 13
.286
.model tiny
;--- DPMI real-mode call structure
RMCS struct
rEDI dd ?
rESI dd ?
rEBP dd ?
dd ?
rEBX dd ?
rEDX dd ?
rECX dd ?
rEAX dd ?
rFlags dw ?
rES dw ?
rDS dw ?
rFS dw ?
rGS dw ?
rIP dw ?
rCS dw ?
rSP dw ?
rSS dw ?
RMCS ends
.data
szWelcome db "welcome in protected-mode",CR,LF,0
dBack db "back in real-mode",CR,LF,'$'
dErr1 db "no DPMI host installed",CR,LF,'$'
dErr2 db "not enough DOS memory for initialisation",CR,LF,'$'
dErr3 db "DPMI initialisation failed",CR,LF,'$'
.code
org 100h
;--- the 16bit initialization part
start:
pop ax ;get word saved on stack for COM files
mov bx, sp
shr bx, 4
jnz @F
mov bx,1000h ;it was a full 64kB stack
@@:
mov ah, 4Ah ;free unused memory
int 21h
mov ax, 1687h ;DPMI host installed?
int 2Fh
and ax, ax
jnz nohost
push es ;save DPMI entry address
push di
and si, si ;requires host client-specific DOS memory?
jz nomemneeded
mov bx, si
mov ah, 48h ;alloc DOS memory
int 21h
jc nomem
mov es, ax
nomemneeded:
mov bp, sp
mov bx, cs ;save real-mode value of CS in BX
mov ax, 0000 ;start a 16-bit client
call far ptr [bp] ;initial switch to protected-mode
jc initfailed
;--- now in protected-mode
push bx
mov si, offset szWelcome
call printstring
pop bx
;--- switch back to real-mode
sub sp, sizeof RMCS
mov bp,sp
mov [bp].RMCS.rIP, offset backtoreal
mov [bp].RMCS.rCS, bx
mov [bp].RMCS.rFlags, 0
lea ax,[bp-20h]
mov [bp].RMCS.rSP, ax
mov [bp].RMCS.rSS, bx
xor bx,bx
xor cx,cx
mov di,bp
push ss
pop es
mov ax,0301h
int 31h
mov ax, 4C00h ;normal client exit
int 21h
backtoreal:
push cs
pop ds
mov dx,offset dBack
mov ah,9
int 21h
retf ;back to protected-mode for final exit
nohost:
mov dx, offset dErr1
jmp error
nomem:
mov dx, offset dErr2
jmp error
initfailed:
mov dx, offset dErr3
error:
push cs
pop ds
mov ah, 9
int 21h
mov ax, 4C00h
int 21h
;--- print a string in protected-mode with simple
;--- DOS commands not using pointers.
printstring:
lodsb
and al,al
jz stringdone
mov dl,al
mov ah,2
int 21h
jmp printstring
stringdone:
ret
end start
--- MS-DOS forever! |
DOS386
26.08.2010, 09:18
@ ecm
|
With DPMI into protect mode and back - EDIT: example |
> > The only way is just to terminate the application.
> Correct.
Not that much.
> > terminate it. Maybe is possible to run some child process but I don't
> > want to call any external EXE file
> This is correct too. To accomplish this without relying on files, create a
> fake process. You can do this manually, then set the PSP with Int21.50 or
> use Int21.26 or Int21.55.
Right. You exposed a big advantage of DOS compared to Windows:
In DOS there is a (hacky, as usual) way to brew a separate process without brewing a file. In Windaube this is impossible to accomplish (except very aggressive kernel intrusion at least):
> The name of the module to be executed. This module can be a
> Windows-based application. It can be some other type of
> module (for example, MS-DOS or OS/2
> process in RM. Worked in NTVDM after
WtF ???
Works for me in FreeDOS and EDR-DOS (my own, not example above).
BTW, I prefer INC CR0 from DPMI --- This is a LOGITECH mouse driver, but some software expect here
the following string:*** This is Copyright 1983 Microsoft *** |
ecm
Düsseldorf, Germany, 26.08.2010, 14:35
@ DOS386
|
With DPMI into protect mode and back - EDIT: example |
> > > The only way is just to terminate the application.
> > Correct.
>
> Not that much.
Well tell us. The way I've shown is to terminate the application - just with it being a fake application executed as child process.
> In DOS there is a (hacky, as usual) way to brew a separate process without
> brewing a file. In Windaube this is
> impossible
> to accomplish (except very aggressive kernel intrusion at least):
>
> > The name of the module to be executed. This module can be a
> > Windows-based application. It can be some other type of
> > module (for example, MS-DOS or OS/2
How bout you just execute your own executable? This is generally more dependable in Windows NT because you always get the path supplied - as opposed to DOS where that (A) depends on COMMAND.COM or any other parent process to set the right environment and (B) isn't done by all versions of COMMAND.COM even.
Besides, this particular issue doesn't exist for a Windows process and without a problem to work around, faking a child isn't useful anyway.
> > process in RM. Worked in NTVDM after
>
>
NTVDM has so many bugs, if it works within it will work with HDPMI too
> BTW, I prefer INC CR0 from DPMI
(1) There is no such instruction as INC CR0 . You mean MOV EAX, CR0 , INC EAX , MOV CR0, EAX . In other news: lol if u b trollin b trollin r8 dude
(2) I prefer DPMI. Although you don't have ring 0 access right away, it's just so much easier to set up. Especially because the host works out just about any memory setup for you, so I don't have to care about A20, XMS, XMS locking, Int15, VCPI or 400 other things you have to consider when switching to PM. Duh. (BTW for ring 0 access I prefer JLMs.) --- l |
DOS386
27.08.2010, 03:33
@ ecm
|
With DPMI into protect mode and back - EDIT: example |
> > > > The only way is just to terminate the application.
> > > Correct.
> > Not that much.
> Well tell us.
NO I won't. No need to duplicate Japheth's work, see above.
> How bout you just execute your own executable?
Bad hack.
> Besides, this particular issue doesn't exist for a Windows process and
> without a problem to work around, faking a child isn't useful anyway.
Strange, how do you execute 3rd party crappy code then ? And why did Firefox ban crappy plugins (most notably Flash) into a separate process ?
> In other news: lol if u b trollin b trollin r8 dude
Is it 64-bit code ? Does it compile ???
> (2) I prefer DPMI. Although you don't have ring 0 access right away, it's
> just so much easier to set up.
Right, no pain no gain
> (BTW for ring 0 access I prefer JLMs.)
Sure, and this works without external files --- This is a LOGITECH mouse driver, but some software expect here
the following string:*** This is Copyright 1983 Microsoft *** |
ecm
Düsseldorf, Germany, 30.08.2010, 21:51
@ DOS386
|
With DPMI into protect mode and back - EDIT: example |
> > > > > The only way is just to terminate the application.
> > > > Correct.
> > > Not that much.
> > Well tell us.
>
> NO I won't. No need to duplicate Japheth's work, see above.
Using RM callbacks (which I did use too, but that's not the point) doesn't properly remove the "DPMI process" or "context", so you're not really back. In that state, it might be a bad idea to terminate the current DOS process. (Japheth probably knows more about that, regarding HDPMI.)
> > How bout you just execute your own executable?
>
> Bad hack.
Right, but it works well enough if you get the name.
> > Besides, this particular issue doesn't exist for a Windows process and
> > without a problem to work around, faking a child isn't useful anyway.
>
> Strange, how do you execute 3rd party crappy code then ? And why did
> Firefox ban crappy plugins (most notably Flash) into a separate process ?
I would think Firefox is not a DOS or DPMI program, so that this would not be the particular issue that we talked about.
> > In other news: lol if u b trollin b trollin r8 dude
>
> Is it 64-bit code ? Does it compile ???
Why would it even be 64-bit code. And yes, it does compile:
D:\>debug
Executed initcont
-a
0F88:0100 mov eax,cr0
0F88:0103 inc eax
0F88:0105 mov cr0,eax
0F88:0108
-u 100l8
0F88:0100 0F20C0 MOV EAX,CR0
0F88:0103 6640 INC EAX
0F88:0105 0F22C0 MOV CR0,EAX
-
See? (True, it's not optimal and all the other preparations to properly go into PM are still missing, but better than not compiling at all.)
(EDIT: No, not all text that contains the token "r8" (or any other register name) is code.)
> > (BTW for ring 0 access I prefer JLMs.)
>
> Sure, and this works without external files.
Sure, and going into PM on your own works with an EMM, XMM or DPMI host installed. --- l |
DOS386
06.09.2010, 20:08
@ ecm
|
With DPMI into protect mode and back | physical memory |
> Using RM callbacks (which I did use too, but that's not
> the point) doesn't properly remove the "DPMI process"
> or "context", so you're not really back.
There is so-called "raw" switch ... (my "raw" is DEC CR0 ...)
> I would think Firefox is not a DOS or DPMI program,
> so that this would not be the particular issue
> that we talked about.
Right, but it may be useful to execute external dangerous code in a separate process on any OS
> and going into PM on your own works with an EMM, XMM or DPMI host installed.
Right (not inside NTVDM of course, but hey, isn't this maybe deliberate ??? ).
BTW, how do you hog physical memory in DPMI ??? --- This is a LOGITECH mouse driver, but some software expect here
the following string:*** This is Copyright 1983 Microsoft *** |
ecm
Düsseldorf, Germany, 07.09.2010, 17:04
@ DOS386
|
With DPMI into protect mode and back | physical memory |
> > Using RM callbacks (which I did use too, but that's not
> > the point) doesn't properly remove the "DPMI process"
> > or "context", so you're not really back.
>
> There is so-called "raw" switch...
What's it do with the "DPMI process" or "context"? Nothing. And that's not better than the callback method, that's worse, because I want those to be properly removed.
> Right, but it may be useful to execute external dangerous code in a
> separate process on any OS.
True.
> > and going into PM on your own works with an EMM, XMM or DPMI host
> installed.
>
> RightWrong, it neither works with any EMM nor with some XMMs and DPMI hosts.
Yeah, that's what I meant.
> BTW, how do you hogallocate or map physical memory in DPMI???
Maybe Int31.0508 (DPMI 1.0)? Otherwise, Int31.08 (DPMI 0.9+). As I understand it, you have to allocate an XMS memory block first and lock that, then access it with the linear address Int31.0800 returns. --- l |
DOS386
08.09.2010, 00:51
@ ecm
|
With DPMI into protect mode and back | physical memory |
> Yeah, that's what I meant.
Right: no NTVDM support.
> BTW, how do you hog allocate or map physical memory in DPMI??????
> Maybe Int31.0508 (DPMI 1.0)? Otherwise, Int31.08 (DPMI 0.9+). As I
> understand it, you have to allocate an XMS memory block first and lock
> that, then access it with the linear address Int31.0800 returns.
This might work under some special optimal circumstances ... but what do you do if there is no XMS host ? BTW, I had very deliberately asked about physical memory hogging and not mapping, because there is (one of many) critical "design" fault in DPMI: no "official" way to hog physical memory --- This is a LOGITECH mouse driver, but some software expect here
the following string:*** This is Copyright 1983 Microsoft *** |
ecm
Düsseldorf, Germany, 08.09.2010, 20:53
@ DOS386
|
With DPMI into protect mode and back | physical memory |
> This might work under some special optimal circumstances... but what do
> you do if there is no XMS host? BTW, I had very deliberately asked about
> physical memory hoggingallocation and not mapping, because there is
> a critical design fault (one of many) in DPMI: no "official" way to
> hogallocate physical memory.
There might not be specific DPMI functions for this, but your "special" optimal circumstances (an XMM) are the default on most DOS systems. Otherwise, abort the operation/process requiring physical memory and inform the user that he needs to configure his set-up to include an XMM. (Sometimes using memory handled by DOS can solve this, as this should be mapped exactly to physical memory if there is no XMM/EMM.) Not nice, but it's nothing critical.
Japheth might know this better.
You didn't even mention that physical memory can't be allocated in NTVDM! Oh no! --- l |
DOS386
11.09.2010, 01:02
@ ecm
|
With DPMI into protect mode and back | physical memory |
> abort the operation/process requiring physical memory and inform
> the user that he needs to configure his set-up to include an XMM
That's exactly how things should NOT be - user having to workaround application flaws coming from bad "standards"
> (Sometimes using memory handled by DOS can solve this, as this should be
> mapped exactly to physical memory if there is no XMM/EMM.)
It works even with XMS host (and maybe even EMM386 ???), but there are only cca 1/2 MiB of low memory available, so it will work with "legacy" LDA sound cards, but not with HHDA (hyper high definition audio: 8 channels, 32 bits per channel sample, 196 KHz, see MPXPLAY forum ) because the 1:1-mapped low memory is not big enough Another flaw: you can request neither a preferred address nor minimal alignment when hogging low memory. This means, that for a 64-KiB aligned 64 KiB buffer you must hog 128 KiB and "find" the buffer inside, the other 64 KiB are wasted. Not cool at all (consider the low-memory-wars about just a few 100 Byte's with German keyboard "drivers" ).
> Not nice, but it's nothing critical.
> You didn't even mention that physical memory can't be allocated in NTVDM!
> Oh no!
--- This is a LOGITECH mouse driver, but some software expect here
the following string:*** This is Copyright 1983 Microsoft *** |
ecm
Düsseldorf, Germany, 11.09.2010, 01:25
@ DOS386
|
With DPMI into protect mode and back | physical memory |
> That's exactly how things should NOT be - user having to work around
> application flaws coming from bad standards.
Agreed. It's your turn to travel back in time and establish better standards.
> It works even with XMS host (and maybe even EMM386 ???), [...]
It possibly doesn't work in EMM-remapped UMA space.
With an EMM, but no XMS available (maybe all allocated (maybe by the EMM)) you might go allocate some physical memory in VCPI then access that from the DPMI code. That's more cumbersome than with XMS but should still work.
> but there are only cca 1/2 MiB of low memory available,
I thought that was implicit when I said that DOS-handled memory can only sometimes solve this.
> [...], the other 64 KiB are wasted.
If you can re-use the space (partly), it's not (fully) wasted. Either the part behind or after the 64 KiB buffer will be at least 32 KiB large. Similarly, you can then re-use the remaining space in allocations of 16 KiB, 8 KiB, 4 KiB etc, alternating between the part behind and the one after the buffer as necessary. This requires little code and some pointers stored somewhere to reference where these data chunks are located. Some of these pointers or code could be stored in the "wasted" space, which still wastes some of the space but considerably less of it. --- l |
Japheth
Germany (South), 18.10.2010, 11:17 (edited by Japheth, 19.10.2010, 08:22)
@ Japheth
|
With DPMI into protect mode and back |
> Here's a sample using the int 31h, ax=0301h method - it's a slightly
> modified dpmicl16.asm which is supplied with FD DEBUG:
>
>
[snipped]
>
It's probably worth to be noted that it was this example which made me aware that DEBUG v1.18 wasn't able to reset its breakpoints when a mode switch occured in the debuggee ( fixed in v1.19 ).
Another note: the bugfix for v1.19 includes a temporary mode switch inside the debugger under certain conditions. Debug uses DPMI raw-mode switches for this. It has turned out that this approach won't work with CWSDPMI v5. HDPMI, Windows 9x/ME and Windows XP are ok. DosEmu is untested yet.
Edit: DosEmu is also ok. --- MS-DOS forever! |
Rugxulo
Usono, 18.10.2010, 23:07
@ Japheth
|
With DPMI into protect mode and back |
> Another note: the bugfix for v1.19 includes a temporary mode switch inside
> the debugger under certain conditions. Debug uses DPMI raw-mode switches
> for this. It has turned out that this approach won't work with CWSDPMI v5.
I doubt r7 is better in this particular part, but you should definitely test against that. It's default on DJ's Zip Picker now anyways (though I'm not denying that r5 exists in a ton of places). Also, I know you're busy, but if it's really a bug, he should be notified. I'll (weakly) do it if you're unwilling. |
Japheth
Germany (South), 19.10.2010, 09:58
@ Rugxulo
|
With DPMI into protect mode and back |
> I doubt r7 is better in this particular part, but you should definitely
> test against that. It's default on DJ's Zip Picker now anyways (though I'm
> not denying that r5 exists in a ton of places). Also, I know you're busy,
> but if it's really a bug, he should be notified. I'll (weakly) do it if
> you're unwilling.
I tested r7 and didn't note a difference.
However, the cause of the problem is found. Here's the output of DPMI.EXE with CWSDPMI loaded:
-------------------------------------------------
Cpu is in V86-mode
[snipped]
state save protected-mode: 002B:000012A2, real-mode: 0306:12A2
size state save buffer: 0000
raw jump to real-mode: 0068:00000000, protected-mode: 0306:1267
[snipped]
-------------------------------------------------
Size of the state buffer is zero, that is, one doesn't need to call the "state save" routines for raw-mode switches. DEBUGX does, no matter what size the buffer has. This is - or "should be" - ok, according to DPMI docs.
With CWSDPMI, it isn't ok, because the protected-mode address, 002B:12A2, is a 16-bit code segment and contains just a RETF. It has to be a 32-bit RETF, however, so there's a 66h byte missing before the RETF. --- MS-DOS forever! |
Rugxulo
Usono, 19.10.2010, 10:09
@ Japheth
|
With DPMI into protect mode and back |
> I tested r7 and didn't note a difference.
Okay, I've e-mailed him, so at least he'll soon be aware of it. I'm sure he's busy as always, but since his kids are in college now, he might? have a bit more free time. |
Japheth
Germany (South), 19.10.2010, 10:20
@ Rugxulo
|
With DPMI into protect mode and back |
> Okay, I've e-mailed him, so at least he'll soon be aware of it. I'm sure
> he's busy as always, but since his kids are in college now, he might? have
> a bit more free time.
I'll implement a workaround in debugx, so there's not really a need to change cwsdpmi. --- MS-DOS forever! |
Japheth
Germany (South), 19.10.2010, 17:59
@ Japheth
|
Possible CWSDPMI design flaw |
> However, the cause of the problem is found.
That was only half of the truth. The workaround has been implemented in DEBUGX - it's simply avoiding to call DPMI "save/restore state" when the state size is zero. However, this fixes only 50%, DEBUGX on CWSDPMI is now able to temporarily switch to real-mode and back with raw switches, but the other direction ( RM -> PM -> RM ) still won't work.
CWSDPMI's state size of zero made me suspicious already, and a quick look into its source - DPMISIM.ASM - revealed that the raw switches are only supposed to work if the first switch is initiated from protected-mode. Trying to do it the other way - as DEBUGX may do - will cause a freeze. --- MS-DOS forever! |