Discussion:
[PATCH] stub: ignore host exit status
(too old to reply)
J.W. Jagersma (jwjagersma@gmail.com) [via djgpp@delorie.com]
2022-11-24 20:35:49 UTC
Permalink
[patch omitted]
Noticed a small bug here, sorry. Will send a v2 soon.
J.W. Jagersma (jwjagersma@gmail.com) [via djgpp@delorie.com]
2022-11-24 23:26:51 UTC
Permalink
Hi all,
If you've ever tried using hdpmi32 with a djgpp program, you may have
noticed some strange behavior. The program first fails to run with
"Load error: no DPMI", but on the second try, it suddenly works. Then
a third invocation fails again, the fourth runs fine, etc.
When you rename 'hdpmi32.exe' to 'cwsdpmi.exe', your program seems to
run consistently. But this is only because there is a second (real)
cwsdpmi in your PATH somewhere. What really happens, is that your
program alternates between running under hdpmi and cwsdpmi.
I finally figured out why this happens, and it's very simple: hdpmi uses
the exit status to indicate if it was loaded via xms, vcpi, or int15.
And the djgpp stub considers any non-zero exit status to be a failure,
so it keeps searching PATH until cwsdpmi is found, which always returns
zero.
For a possible solution, I would suggest to ignore the return status
from the host, and just check int 2f/1687 after every exec. As an added
bonus, this saves 13 bytes of stub space.
Amended patch follows - it no longer skips the last iteration (exec
with no path).

It's a bit larger, but still saves 6 bytes in total.

--- a/src/stub/stub.asm
+++ b/src/stub/stub.asm
@@ -199,38 +199,49 @@ not_path:
;-----------------------------------------------------------------------------
; Get DPMI information before doing anything 386-specific

- push es
push di
- xor cx, cx ; flag for load attempt set cx = 0
- jz @f2 ; We always jump, shorter than jmp
+ ; Set up loadname in case of no DPMI.
+ ; First try current dir.
+ xor ah, ah ; Copy until this character (=0)
+ call store_env_string ; copy stub image to "loadname"
+ mov si, bx ; remove name so we can add DPMI name
+ mov di, [path_off] ; Pointer to path contents (next try)
@b1:
+ xor cx, cx ; flag to signal end of loop
+@b2:
+ call check_dpmi ; int 2f, ax=1687
+ jz @f3
+ call do_exec ; copy our name to string and try load
+ jcxz @f1 ; cx=0 while we have more paths to try
+ call check_dpmi ; last chance...
+ jz @f3
mov al, 110
mov dx, msg_no_dpmi
jmpl error
-@b2:
- or cx, cx
- jnz @b1 ; we already tried load once before
- inc cx
- call load_dpmi
- jc @b1
+@f1:
+ ; Set up loadname for next attempt.
+ mov ah, ';' ; Copy until this character
+ call store_env_string ; to "loadname"
+ or al, al ; Check terminating character
+ jne @f2 ; If ';', continue
+ dec di ; else point at null for next pass.
@f2:
- mov ax, 0x1687 ; get DPMI entry point
- int 0x2f
- or ax, ax
- jnz @b2 ; if 0 then it's there
- and bl, 1 ; 32 bit capable?
- jz @b2
+ inc cx
+ cmp si, loadname ; anything there?
+ je @b2 ; final try (no path)
+ mov al, [si-1]
+ call test_delim ; is final character a path delimiter
+ je @b1
+ movb [si], '\\' ; no, add separator between path & name
+ inc si
+ jmp @b1
@f3:
- mov [modesw], di ; store the DPMI entry point
- mov [modesw+2], es
- mov [modesw_mem], si
pop di
- pop es

;-----------------------------------------------------------------------------
; Now, find the name of the program file we are supposed to load.

-; xor ah, ah ; termination character (set above!)
+; xor ah, ah ; termination char (set by check_dpmi)
call store_env_string ; copy it to loadname, set bx

mov [stubinfo_env_size], di
@@ -700,36 +711,29 @@ pm_dos:
ret

;-----------------------------------------------------------------------------
-; load DPMI server if not present
-; First check directory from which stub is loaded, then path, then default
-; On entry di points to image name
+; Check for presence of a DPMI host, and save the mode switch address.
+; Zero flag is clear on success. Clobbers ax/bx/dx.

-path_off:
- .dw 0 ; If stays zero, no path
-
-load_dpmi:
- xor ah, ah ; Copy until this character (=0)
- call store_env_string ; copy stub image to "loadname"
- mov si, bx ; remove name so we can add DPMI name
- mov di, [path_off] ; Pointer to path contents (next try)
- jmp @f2
-loadloop:
- mov ah, ';' ; Copy until this character
- call store_env_string ; to "loadname"
- or al,al ; Check terminating character
- jne @f1 ; If ';', continue
- dec di ; else point at null for next pass.
-@f1:
- cmp si, loadname ; anything there?
- je do_exec ; final try (no path) let it return
- mov al, [si-1]
- call test_delim ; is final character a path delimiter
- je @f2
- movb [si], '\\' ; no, add separator between path & name
- inc si
-@f2:
- call do_exec ; copy our name to string and try load
- jc loadloop
+check_dpmi:
+ push es
+ push cx
+ push di
+ push si
+ mov ax, 0x1687 ; get DPMI entry point
+ int 0x2f
+ mov dx, bx
+ or dl, 1 ; bx bit 0: 32-bit capable
+ xor bx, dx
+ or ax, bx ; DPMI present if ax = 0
+ jnz @f1
+ mov [modesw], di ; store the DPMI entry point
+ mov [modesw+2], es
+ mov [modesw_mem], si
+@f1:
+ pop si
+ pop di
+ pop cx
+ pop es
ret

;-----------------------------------------------------------------------------
@@ -766,13 +770,6 @@ do_exec:
int 0x21
pop di
pop es
- jc @f1 ;carry set if exec failed
-
- mov ah, 0x4d ;get return code
- int 0x21
- sub ax, 0x300 ;ah=3 TSR, al=code (success)
- neg ax ;CY, if not originally 0x300
-@f1:
jmp restore_umb ;called func. return for us.

;-----------------------------------------------------------------------------
@@ -796,10 +793,9 @@ include_umb:
@f1:
ret

-; Restore upper memory status. All registers and flags preserved.
+; Restore upper memory status. All registers preserved.

restore_umb:
- pushf
cmpb [dos_major], 5 ; Won't work before dos 5
jb @f1
push ax
@@ -815,7 +811,6 @@ restore_umb:
pop bx
pop ax
@f1:
- popf
ret

;-----------------------------------------------------------------------------
@@ -840,6 +835,8 @@ msg_no_selectors:
.db "no DPMI selectors$"
msg_no_dpmi_memory:
.db "no DPMI memory$"
+path_off:
+ .dw 0 ; Points to PATH, stays zero if none.

;-----------------------------------------------------------------------------
; Unstored Data, available during and after mode switch
J.W. Jagersma (jwjagersma@gmail.com) [via djgpp@delorie.com]
2023-01-24 18:10:21 UTC
Permalink
Would appreciate any feedback on this. I know there's a small mistake in one
comment, but the code works.
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
Hi all,
If you've ever tried using hdpmi32 with a djgpp program, you may have
noticed some strange behavior. The program first fails to run with
"Load error: no DPMI", but on the second try, it suddenly works. Then
a third invocation fails again, the fourth runs fine, etc.
When you rename 'hdpmi32.exe' to 'cwsdpmi.exe', your program seems to
run consistently. But this is only because there is a second (real)
cwsdpmi in your PATH somewhere. What really happens, is that your
program alternates between running under hdpmi and cwsdpmi.
I finally figured out why this happens, and it's very simple: hdpmi uses
the exit status to indicate if it was loaded via xms, vcpi, or int15.
And the djgpp stub considers any non-zero exit status to be a failure,
so it keeps searching PATH until cwsdpmi is found, which always returns
zero.
For a possible solution, I would suggest to ignore the return status
from the host, and just check int 2f/1687 after every exec. As an added
bonus, this saves 13 bytes of stub space.
Amended patch follows - it no longer skips the last iteration (exec
with no path).
It's a bit larger, but still saves 6 bytes in total.
--- a/src/stub/stub.asm
+++ b/src/stub/stub.asm
;-----------------------------------------------------------------------------
; Get DPMI information before doing anything 386-specific
- push es
push di
- xor cx, cx ; flag for load attempt set cx = 0
+ ; Set up loadname in case of no DPMI.
+ ; First try current dir.
+ xor ah, ah ; Copy until this character (=0)
+ call store_env_string ; copy stub image to "loadname"
+ mov si, bx ; remove name so we can add DPMI name
+ mov di, [path_off] ; Pointer to path contents (next try)
+ xor cx, cx ; flag to signal end of loop
+ call check_dpmi ; int 2f, ax=1687
+ call do_exec ; copy our name to string and try load
+ call check_dpmi ; last chance...
mov al, 110
mov dx, msg_no_dpmi
jmpl error
- or cx, cx
- inc cx
- call load_dpmi
+ ; Set up loadname for next attempt.
+ mov ah, ';' ; Copy until this character
+ call store_env_string ; to "loadname"
+ or al, al ; Check terminating character
+ dec di ; else point at null for next pass.
- mov ax, 0x1687 ; get DPMI entry point
- int 0x2f
- or ax, ax
- and bl, 1 ; 32 bit capable?
+ inc cx
+ cmp si, loadname ; anything there?
+ mov al, [si-1]
+ call test_delim ; is final character a path delimiter
+ movb [si], '\\' ; no, add separator between path & name
+ inc si
- mov [modesw], di ; store the DPMI entry point
- mov [modesw+2], es
- mov [modesw_mem], si
pop di
- pop es
;-----------------------------------------------------------------------------
; Now, find the name of the program file we are supposed to load.
-; xor ah, ah ; termination character (set above!)
+; xor ah, ah ; termination char (set by check_dpmi)
call store_env_string ; copy it to loadname, set bx
mov [stubinfo_env_size], di
ret
;-----------------------------------------------------------------------------
-; load DPMI server if not present
-; First check directory from which stub is loaded, then path, then default
-; On entry di points to image name
+; Check for presence of a DPMI host, and save the mode switch address.
+; Zero flag is clear on success. Clobbers ax/bx/dx.
- .dw 0 ; If stays zero, no path
-
- xor ah, ah ; Copy until this character (=0)
- call store_env_string ; copy stub image to "loadname"
- mov si, bx ; remove name so we can add DPMI name
- mov di, [path_off] ; Pointer to path contents (next try)
- mov ah, ';' ; Copy until this character
- call store_env_string ; to "loadname"
- or al,al ; Check terminating character
- dec di ; else point at null for next pass.
- cmp si, loadname ; anything there?
- je do_exec ; final try (no path) let it return
- mov al, [si-1]
- call test_delim ; is final character a path delimiter
- movb [si], '\\' ; no, add separator between path & name
- inc si
- call do_exec ; copy our name to string and try load
- jc loadloop
+ push es
+ push cx
+ push di
+ push si
+ mov ax, 0x1687 ; get DPMI entry point
+ int 0x2f
+ mov dx, bx
+ or dl, 1 ; bx bit 0: 32-bit capable
+ xor bx, dx
+ or ax, bx ; DPMI present if ax = 0
+ mov [modesw], di ; store the DPMI entry point
+ mov [modesw+2], es
+ mov [modesw_mem], si
+ pop si
+ pop di
+ pop cx
+ pop es
ret
;-----------------------------------------------------------------------------
int 0x21
pop di
pop es
-
- mov ah, 0x4d ;get return code
- int 0x21
- sub ax, 0x300 ;ah=3 TSR, al=code (success)
- neg ax ;CY, if not originally 0x300
jmp restore_umb ;called func. return for us.
;-----------------------------------------------------------------------------
ret
-; Restore upper memory status. All registers and flags preserved.
+; Restore upper memory status. All registers preserved.
- pushf
cmpb [dos_major], 5 ; Won't work before dos 5
push ax
pop bx
pop ax
- popf
ret
;-----------------------------------------------------------------------------
.db "no DPMI selectors$"
.db "no DPMI memory$"
+ .dw 0 ; Points to PATH, stays zero if none.
;-----------------------------------------------------------------------------
; Unstored Data, available during and after mode switch
Frank H. Sapone (emoaddict15@gmail.com) [via djgpp@delorie.com]
2023-01-24 23:36:35 UTC
Permalink
I know you're looking for feedback but I dont use hdpmi32 and don't know of
too many others that do except to run some windows console apps under dos.
Cwsdpmi works just fine for djgpp.

In any case, someone who knows what they're looking at can hopefully chime
in. Just wanted to let you know we're receiving your messages. :)
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
Would appreciate any feedback on this. I know there's a small mistake in one
comment, but the code works.
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
Hi all,
If you've ever tried using hdpmi32 with a djgpp program, you may have
noticed some strange behavior. The program first fails to run with
"Load error: no DPMI", but on the second try, it suddenly works. Then
a third invocation fails again, the fourth runs fine, etc.
When you rename 'hdpmi32.exe' to 'cwsdpmi.exe', your program seems to
run consistently. But this is only because there is a second (real)
cwsdpmi in your PATH somewhere. What really happens, is that your
program alternates between running under hdpmi and cwsdpmi.
I finally figured out why this happens, and it's very simple: hdpmi uses
the exit status to indicate if it was loaded via xms, vcpi, or int15.
And the djgpp stub considers any non-zero exit status to be a failure,
so it keeps searching PATH until cwsdpmi is found, which always returns
zero.
For a possible solution, I would suggest to ignore the return status
from the host, and just check int 2f/1687 after every exec. As an added
bonus, this saves 13 bytes of stub space.
Amended patch follows - it no longer skips the last iteration (exec
with no path).
It's a bit larger, but still saves 6 bytes in total.
--- a/src/stub/stub.asm
+++ b/src/stub/stub.asm
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
; Get DPMI information before doing anything 386-specific
- push es
push di
- xor cx, cx ; flag for load attempt set cx = 0
+ ; Set up loadname in case of no
DPMI.
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+ ; First try current dir.
+ xor ah, ah ; Copy until this character (=0)
+ call store_env_string ; copy stub image to "loadname"
+ mov si, bx ; remove name so we can add DPMI
name
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+ mov di, [path_off] ; Pointer to path contents (next
try)
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+ xor cx, cx ; flag to signal end of loop
+ call check_dpmi ; int 2f, ax=1687
+ call do_exec ; copy our name to string and try
load
try
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+ call check_dpmi ; last chance...
mov al, 110
mov dx, msg_no_dpmi
jmpl error
- or cx, cx
- inc cx
- call load_dpmi
+ ; Set up loadname for next attempt.
+ mov ah, ';' ; Copy until this character
+ call store_env_string ; to "loadname"
+ or al, al ; Check terminating character
+ dec di ; else point at null for next pass.
- mov ax, 0x1687 ; get DPMI entry point
- int 0x2f
- or ax, ax
- and bl, 1 ; 32 bit capable?
+ inc cx
+ cmp si, loadname ; anything there?
+ mov al, [si-1]
+ call test_delim ; is final character a path
delimiter
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+ movb [si], '\\' ; no, add separator between path &
name
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+ inc si
- mov [modesw], di ; store the DPMI entry point
- mov [modesw+2], es
- mov [modesw_mem], si
pop di
- pop es
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
; Now, find the name of the program file we are supposed to load.
-; xor ah, ah ; termination character (set
above!)
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
+; xor ah, ah ; termination char (set by
check_dpmi)
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
call store_env_string ; copy it to loadname, set bx
mov [stubinfo_env_size], di
ret
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
-; load DPMI server if not present
-; First check directory from which stub is loaded, then path, then
default
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
-; On entry di points to image name
+; Check for presence of a DPMI host, and save the mode switch address.
+; Zero flag is clear on success. Clobbers ax/bx/dx.
- .dw 0 ; If stays zero, no path
-
- xor ah, ah ; Copy until this character (=0)
- call store_env_string ; copy stub image to "loadname"
- mov si, bx ; remove name so we can add DPMI
name
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
- mov di, [path_off] ; Pointer to path contents (next
try)
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
- mov ah, ';' ; Copy until this character
- call store_env_string ; to "loadname"
- or al,al ; Check terminating character
- dec di ; else point at null for next pass.
- cmp si, loadname ; anything there?
- je do_exec ; final try (no path) let it return
- mov al, [si-1]
- call test_delim ; is final character a path
delimiter
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
- movb [si], '\\' ; no, add separator between path &
name
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
- inc si
- call do_exec ; copy our name to string and try
load
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
- jc loadloop
+ push es
+ push cx
+ push di
+ push si
+ mov ax, 0x1687 ; get DPMI entry point
+ int 0x2f
+ mov dx, bx
+ or dl, 1 ; bx bit 0: 32-bit capable
+ xor bx, dx
+ or ax, bx ; DPMI present if ax = 0
+ mov [modesw], di ; store the DPMI entry point
+ mov [modesw+2], es
+ mov [modesw_mem], si
+ pop si
+ pop di
+ pop cx
+ pop es
ret
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
int 0x21
pop di
pop es
-
- mov ah, 0x4d ;get return code
- int 0x21
- sub ax, 0x300 ;ah=3 TSR, al=code (success)
- neg ax ;CY, if not originally 0x300
jmp restore_umb ;called func. return for us.
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
ret
-; Restore upper memory status. All registers and flags preserved.
+; Restore upper memory status. All registers preserved.
- pushf
cmpb [dos_major], 5 ; Won't work before dos 5
push ax
pop bx
pop ax
- popf
ret
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
.db "no DPMI selectors$"
.db "no DPMI memory$"
+ .dw 0 ; Points to PATH, stays zero if
none.
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
;-----------------------------------------------------------
------------------
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
; Unstored Data, available during and after mode switch
J.W. Jagersma (jwjagersma@gmail.com) [via djgpp@delorie.com]
2023-01-25 21:10:28 UTC
Permalink
I know you're looking for feedback but I dont use hdpmi32 and don't know of too many others that do except to run some windows console apps under dos.  Cwsdpmi works just fine for djgpp.
In any case, someone who knows what they're looking at can hopefully chime in.  Just wanted to let you know we're receiving your messages. :)
Thanks for the message! I think this is an important patch, hopefully someone
can review it at some point. Although I suppose this should be fixed on the
hdpmi32 side too, so newer hdpmi versions are compatible with old djgpp
programs, and new djgpp programs can work with older hdpmi versions.

As for why someone might want to use hdpmi instead of cwsdpmi, the simple
answer is speed - on the few functions I benchmarked, it's over 20 times
faster. That can add up on things like allocating memory or PM-RM switches.
Plus it implements more (almost all) DPMI 1.0 functions.
Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]
2024-02-27 17:35:29 UTC
Permalink
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
Would appreciate any feedback on this. I know there's a small mistake in one
comment, but the code works.
Post by J.W. Jagersma (***@gmail.com) [via ***@delorie.com]
Hi all,
If you've ever tried using hdpmi32 with a djgpp program, you may have
noticed some strange behavior. The program first fails to run with
"Load error: no DPMI", but on the second try, it suddenly works. Then
a third invocation fails again, the fourth runs fine, etc.
When you rename 'hdpmi32.exe' to 'cwsdpmi.exe', your program seems to
run consistently. But this is only because there is a second (real)
cwsdpmi in your PATH somewhere. What really happens, is that your
program alternates between running under hdpmi and cwsdpmi.
I finally figured out why this happens, and it's very simple: hdpmi uses
the exit status to indicate if it was loaded via xms, vcpi, or int15.
And the djgpp stub considers any non-zero exit status to be a failure,
so it keeps searching PATH until cwsdpmi is found, which always returns
zero.
For a possible solution, I would suggest to ignore the return status
from the host, and just check int 2f/1687 after every exec. As an added
bonus, this saves 13 bytes of stub space.
Amended patch follows - it no longer skips the last iteration (exec
with no path).
It's a bit larger, but still saves 6 bytes in total.
--- a/src/stub/stub.asm
+++ b/src/stub/stub.asm
;-----------------------------------------------------------------------------
; Get DPMI information before doing anything 386-specific
- push es
push di
- xor cx, cx ; flag for load attempt set cx = 0
+ ; Set up loadname in case of no DPMI.
+ ; First try current dir.
+ xor ah, ah ; Copy until this character (=0)
+ call store_env_string ; copy stub image to "loadname"
+ mov si, bx ; remove name so we can add DPMI name
+ mov di, [path_off] ; Pointer to path contents (next try)
+ xor cx, cx ; flag to signal end of loop
+ call check_dpmi ; int 2f, ax=1687
+ call do_exec ; copy our name to string and try load
+ call check_dpmi ; last chance...
mov al, 110
mov dx, msg_no_dpmi
jmpl error
- or cx, cx
- inc cx
- call load_dpmi
+ ; Set up loadname for next attempt.
+ mov ah, ';' ; Copy until this character
+ call store_env_string ; to "loadname"
+ or al, al ; Check terminating character
+ dec di ; else point at null for next pass.
- mov ax, 0x1687 ; get DPMI entry point
- int 0x2f
- or ax, ax
- and bl, 1 ; 32 bit capable?
+ inc cx
+ cmp si, loadname ; anything there?
+ mov al, [si-1]
+ call test_delim ; is final character a path delimiter
+ movb [si], '\\' ; no, add separator between path & name
+ inc si
- mov [modesw], di ; store the DPMI entry point
- mov [modesw+2], es
- mov [modesw_mem], si
pop di
- pop es
;-----------------------------------------------------------------------------
; Now, find the name of the program file we are supposed to load.
-; xor ah, ah ; termination character (set above!)
+; xor ah, ah ; termination char (set by check_dpmi)
call store_env_string ; copy it to loadname, set bx
mov [stubinfo_env_size], di
ret
;-----------------------------------------------------------------------------
-; load DPMI server if not present
-; First check directory from which stub is loaded, then path, then default
-; On entry di points to image name
+; Check for presence of a DPMI host, and save the mode switch address.
+; Zero flag is clear on success. Clobbers ax/bx/dx.
- .dw 0 ; If stays zero, no path
-
- xor ah, ah ; Copy until this character (=0)
- call store_env_string ; copy stub image to "loadname"
- mov si, bx ; remove name so we can add DPMI name
- mov di, [path_off] ; Pointer to path contents (next try)
- mov ah, ';' ; Copy until this character
- call store_env_string ; to "loadname"
- or al,al ; Check terminating character
- dec di ; else point at null for next pass.
- cmp si, loadname ; anything there?
- je do_exec ; final try (no path) let it return
- mov al, [si-1]
- call test_delim ; is final character a path delimiter
- movb [si], '\\' ; no, add separator between path & name
- inc si
- call do_exec ; copy our name to string and try load
- jc loadloop
+ push es
+ push cx
+ push di
+ push si
+ mov ax, 0x1687 ; get DPMI entry point
+ int 0x2f
+ mov dx, bx
+ or dl, 1 ; bx bit 0: 32-bit capable
+ xor bx, dx
+ or ax, bx ; DPMI present if ax = 0
+ mov [modesw], di ; store the DPMI entry point
+ mov [modesw+2], es
+ mov [modesw_mem], si
+ pop si
+ pop di
+ pop cx
+ pop es
ret
;-----------------------------------------------------------------------------
int 0x21
pop di
pop es
-
- mov ah, 0x4d ;get return code
- int 0x21
- sub ax, 0x300 ;ah=3 TSR, al=code (success)
- neg ax ;CY, if not originally 0x300
jmp restore_umb ;called func. return for us.
;-----------------------------------------------------------------------------
ret
-; Restore upper memory status. All registers and flags preserved.
+; Restore upper memory status. All registers preserved.
- pushf
cmpb [dos_major], 5 ; Won't work before dos 5
push ax
pop bx
pop ax
- popf
ret
;-----------------------------------------------------------------------------
.db "no DPMI selectors$"
.db "no DPMI memory$"
+ .dw 0 ; Points to PATH, stays zero if none.
;-----------------------------------------------------------------------------
; Unstored Data, available during and after mode switch
PING? Has anyone reviewed this one?

Loading...