www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/11/08/22:44:57

Date: Tue, 8 Nov 1994 20:27:25 +0100
From: Kim Jersin <u940422 AT daimi DOT aau DOT dk>
To: dj AT stealth DOT ctron DOT com
Cc: djgpp AT sun DOT soe DOT clarkson DOT edu
Subject: Re: Fast disk I/O in DJGPP programs.

> 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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019