home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / SASC6571.LZX / examples / avg / avg2.a < prev    next >
Encoding:
Text File  |  1996-12-24  |  5.3 KB  |  176 lines

  1. ;-------------------------------------------------------------------------- 
  2. ; Copyright (c) 1989-1993 by SAS Institute Inc., Cary NC, USA
  3. ; All Rights Reserved.
  4. ;
  5. ; Name       : avg2.a
  6. ; Author     : Michael S. Whitcher
  7. ; Date       : 02June92
  8. ; Description:
  9. ; Buildline  : asm avg2.a
  10. ;
  11. ;  Example assembler routine to demonstrate how 
  12. ;
  13. ;  -- to set up parameters being called from a 
  14. ;     C routine using stack and register passing conventions
  15. ;  -- to call a link library function using registerized parameters
  16. ;                     
  17. ;-------------------------------------------------------------------------- 
  18.  
  19.    INCLUDE "exec/macros.i"
  20.    INCLUDE "exec/libraries.i"
  21.    INCLUDE "dos/dos_lib.i"
  22.  
  23. ;-------------------------------------------------------------------------- 
  24. ;  These are the entrypoints defined in this module.
  25.    xdef _avg
  26.    xdef @avg
  27.    xdef _prnts
  28.  
  29. ;-------------------------------------------------------------------------- 
  30. ;  External routines
  31.    xref @__stcd_l
  32.   
  33. ;-------------------------------------------------------------------------- 
  34. ;  External data that I reference
  35. ;  This is actually defined in the link library.
  36.    xref _DOSBase
  37.  
  38.  
  39.  
  40.    section text,code
  41.  
  42. ;-------------------------------------------------------------------------- 
  43. ; long avg(register __d0 int argc, register __a0 char **argv);
  44. ;      -- Computes the average of an array of numbers
  45. ;-------------------------------------------------------------------------- 
  46. ;  This is the stack based entry point into this function  
  47. ;  Move the parameters off the stack and back into register so that
  48. ;  we can drop through to the rest of the routine.
  49. _avg:
  50.    MOVE.L   4(SP),D0
  51.    MOVE.L   8(SP),A0
  52.  
  53. ;-------------------------------------------------------------------------- 
  54. ;  This is the registerized entry point into this function
  55. ;  Nothing extra to do in this case.
  56. @avg:   
  57.  
  58. ;  At function entry register D0 holds argc and A0 holds argv
  59.  
  60. ;  This is how to allocate storage for auto variables.
  61. ;  In this case, we need 4bytes to store the return value from a 
  62. ;  call to stcd_l() 
  63.    SUBQ.W      #4,SP
  64.    
  65. ;  Save the current value of these registers so that we can reuse them
  66. ;  below.  We will restore these registers at function exit.
  67.    MOVEM.L     D5-D7/A3,-(SP)
  68.  
  69. ;  Since argc and argv are both in scratch registers (registers that are 
  70. ;  not saved over function calls), move them to a location where they 
  71. ;  won't be destroyed.
  72.    MOVEA.L     A0,A3
  73.    MOVE.L      D0,D7
  74.    
  75. ;  Do some error checking to make sure argc looks reasonable.
  76.    TST.L       D7
  77.    BGT.B       sumval
  78.  
  79. ;  Error case (argc <= 0). Return an average of zero.
  80.    MOVEQ       #00,D0
  81.    BRA.B       avgret
  82.  
  83. sumval:
  84. ;  Convert the strings into numbers and sum them into register D6
  85. ;  If we get to here we are guaranteed to execute the loop at least once.
  86.    MOVEQ       #00,D6
  87.  
  88. ;  Use D5 as our loop counter
  89.    MOVEQ       #00,D5
  90.  
  91. avgloop:
  92. ;  Convert the number from string format into numeric form
  93. ;  Note:  The '@' on the JSR instruction means that this is the 
  94. ;  registerized parameter version.
  95.    MOVEA.L     (A3)+,A0
  96.    LEA         0010(SP),A1
  97.    JSR         @__stcd_l(PC)
  98.  
  99. ;  Accumulate our total
  100.    ADD.L       0010(SP),D6
  101.  
  102. ;  See if there is more to do
  103. ;  Increment our loop counter and compare against our termination value
  104.    ADDQ.L      #1,D5
  105.    CMP.L       D7,D5
  106.    BLT.B       avgloop
  107.    
  108. ;  Now that we have the sum, compute the average as (total/argc).
  109.    DIVS.W      D7,D6
  110.    EXT.L       D6
  111.    MOVE.L      D6,D0      
  112.  
  113. ;  Done; cleanup and return
  114. avgret:
  115.  
  116. ;  Restore saved registers
  117.    MOVEM.L     (SP)+,D5-D7/A3
  118.  
  119. ;  Release our automatic storage
  120.    ADDQ.W      #4,SP
  121.  
  122. ;  Away we go   
  123.    RTS
  124.  
  125. ;-----------------------------------------------------------------
  126. ; int __asm prnts(register __d0 BPTR fh,  register __a0 char *str);
  127. ;      -- write a string out to the given AmigaDos file handle
  128. ;      -- no error checking is done on the input file handle
  129. ;-----------------------------------------------------------------
  130. ; Setup a single entrypoint for this routine.   Parameters will 
  131. ; always be passed in register.  
  132. _prnts   
  133. ;  Here is our list of saved registers
  134.    MOVEM.L     D3/A3/A6,-(SP)
  135.  
  136. ;  Save the start of the string, because we will need it later
  137.    MOVEA.L     A0,A3
  138.  
  139. ;  We need to find the length of the string
  140. ;  Loop to count the number of characters until we find a NULL byte.
  141. ;  Note:  I use D3 here to hold the length of the string so that I
  142. ;  don't have to do a move when I go to do the write.
  143.  
  144.    MOVEQ       #00,D3
  145. prntloop:   
  146.    TST.B       (A0)+
  147.    BEQ.B       wrtstr
  148.    ADDQ.L      #1,D3
  149.    BRA.B       prntloop
  150.  
  151.  
  152. ;  Load up the needed registers to make the call to AmigaDos to write
  153. ;  out the string.  Note:  I don't have to worry about opening up dos.library
  154. ;  here because it is done for me in the startup code.     
  155. ;  By convention, calls into the AmigaDos libraries are done off of A6, and 
  156. ;  the macros in the header files reflect this.  If you were making several 
  157. ;  calls you would not have to reload this register before each call unless 
  158. ;  you had used it in the interum.
  159. wrtstr:
  160.    MOVE.L      D0,D1
  161.    MOVE.L      A3,D2
  162.    MOVEA.L     _DOSBase(A4),A6
  163.    JSR         _LVOWrite(A6)
  164.    
  165.  
  166. ;  The return value from Write() comes back in register D0 which is just where
  167. ;  we want it to return to our caller.
  168.  
  169.  
  170. ;  Restore saved registers
  171.    MOVEM.L     (SP)+,D3/A3/A6
  172.  
  173. ;  Away we go   
  174.    RTS
  175.    END
  176.