home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / GRDBDL17.ZIP / DISPATCH.ASM < prev    next >
Encoding:
Assembly Source File  |  1998-10-26  |  2.9 KB  |  97 lines

  1. ;
  2. ; GRDP
  3. ;
  4. ; Copyright(c) LADsoft
  5. ;
  6. ; David Lindauer, camille@bluegrass.net
  7. ;
  8. ;
  9. ; Dispatch.asm
  10. ;
  11. ; Function: OS Function dispatcher
  12. ;   Handles Call to Major function number
  13. ;   Handles generic call to function number
  14. ;   Handles keeping track of last known error
  15. ;
  16.     ;MASM MODE
  17.     .model small
  18.     .386
  19. include  eprints.inc
  20.  
  21.     PUBLIC    TableDispatch, nofunction
  22.  
  23.     .code
  24. ;
  25. ; Core dispatch routine.  Calls the subfunction indicated in AL
  26. ; and then set the return address to after the dispatch table
  27. ; This expects a subfunction code to be on the stack
  28. ;
  29. ;    As whacked-out a technique as I've seen in awhile. If there's a
  30. ;more obscure way of doing something really simple, I don't want to see it.
  31. ;ANYWAY, in addition to a subfunction being on the stack whether we need
  32. ;one or not, we have the following input conditions:
  33. ;    AL contains the index of the routine to be called
  34. ;    Immediately following the call to this routine, the number of
  35. ;    table elements minus one must be stored right in the code as a
  36. ;    word. Immediately following that count, right in the code of the
  37. ;    routine itself, must be the addresses of all the routines that
  38. ;    can be called, finally followed by the continuing code!
  39. ;Processing:
  40. ;    1) Using the return address as a pointer, do a range check on the
  41. ;       index to see if it's in range
  42. ;    2) Forge a return address to finishup and put it on the stack
  43. ;    3) Forge a return address to the routine to call, and stack that
  44. ;    4) Load the subfunction from the caller's stack into AX
  45. ;    5) Do a near return as a call alias to this function
  46. ;    6) When the function returns to finishup, get the original caller's
  47. ;       return address back
  48. ;    7) Use it to get the number of entries in the table
  49. ;    8) Double the entry count, add 2 bytes for the count and two more
  50. ;       because the count was minus one, and stick that on the stack
  51. ;    9) Return to the calculated return address, in the process stripping
  52. ;       the subfunction off the stack.
  53. ;
  54. ;This entire amazing exercise could have been performed by a single, obvious
  55. ;instruction: call local_table[bx]
  56. ;sheeesh
  57. ;
  58. TableDispatch    PROC    
  59.     ENTER    0,0
  60.     xchg    bx,[bp+2]        ; xchg ret address & ebx
  61.     cmp    al,cs:[bx]        ; Limit check
  62.     ja    short noaction        ; Error if too big
  63.                     ; Here we call the routine
  64.     push    offset cs:finishup    ; Return address
  65.     movzx    eax,al
  66.     movzx    ebx,bx
  67.     push    WORD PTR cs:[ebx+2*eax+2]    ; Get code address to stack
  68.     xchg    bx,[bp+2]        ; put things as they were
  69.     mov    ax,[bp+4]        ; Get the subkey
  70.     cld                ; Assume move dir up
  71.     ret                ; Go to subroutine
  72.     
  73. noaction:
  74.     call    nofunction        ; Register bad function error
  75. finishup:
  76.     ; Now we have to find the return address
  77.     xchg    bx,[bp+2]        ; Get return address
  78.     push    eax
  79.     movzx    eax,word ptr cs:[bx]
  80.     movzx    ebx,bx
  81.     lea    ebx,[ebx+2*eax+4]    ; Get offset to return address
  82.     pop    eax
  83.     xchg    bx,[bp+2]        ; Xchg with orig value of ebx
  84.     LEAVE
  85.     ret    2
  86. TableDispatch    ENDP    
  87. nofunction    PROC    
  88.     stc                ; Set carry flag
  89.     ret
  90. nofunction    ENDP    
  91. END
  92.     
  93.     
  94.     
  95.     
  96.     
  97.