home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / rexx / dosrexx / rexx88ex.asm next >
Assembly Source File  |  1987-07-09  |  12KB  |  240 lines

  1. ;-REXX88EX.ASM-----------------------------------------------------------------;
  2. ; Sample rexx extension program.                                               ;
  3. ;                                                                              ;
  4. ; This module provides a function named "uppercase" which returns its arguments;
  5. ; uppercased and concatenated into a single string.                            ;
  6. ;                                                                              ;
  7. ; To assemble, link, and install this module as an extension to rexx88r,       ;
  8. ; execute the following rexx program:                                          ;
  9. ;                                                                              ;
  10. ; /* make rexx extension */                                                    ;
  11. ; 'masm rexx88ex,rexx88ex,nul,nul'  /* assemble */                             ;
  12. ; 'link rexx88ex,rexx88ex,nul,nul'  /* link */                                 ;
  13. ; 'exe2bin rexx88ex rexx88ex.com'   /* convert into a com file */              ;
  14. ; 'erase rexx88ex.obj'              /* get rid of intermediate file */         ;
  15. ; 'erase rexx88ex.exe'              /* get rid of intermediate file */         ;
  16. ; 'rexx88ex'                        /* install */                              ;
  17. ;                                                                              ;
  18. ;       Original code by Derek Lieber                                          ;
  19. ;                                                                              ;
  20. ;       Updated 6/23/87 by Sam Detweiler                                       ;
  21. ;                                                                              ;
  22. ;       Added check for LOADED function request (ax==7)                        ;
  23. ;       Added code to check for first in chain and handle accordingly          ;
  24. ;                                                                              ;
  25. ;------------------------------------------------------------------------------;
  26. PROGRAMSEG      segment para public
  27.                 assume cs:PROGRAMSEG, ds:PROGRAMSEG
  28.  
  29.                 org 100H
  30.  
  31. begin:  jmp     start
  32.  
  33. ;-----------------------------------------------------------------------------
  34. ; Data area
  35. ;-----------------------------------------------------------------------------
  36. rexxchain       dd      0               ;link to next rexx extension in chain
  37. myname          db      "uppercase",0   ;name of the function we're supplying
  38. installed_byte  db      '1',0           ;used for ax=7 call
  39. not_installed   db      '0',0           ;used for ax=7 call when we are first
  40. save_call       dw      0               ; place to save request code
  41. RESULT_BUF      equ     0               ;buffer for building result strings
  42.                                         ;(we'll re-use our program segment
  43.                                         ; prefix)
  44.  
  45. ;-----------------------------------------------------------------------------
  46. ; Code area
  47. ;-----------------------------------------------------------------------------
  48. REXX_VECTOR     equ     7CH             ;rexx communication vector
  49. REXX_CALL       equ     5               ;rexx 'call an extension' subfunction
  50. REXX_FUNCLOADED equ     7               ;rexx 'check for extension loaded
  51.  
  52. start:
  53.  
  54.         ;find current head of rexx control chain
  55.  
  56.         xor     ax,ax
  57.         mov     es,ax
  58.         mov     ax,es:[REXX_VECTOR * 4]
  59.         mov     word ptr rexxchain,ax
  60.         mov     ax,es:[REXX_VECTOR * 4 + 2]
  61.         mov     word ptr rexxchain + 2,ax
  62.  
  63.         ;make ourself the new head
  64.  
  65.         mov     word ptr es:[REXX_VECTOR * 4],offset myfunction
  66.         mov     word ptr es:[REXX_VECTOR * 4 + 2],cs
  67.  
  68.         ;terminate, but remain resident
  69.  
  70.         mov     dx,offset program_end   ;pick up our program size (bytes)
  71.         mov     cl,4
  72.         shr     dx,cl                   ;convert to paragraphs
  73.         inc     dx                      ;round up
  74.         mov     ax,3100H                ;terminate-but-remain-resident
  75.         cld                             ;(<--- fix DOS bug)
  76.         int     21H
  77.         jmp     $                       ;should never get here
  78.  
  79. ;
  80. ; Sample rexx extension
  81. ;
  82. ; This sample function simply concatenates its arguments into a string,
  83. ; shifting them to upper case in the process.
  84. ; It might be invoked from rexx via the statment:
  85. ;               say uppercase(one, two, three, ...)
  86. ;
  87. ; On entry:     <ax> == 5 if this is a call to a rexx extension
  88. ;               <ss:bp> points to a stackframe containing the function name,
  89. ;               the number of arguments, and a pointer to an array of pointers
  90. ;               to null terminated argument strings. This "argc, argv" structure
  91. ;               should be familiar to C programmers.
  92. ;               <ax> == 7 then this is a request to see if the function is
  93. ;                       loaded. if names match respond pointing to '1',0
  94. ;
  95. ;
  96. ;
  97. ;
  98. ; On exit:      <ax>==5 <ds:si> points to a null terminated result string
  99. ;               <ax>==7 <ds:si> points to '1',0
  100. ;
  101. ;               (we are installed BELOW REXX processor)
  102. ;
  103. ;               if previous vector 0:0 then for above
  104. ;
  105. ;               <ax>==5 ds:si equals 0:0
  106. ;               <ax>==7 ds:si points to '0',0
  107. ;               ax=-1 and carry set
  108. ;
  109. ; Notes:        1. if ax <> 5 or the function name isn't one we're interested
  110. ;                  in, we pass control up the rexx control chain
  111. ;               2. we don't check for string buffer overflow but we really
  112. ;                  should
  113. ;
  114.  
  115. otherfunction:
  116.         cmp     cs:rexxchain,0                  ; previous link 0?
  117.         jne     ok_to_go_on                     ; no, let it look up the answer
  118.         cmp     ax,REXX_CALL                    ; was this a 'call request'?
  119.         jne     try_loaded                      ; no try loaded
  120.         mov     si,0                            ; no extesnion answered
  121.         mov     ds,si                           ; the call
  122.         jmp     otherdone                       ; done
  123. try_loaded:
  124.         cmp     ax,REXX_FUNCLOADED              ; extension loaded request?
  125.         jne     otherdone                       ; no
  126.         mov     si,offset cs:not_installed      ; say extension not installed
  127.         push    cs                              ;
  128.         pop     ds                              ;
  129. otherdone:
  130.         mov     ax,-1                           ; set error return code
  131.         push    bp                              ; set carry flag
  132.         mov     bp,sp                           ; in callers
  133.         or      word ptr [bp+6],1               ; flags on stack
  134.         pop     bp                              ;
  135.         iret                                    ; and iret preserving int status
  136. ok_to_go_on:
  137.         jmp     cs:[rexxchain]          ;pass control up the rexx control chain
  138.  
  139. myfunction:
  140.  
  141.         ;see if this function call is for us
  142.  
  143.         cmp     ax,REXX_CALL            ;rexx 'call extension' subfunction?
  144.         je      dofunc
  145.         cmp     ax,REXX_FUNCLOADED      ;rexx 'extension loaded' subfunction?
  146.         jne     otherfunction           ;no...
  147.         mov     cs:save_call,ax         ; save function code
  148. dofunc:
  149.         push    ss
  150.         pop     ds                      ;source segment
  151.         mov     si,0[bp]                ;point to function name
  152.         push    cs
  153.         pop     es                      ;destination segment
  154.         mov     di,offset myname        ;point to name we're looking for
  155.         call    scompare                ;are they the same?
  156.         mov     ax,save_call            ;(restore subfunction number)
  157.         jc      otherfunction           ;no...
  158.         cmp     ax,REXX_FUNCLOADED      ;loaded request?
  159.         jne     dofunc1                 ; nope, must be call
  160.         mov     si,offset installed_byte ; point to '1' answer
  161.         push    cs                      ; in code segment
  162.         pop     ds                      ;
  163.         iret                            ; and done
  164.  
  165.         ;gather arguments into a list, upper casing them
  166. dofunc1:
  167.         mov     cx,2[bp]                ;argument count
  168.         mov     bx,4[bp]                ;argument pointer array
  169.         mov     di,RESULT_BUF           ;destination buffer
  170.         jcxz    done                    ;if no arguments, we're done...
  171. gather: mov     si,[bx]                 ;point to the argument string
  172.         call    supper                  ;upper case it into destination buffer
  173.         mov     al,' '
  174.         stosb                           ;append a blank
  175.         add     bx,2                    ;point to next argument pointer in array
  176.         loop    gather                  ;continue
  177. done:   cmp     di,RESULT_BUF           ;is string empty?
  178.         je      done1                   ;yes...
  179.         dec     di                      ;point to trailing space
  180. done1:  mov     al,0
  181.         stosb                           ;null terminate the string
  182.         push    cs
  183.         pop     ds
  184.         mov     si,RESULT_BUF           ;point <ds:si> to result
  185.         iret
  186.  
  187. ;
  188. ;Compare strings for equality, ignoring case
  189. ;
  190. ;Taken:         <ds:si> points to string 1
  191. ;               <es:di> points to string 2
  192. ;Returned:      'nc' indicates "equal", 'c' indicates "not equal"
  193. ;
  194. scompare:
  195.                 cld
  196. scomp1:         lodsb                   ;al := *string1++
  197.                 cmp     al,'A'          ;upper case letter?
  198.                 jb      scomp2          ;no...
  199.                 cmp     al,'Z'          ;upper case letter?
  200.                 ja      scomp2          ;no...
  201.                 or      al,20H          ;convert to lower case
  202. scomp2:         mov     ah,es:[di]
  203.                 inc     di              ;ah := *string2++
  204.                 cmp     ah,'A'          ;upper case letter?
  205.                 jb      scomp3          ;no...
  206.                 cmp     ah,'Z'          ;upper case letter?
  207.                 ja      scomp3          ;no...
  208.                 or      ah,20H          ;convert to lower case
  209. scomp3:         cmp     ah,al           ;equal?
  210.                 jne     scomp4          ;no...
  211.                 cmp     al,0            ;end of both strings?
  212.                 jne     scomp1          ;no...
  213.                 clc                     ;"strings are equal"
  214.                 ret
  215. scomp4:         stc                     ;"strings are not equal"
  216.                 ret
  217.  
  218. ;
  219. ;Uppercase a null terminated string
  220. ;Taken:         <ds:si> points to source
  221. ;               <es:di> points to destination
  222. ;Returned:      <es:di> points to null terminator at destination
  223. ;
  224. supper:         cld
  225. sup:            lodsb                   ;get char
  226.                 cmp     al,'a'          ;lower case letter?
  227.                 jb      sup1            ;no...
  228.                 cmp     al,'z'          ;lower case letter?
  229.                 ja      sup1            ;no...
  230.                 and     al,not 20H      ;convert to upper case
  231. sup1:           stosb                   ;put char
  232.                 or      al,al           ;null terminator?
  233.                 jnz     sup             ;no...
  234.                 dec     di              ;point to null terminator
  235.                 ret
  236.  
  237. program_end     label byte              ;<< end of program marker >>
  238. PROGRAMSEG      ends
  239.                 end     begin
  240.