home *** CD-ROM | disk | FTP | other *** search
- ;
- ; GRDP
- ;
- ; Copyright(c) LADsoft
- ;
- ; David Lindauer, camille@bluegrass.net
- ;
- ;
- ; Dispatch.asm
- ;
- ; Function: OS Function dispatcher
- ; Handles Call to Major function number
- ; Handles generic call to function number
- ; Handles keeping track of last known error
- ;
- ;MASM MODE
- .model small
- .386
- include eprints.inc
-
- PUBLIC TableDispatch, nofunction
-
- .code
- ;
- ; Core dispatch routine. Calls the subfunction indicated in AL
- ; and then set the return address to after the dispatch table
- ; This expects a subfunction code to be on the stack
- ;
- ; As whacked-out a technique as I've seen in awhile. If there's a
- ;more obscure way of doing something really simple, I don't want to see it.
- ;ANYWAY, in addition to a subfunction being on the stack whether we need
- ;one or not, we have the following input conditions:
- ; AL contains the index of the routine to be called
- ; Immediately following the call to this routine, the number of
- ; table elements minus one must be stored right in the code as a
- ; word. Immediately following that count, right in the code of the
- ; routine itself, must be the addresses of all the routines that
- ; can be called, finally followed by the continuing code!
- ;Processing:
- ; 1) Using the return address as a pointer, do a range check on the
- ; index to see if it's in range
- ; 2) Forge a return address to finishup and put it on the stack
- ; 3) Forge a return address to the routine to call, and stack that
- ; 4) Load the subfunction from the caller's stack into AX
- ; 5) Do a near return as a call alias to this function
- ; 6) When the function returns to finishup, get the original caller's
- ; return address back
- ; 7) Use it to get the number of entries in the table
- ; 8) Double the entry count, add 2 bytes for the count and two more
- ; because the count was minus one, and stick that on the stack
- ; 9) Return to the calculated return address, in the process stripping
- ; the subfunction off the stack.
- ;
- ;This entire amazing exercise could have been performed by a single, obvious
- ;instruction: call local_table[bx]
- ;sheeesh
- ;
- TableDispatch PROC
- ENTER 0,0
- xchg bx,[bp+2] ; xchg ret address & ebx
- cmp al,cs:[bx] ; Limit check
- ja short noaction ; Error if too big
- ; Here we call the routine
- push offset cs:finishup ; Return address
- movzx eax,al
- movzx ebx,bx
- push WORD PTR cs:[ebx+2*eax+2] ; Get code address to stack
- xchg bx,[bp+2] ; put things as they were
- mov ax,[bp+4] ; Get the subkey
- cld ; Assume move dir up
- ret ; Go to subroutine
-
- noaction:
- call nofunction ; Register bad function error
- finishup:
- ; Now we have to find the return address
- xchg bx,[bp+2] ; Get return address
- push eax
- movzx eax,word ptr cs:[bx]
- movzx ebx,bx
- lea ebx,[ebx+2*eax+4] ; Get offset to return address
- pop eax
- xchg bx,[bp+2] ; Xchg with orig value of ebx
- LEAVE
- ret 2
- TableDispatch ENDP
- nofunction PROC
- stc ; Set carry flag
- ret
- nofunction ENDP
- END
-
-
-
-
-
-