Laaca
Czech republic, 11.05.2020, 13:37 |
DPMI code from .COM file? (Developers) |
I am curious whether is possible to call some DPMI code from .COM file. Because if yes it would be easy to f.e. bundle machine-code modules as a payloads into normal real-mode turbo pascal programs.
To narrow the question:
In FASM distribution is a example file USEDPMI.ASM
It prints a message "Hello from protected mode!"
Here is the listing:
format MZ
heap 0 ; no additional memory
segment loader use16
push cs
pop ds
mov ax,1687h
int 2Fh
or ax,ax ; DPMI installed?
jnz error
test bl,1 ; 32-bit programs supported?
jz error
mov word [mode_switch],di
mov word [mode_switch+2],es
mov bx,si ; allocate memory for DPMI data
mov ah,48h
int 21h
jc error
mov es,ax
mov ax,1
call far [mode_switch] ; switch to protected mode
jc error
mov cx,1
xor ax,ax
int 31h ; allocate descriptor for code
mov si,ax
xor ax,ax
int 31h ; allocate descriptor for data
mov di,ax
mov dx,cs
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,si
mov ax,9
int 31h ; set code descriptor access rights
mov dx,ds
lar cx,dx
shr cx,8
or cx,0C000h
mov bx,di
int 31h ; set data descriptor access rights
mov ecx,main
shl ecx,4
mov dx,cx
shr ecx,16
mov ax,7 ; set descriptor base address
int 31h
mov bx,si
int 31h
mov cx,0FFFFh
mov dx,0FFFFh
mov ax,8 ; set segment limit to 4 GB
int 31h
mov bx,di
int 31h
mov ds,di
mov es,di
mov fs,di
mov gs,di
push 0
push si
push dword start
retfd
error:
mov ax,4CFFh
int 21h
mode_switch dd ?
segment main use32
start:
mov esi,hello
.loop:
lodsb
or al,al
jz .done
mov dl,al
mov ah,2
int 21h
jmp .loop
.done:
mov ax,4C00h
int 21h
hello db 'Hello from protected mode!',0Dh,0Ah,0
Is possible to convert the code to be compilable not as a .EXE but as a .COM? --- DOS-u-akbar! |
ecm
Düsseldorf, Germany, 11.05.2020, 14:42
@ Laaca
|
DPMI code from .COM file? |
> Is possible to convert the code to be compilable not as a .EXE but as a
> .COM?
It certainly is possible, but I don't know FASM much and haven't looked into your example. The FreeDOS Debug releases come with some DPMI example programs for DebugX, at least some of which are or used to be compiled into flat .COM files using NASM. --- l |
Laaca
Czech republic, 11.05.2020, 14:50
@ ecm
|
DPMI code from .COM file? |
> It certainly is possible, but I don't know FASM much and haven't looked
> into your example. The FreeDOS Debug releases come with some DPMI example
> programs for DebugX, at least some of which are or used to be compiled into
> flat .COM files using NASM.
You are right!
It is possible and I even found a source for it. Uploaded here: http://www.laaca.sweb.cz/tinycom.asm
But...
If I want to somehow include it into realmode pascal source I need to end the program by instruction RETF and not by INT 21/4C because it would end whole my application and only my routine... --- DOS-u-akbar! |
ecm
Düsseldorf, Germany, 11.05.2020, 14:59
@ Laaca
|
DPMI code from .COM file? |
> To narrow the question:
> In FASM distribution is a example file USEDPMI.ASM
> It prints a message "Hello from protected mode!"
> Here is the listing:
I edited your post to put the listing into BB-code [code] tags.
> format MZ
> heap 0 ; no additional memory
>
> segment loader use16
Insert whatever is used by FASM for flat .COM files.
> push cs
> pop ds
This is probably fine.
> mov bx,si ; allocate memory for DPMI data
> mov ah,48h
> int 21h
> jc error
Before this you need to shrink the process's memory block because flat .COM files are always loaded with max alloc = FFFFh. Shrink it to 1000h paragraphs (64 KiB), or if you want to shrink it smaller insure that the stack is below that. Eg (for NASM, adjust to whatever FASM needs):
cpu 8086
org 256
startprogram:
[...]
cmp sp, stack_end
jb error
mov sp, stack_end
mov bx, ( (stack_end - startprogram) + 256 + 15 ) >> 4
mov ah, 4Ah
int 21h
jc error
[...]
align 2
endprogram:
stack_end: equ endprogram + 512
> mov ecx,main
> shl ecx,4
> mov dx,cx
> shr ecx,16
> mov ax,7 ; set descriptor base address
> int 31h
> mov bx,si
> int 31h
This needs to change. Easiest is putting the "main" or "start" label in the same segment as the .COM entrypoint. In that case replace the "mov ecx, main " with:
mov cx, cs
movzx ecx, cx
If you want to keep using different segments then in NASM you'd need "section main vstart=0 " and load ecx with CS plus whatever is the size in paragraphs of the PSP plus the section "loader". Not sure how to do that in FASM. --- l |
ecm
Düsseldorf, Germany, 11.05.2020, 15:07
@ Laaca
|
DPMI code from .COM file? |
> You are right!
> It is possible and I even found a source for it. Uploaded here:
> http://www.laaca.sweb.cz/tinycom.asm
>
> But...
> If I want to somehow include it into realmode pascal source I need to end
> the program by instruction RETF and not by INT 21/4C because it would end
> whole my application and only my routine...
DPMI programs must end with Int 21.4C to allow the DPMI host to learn of the termination. What you can do is create a new PSP, and set its Int 22 address (Parent Return Address) and Parent Process field so as to return into your program. Then when the DPMI part is finished you use protected-mode Int 21.4C which eventually has the host drop into 86 Mode to run DOS's interrupt 21h handler, and then DOS returns to your process (closing all file handles in the new PSP and freeing memory allocated to that new PSP).
If you want to keep calling into DPMI and returning back, you can use the raw mode switch entrypoints (Int 31.0305 and .0306) or use the other Int 31.03 functions to call 86 Mode code from protected mode. --- l |
ecm
Düsseldorf, Germany, 11.05.2020, 16:07 (edited by ecm, 18.08.2021, 14:28)
@ Laaca
|
DPMI code from .COM file? |
Here's a full example (from my lDebug/assorted/tests/ directory, wasn't yet in any repo) that builds a new child PSP from the current PSP, DUPs the file handles to use in the child, sets this child PSP as active, enters protected mode, then returns back to the original process in 86 Mode. (Plus, it shows some callback usages.) It builds with nasm dpmipsp.asm -f bin -o dpmipsp.com -l dpmipsp.lst --- l |
Laaca
Czech republic, 11.05.2020, 22:44
@ ecm
|
DPMI code from .COM file? |
Wow!
It is really impressive. But it is too complicated for me and do not understand the code much.
However - is possible to change the lines 313-314 from "mov ax,4c00h / int 21h" to RETF ?
Why I examine all this stuff - I have a quite nice pascal unit and I am proud that it is a amphiguous code - it compiles in DOS 32-bit Freepascal and 16-bit realmode turbopascal.
I almost always use the Freepascal and 32-bit protected mode but anyway, in this unit I want to keep full compatibility with Turbo pascal.
And in this unit I have a function Get_DPMI_Info.
No problem in FreePascal as I simply call the DPMI function 400h and 401h.
But in Turbopascal we are in real mode but the DPMI server may or may not be installed (although not active in this moment). And it would be nice to get some info about this non-active daemon. --- DOS-u-akbar! |
ecm
Düsseldorf, Germany, 11.05.2020, 23:05
@ Laaca
|
DPMI code from .COM file? |
> Wow!
> It is really impressive. But it is too complicated for me and do not
> understand the code much.
If you have any specific questions I can try to help you more.
> However - is possible to change the lines 313-314 from "mov ax,4c00h / int
> 21h" to RETF ?
Yes, that should be possible without problems.
However, you need to take care with the segmentation to properly address the current PSP (get using Int 21.51 if you don't have it available easily), the new PSP to be created, and your own data segments. And don't forget that after returning to the original process all register values except ss:sp may have changed, so put things on the stack (before calling Int 21.48 to allocate the process memory block) or into variables in the code segment.
Also, if you do use Int 21.48 to allocate the block for the process, you may want to make it self-owned (in line 61) so that it is freed by DOS when you terminate the child process.
Another bit to watch out for is that you may want to record into the child PSP the interrupt 23h and 24h handlers currently in use by your process. That is, use Int 21.3523 and .3524 and store the vectors into the child PSP. When the child terminates, DOS will set the vectors to those found in the child PSP. (My example just copies whatever vectors are in its own PSP, which is fine if you do not ever modify them. I guess Pascal may modify them.)
> Why I examine all this stuff - I have a quite nice pascal unit and I am
> proud that it is a amphiguous code - it compiles in DOS 32-bit Freepascal
> and 16-bit realmode turbopascal.
> I almost always use the Freepascal and 32-bit protected mode but anyway, in
> this unit I want to keep full compatibility with Turbo pascal.
> And in this unit I have a function Get_DPMI_Info.
> No problem in FreePascal as I simply call the DPMI function 400h and 401h.
> But in Turbopascal we are in real mode but the DPMI server may or may not
> be installed (although not active in this moment). And it would be nice to
> get some info about this non-active daemon.
That should be possible. Just a nitpick, if you have a DPMI server loaded "for the next client only" (I think HDPMI has such a mode) then your stint into protected mode will exhaust the DPMI server and it will uninstall itself when you terminate the DPMI client process. I guess you could expect a user to know what they are doing. --- l |
Rugxulo
Usono, 13.05.2020, 04:39
@ Laaca
|
DPMI code from .COM file? |
> I am curious whether is possible to call some DPMI code from .COM file.
FASM used to be .COM! And it was never real mode. But that was many versions ago, e.g. FASM 1.40 (UPX'd) from 2002.
Since .COM is easiest to reproduce (usually no linker needed, no header), for laughs I made a thread called bootstrapping FASM? two years ago. Technically, I didn't fully do it, only used old 1.40's .COM to build 1.64 then that to build 1.72. But that was my point, start from simple and go more complex. (I know that's not quite what you wanted, but just FYI.) |
CandyMan
13.05.2020, 19:53
@ Laaca
|
DPMI code from .COM file? |
D3XX dos extender with debugger and examples how to use it with fasm.
https://board.flatassembler.net/topic.php?p=145936#145936 |