Mail Archives: djgpp/1994/11/08/22:44:57
> This would be amazingly useful if you could figure out how to make the
> application load the 16-bit code into the transfer buffer and run it
> there, instead of using a TSR. That way, the user doesn't even need
> to know about it. V2.0 does this for a few functions, like sbrk()
> which can't be run in the segment you're modifying.
It is possible!
I have included a modification of the TSR assembler code, nothing of
the code for reading data (the resident part) has changed, so you can
just use the previus supplied C++ code for testing.
The modified version uses somewhat the same technich as go32.exe uses
when starting it. Start the real mode helper program and specify on the
command line wich program to run, eg. something like go32hlp go32
ownprogram (where go32hlp is the real mode helper). Or if coff2exe was
used, omit the go32 extender part.
This is not an ideal situation either, but it should be enough to
illustrate that the real mode helper doesn't have to reside in a TSR.
The code should be placed in the go32 real mode part or parhaps even
better in the stub program used by coff2exe. This way it would be
possible to include realmode helper functionality for any need.
If you don't want to type the name of the real mode helper every time
you wan't to try out a program then execute the real mode helper with a
new command shell, eg. something like go32hlp command.com. This way it
stays resident until you quit it by typing exit.
Notes on assembling:
--------------------
The program launches command.com to execute the specified program, this
way the path i search. But the code need to know where command.com is
located and I didn't bother to write some code for examine the COMSPEC
environment variable. Please modify the string at label "Program" (line
29) to point at your own command.com before assembling.
---
Kim Jersin
;go32hlp.asm
IDEAL
P386N ; Allow the use of 386 instructions
JUMPS ; Resolove conditional jumps going further than
; 127 bytes
; Defines
INTHANDLE = 65h ; The interrupt used for HLP<=>GPP communication
WRONGINT = 1 ; Error code returned on error when int is used
SEGMENT DSEG WORD 'DATA'
; Importened values
PSP DW ?
MinMem DW ?
; The parameter block parsed to the dos EXEC function
ParamBlock DW 0 ; Use copy of current environment string
ParamCmd DW OFFSET CmdLine ; Pointer to the
DW DSEG ; .. command line
DD ?
DD ?
DD 0
DD 0
; NOTICE: the full path to the command line is hardcoded. The COMSPEC
; environment variable is NOT used. Change it to point at your
; command.com.
Program DB "c:\dos\command.com",0
CmdLine DB 3,"/C "
CmdApp DB 127 DUP (?)
ENDS DSEG
SEGMENT INTSEG PARA 'CODE'
ASSUME cs:INTSEG
ASSUME ds:NOTHING,es:NOTHING
; Code based memory pointers to the storige of the stackpointers during
; the execution of the go32 extended program
StackPt DW ?
StackSS DW ?
GppHlpStr DB "GPPHLP",0
;
; Entry point of the interrupt service
; ------------------------------------
; Available services:
; AX= 6500h - Existens check
; Call this function to check if the interrupt is installed by
; this program. First check the contens of AX and if ok then
; compare the string pointed to by EBX.
; Return: AL= 65h
; AH= 0
; EBX= Linear address of "GPPHLP" string.
; AX= 213Fh - Huge read from file or device
; Like dos function 3Fh, except that it is able to read into a
; huge buffer (larger than 64Kb-1).
; BX= File handler
; ECX= Number of bytes to read
; DS:DX= Linear address of buffer
; Return: EAX= Number of bytes read or error code if the value
; is negative (take the ABS() and you have the
; dos error code as returned by int 21h AH=3Fh).
; Destroyed: EDI ESI, the rest is preserved.
;
PROC RealModeHlp FAR
; Make primary function selection
cmp ah,21h
je @@Dos
cmp ah,65h
je @@GppHlp
jmp @@Chain
@@GppHlp:
;-- GppHlp specific functions --
cmp al,0
jne @@Chain
; Return information that says "alive and well".
xchg al,ah
xor ebx,ebx ; Clear
mov bx,cs
shl ebx,4 ; Calculate the
add ebx,OFFSET GppHlpStr ; linear address
jmp @@End
@@Dos:
;-- Dos functions extended by this TSR --
push OFFSET @@End ; Inforce a near return frame to the
; "one point out" exit.
cmp al,3Fh
je Dos3F
;-- Add additional dos extensions here --
; Not a valid dos extension -
; remove the not needed return address and exit this TSR
add sp,2
jmp @@Chain
@@Chain:
; If coded correctly this would include a call (or jump) to the next
; int handler in the chain (the one installed prior to this TSR).
iret
@@End:
; We inforce all returns from valid functions to go through this label,
; so that any generel cleanup can be done at this point.
iret
ENDP RealModeHlp
;
; Huge read from file or device, using a handler:
; -----------------------------------------------
PROC Dos3F NEAR
ASSUME ds:NOTHING,es:NOTHING
push DS
xor eax,eax ; We havent read any bytes yet
or ecx,ecx
jz @@End
@@Read:
push eax ecx
push bx dx ds ; We don't rely on DOS preserving these
cmp ecx,8000h
jb @@Less32Kb
mov cx,8000h
@@Less32Kb:
mov ah,3Fh
int 21h
movzx edi,ax ; Store the read result
pop ds dx bx
pop ecx eax
jc @@Error
or di,di
jz @@End ; If nothing read than return
add eax,edi ; The new read total
sub ecx,edi ; decreament the counter
jz @@End ; ..and return if it reaches zero
mov di,ds
add di,800h
mov ds,di ; Move the buffer pointer (DS:DX) 32Kb
jmp @@Read
@@Error:
xor eax,eax
sub eax,edi ; The error return code
@@End:
pop ds
ret
@@ToEOF:
add ecx,8000h
jmp @@Read
ENDP Dos3F
;
; Execute the program.
; --------------------
; Entry: MinMem should contain the memory needed by the remaining
; code.
; Return: No return from this function.
; Return is made to DOS.
;
PROC ExecGpp FAR
ASSUME ds:DSEG, es:NOTHING
; Release non used memory
mov ah,4Ah ; Modify memory block
mov es,[PSP]
mov bx,[MinMem]
int 21h
; EXEC
mov dx,OFFSET Program
mov bx,OFFSET ParamBlock
mov ax,ds
mov es,ax
push ds
mov [StackPt],sp
mov [StackSS],ss
mov ax,4B00h
int 21h
mov ss,[StackSS]
mov sp,[StackPt]
pop ds
push ax ; Save for use as return value
; Restore the used interrupt
; -- As mentioned, this should be improved!
push ds
xor dx,dx
mov ds,dx ; Cleared to 0000:0000
mov ah,25h
mov al,INTHANDLE
int 21h
pop ds
; Return value is the one returned from the EXEC call
pop ax
mov ah,4Ch ; Return to dos
int 21h
ENDP ExecGpp
ENDS INTSEG
SEGMENT SSEG PARA 'DATA'
; 128 bytes stack should be enough.
; Notice that the stack is only used during initialization and during
; cleanup after the program exits.
; The stack that is used when called from a GPP program is supplied
; by the dos extender.
DW 24h DUP (?)
SSTop DW ?
ENDS SSEG
; **************************************************************************
; The segments past this point won't be valid after the program goes resident.
; Eg. All the instalation code is thrown away and only the parts
; needed to execute the GPP requests will remain in memory.
;
SEGMENT CSEG PARA 'CODE'
ASSUME cs:CSEG
ASSUME ds:DSEG,es:NOTHING
start:
; Initialize the stack
; This could have been done automatically by using a STACK segment,
; but I don't no how to prevent the linker from placing the STACK
; segment at the end.
mov ax,SSEG
mov ss,ax
mov sp,OFFSET SSTop
mov ax,DSEG
mov ds,ax ; Initialize the the data segment
mov [PSP],es ; The PSP address
; Calculate how much memory is used by this program
mov ax,es ; Start of the program
mov bx,CSEG ; End of last segment used
sub bx,ax
mov [MinMem],bx ; Memory needed, in paragraphs
; Make sure the interrupt handler we want to use ain't taken allready
mov ah,35h
mov al,INTHANDLE
int 21h
mov ax,es
or ax,bx
jnz @@IntError
; Copy the program name including parameters
cld
push ds
mov ax,ds
mov es,ax
mov ds,[PSP]
mov si,80h
movzx cx,[si] ; Length to copy
jcxz @@NoProgram ; No program to execute
inc si ; Command line to execute
mov di,OFFSET CmdLine
add [es:di],cl ; Store length
mov di,OFFSET CmdApp
rep movsb
pop ds
; Install our interrupt handler
; -- Please notice that no chaining is done, this should be improved
; -- if you plan to use this facility in the future.
; -- This is NOT the right way. The services should be installed
; -- using the Multiplex interrupt (INT 2Fh).
push ds
mov dx,INTSEG
mov ds,dx
mov dx,OFFSET RealModeHlp
mov ah,25h
mov al,INTHANDLE
int 21h
pop ds
; Set up the parameter block and jump for execution
mov bx,OFFSET ParamBlock
mov [WORD bx+6],5Ch ;
mov [bx+8],ax
mov [WORD bx+10],6Ch
mov [bx+12],ax
jmp ExecGpp
@@IntErrorMsg:
DB "Error installing go32hlp",13,10
DB "The needed interrupt is used by someone else...",13,10,'$'
@@NoProgramMsg:
DB "Go32hlp load error: No program was specified...",13,10,'$'
@@NoProgram:
mov ax,DSEG
mov ds,ax
mov dx,OFFSET @@NoProgramMsg
jmp @@WriteError
@@IntError:
; Display error message and return to dos
mov dx,OFFSET @@IntErrorMsg
@@WriteError:
push ds
mov ax,cs
mov ds,ax
mov ah,9
int 21h
pop ds
@@Exit:
mov ah,4Ch
mov al,WRONGINT
int 21h
ENDS CSEG
END start
- Raw text -