Date: Tue, 8 Nov 1994 20:27:25 +0100 From: Kim Jersin 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