home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------------------------------------------------
- ; Copyright (c) 1989-1993 by SAS Institute Inc., Cary NC, USA
- ; All Rights Reserved.
- ;
- ; Name : avg2.a
- ; Author : Michael S. Whitcher
- ; Date : 02June92
- ; Description:
- ; Buildline : asm avg2.a
- ;
- ; Example assembler routine to demonstrate how
- ;
- ; -- to set up parameters being called from a
- ; C routine using stack and register passing conventions
- ; -- to call a link library function using registerized parameters
- ;
- ;--------------------------------------------------------------------------
-
- INCLUDE "exec/macros.i"
- INCLUDE "exec/libraries.i"
- INCLUDE "dos/dos_lib.i"
-
- ;--------------------------------------------------------------------------
- ; These are the entrypoints defined in this module.
- xdef _avg
- xdef @avg
- xdef _prnts
-
- ;--------------------------------------------------------------------------
- ; External routines
- xref @__stcd_l
-
- ;--------------------------------------------------------------------------
- ; External data that I reference
- ; This is actually defined in the link library.
- xref _DOSBase
-
-
-
- section text,code
-
- ;--------------------------------------------------------------------------
- ; long avg(register __d0 int argc, register __a0 char **argv);
- ; -- Computes the average of an array of numbers
- ;--------------------------------------------------------------------------
- ; This is the stack based entry point into this function
- ; Move the parameters off the stack and back into register so that
- ; we can drop through to the rest of the routine.
- _avg:
- MOVE.L 4(SP),D0
- MOVE.L 8(SP),A0
-
- ;--------------------------------------------------------------------------
- ; This is the registerized entry point into this function
- ; Nothing extra to do in this case.
- @avg:
-
- ; At function entry register D0 holds argc and A0 holds argv
-
- ; This is how to allocate storage for auto variables.
- ; In this case, we need 4bytes to store the return value from a
- ; call to stcd_l()
- SUBQ.W #4,SP
-
- ; Save the current value of these registers so that we can reuse them
- ; below. We will restore these registers at function exit.
- MOVEM.L D5-D7/A3,-(SP)
-
- ; Since argc and argv are both in scratch registers (registers that are
- ; not saved over function calls), move them to a location where they
- ; won't be destroyed.
- MOVEA.L A0,A3
- MOVE.L D0,D7
-
- ; Do some error checking to make sure argc looks reasonable.
- TST.L D7
- BGT.B sumval
-
- ; Error case (argc <= 0). Return an average of zero.
- MOVEQ #00,D0
- BRA.B avgret
-
- sumval:
- ; Convert the strings into numbers and sum them into register D6
- ; If we get to here we are guaranteed to execute the loop at least once.
- MOVEQ #00,D6
-
- ; Use D5 as our loop counter
- MOVEQ #00,D5
-
- avgloop:
- ; Convert the number from string format into numeric form
- ; Note: The '@' on the JSR instruction means that this is the
- ; registerized parameter version.
- MOVEA.L (A3)+,A0
- LEA 0010(SP),A1
- JSR @__stcd_l(PC)
-
- ; Accumulate our total
- ADD.L 0010(SP),D6
-
- ; See if there is more to do
- ; Increment our loop counter and compare against our termination value
- ADDQ.L #1,D5
- CMP.L D7,D5
- BLT.B avgloop
-
- ; Now that we have the sum, compute the average as (total/argc).
- DIVS.W D7,D6
- EXT.L D6
- MOVE.L D6,D0
-
- ; Done; cleanup and return
- avgret:
-
- ; Restore saved registers
- MOVEM.L (SP)+,D5-D7/A3
-
- ; Release our automatic storage
- ADDQ.W #4,SP
-
- ; Away we go
- RTS
-
- ;-----------------------------------------------------------------
- ; int __asm prnts(register __d0 BPTR fh, register __a0 char *str);
- ; -- write a string out to the given AmigaDos file handle
- ; -- no error checking is done on the input file handle
- ;-----------------------------------------------------------------
- ; Setup a single entrypoint for this routine. Parameters will
- ; always be passed in register.
- _prnts
- ; Here is our list of saved registers
- MOVEM.L D3/A3/A6,-(SP)
-
- ; Save the start of the string, because we will need it later
- MOVEA.L A0,A3
-
- ; We need to find the length of the string
- ; Loop to count the number of characters until we find a NULL byte.
- ; Note: I use D3 here to hold the length of the string so that I
- ; don't have to do a move when I go to do the write.
-
- MOVEQ #00,D3
- prntloop:
- TST.B (A0)+
- BEQ.B wrtstr
- ADDQ.L #1,D3
- BRA.B prntloop
-
-
- ; Load up the needed registers to make the call to AmigaDos to write
- ; out the string. Note: I don't have to worry about opening up dos.library
- ; here because it is done for me in the startup code.
- ; By convention, calls into the AmigaDos libraries are done off of A6, and
- ; the macros in the header files reflect this. If you were making several
- ; calls you would not have to reload this register before each call unless
- ; you had used it in the interum.
- wrtstr:
- MOVE.L D0,D1
- MOVE.L A3,D2
- MOVEA.L _DOSBase(A4),A6
- JSR _LVOWrite(A6)
-
-
- ; The return value from Write() comes back in register D0 which is just where
- ; we want it to return to our caller.
-
-
- ; Restore saved registers
- MOVEM.L (SP)+,D3/A3/A6
-
- ; Away we go
- RTS
- END
-