home *** CD-ROM | disk | FTP | other *** search
/ Falcon 030 Power 2 / F030_POWER2.iso / ST_STE / MAGS / ICTARI08.ARJ / ictari.08 / ASSEMBLY / TECH_1.TXT < prev   
Text File  |  1994-02-27  |  10KB  |  166 lines

  1.  
  2.  
  3.                ASSEMBLER PROGRAMMING TECHNIQUES FOR THE ATARI ST
  4.                =================================================
  5.                                 by Peter Hibbs.
  6.  
  7.                   PASSING IN-LINE PARAMETERS TO SUB-ROUTINES
  8.                   ==========================================
  9.  
  10.  
  11.     In common with all  micro-processors,  the  ATARIs 68000 processor uses
  12.     sub-routines for sections of code which  may be repeated more than once
  13.     within a program and it  is  often  necessary  to  pass  data to a sub-
  14.     routine from the calling program.
  15.  
  16.     There are  several  methods  of  passing  data  to  a  sub-routine. The
  17.     simplest method is to load  the  required  values  into data or address
  18.     registers and then call  the  sub-routine  which  then fetches the data
  19.     from these registers. This system is  useful  where the data values are
  20.     variable and sufficient registers are available  but is not ideal where
  21.     a large amount of data (such as a string of text) is to be transferred.
  22.  
  23.     Another method (which is used extensively by the ATARI GEM and BIOS) is
  24.     to push the data values (or the  address  of a string of data) onto the
  25.     stack and then the sub-routine has to  recover the data from the stack.
  26.     This method is fairly flexible but  is somewhat untidy especially where
  27.     several strings of data may need to be passed to the routine.
  28.  
  29.     A third method (which does not seem  to be used much in ATARI software)
  30.     is to pass the data  as  in-line  data  embedded in the calling program
  31.     immediately after the sub-routine  call.  This  method is only suitable
  32.     for fixed data, however,  since  its  value  is  determined at assembly
  33.     time. This system has the advantage  though  that the data concerned is
  34.     easily visible at the point in the program  where it is used and not in
  35.     some look-up table somewhere else in  the source code.  Also the values
  36.     (such as the string data  or  addresses)  can  be easily altered during
  37.     program development.
  38.  
  39.     This article describes this technique with  an example of a sub-routine
  40.     which use in-line data.  With the powerful instruction set of the 68000
  41.     processor the task of accessing  the  data  in the calling program from
  42.     the sub-routine is quite  simple.  For  example, consider the following
  43.     code where the data string 'text string',0  is to be passed to the sub-
  44.     routine PRINT which then sends it to the printer port.
  45.  
  46.                     bsr        print                call sub-routine
  47.                     dc.b       'text string',0      data to be passd
  48.                     even
  49.  
  50.     The calling program  calls  the  required  sub-routine  and immediately
  51.     follows  it  with  the  byte  constants  of  the  required  string  and
  52.     terminated with  a  NUL  (0)  character.  Note  that  since  the string
  53.     consists of byte size data it could  end  on an odd address which would
  54.     cause the processor to generate  an  'address'  error  on return to the
  55.     calling program. The 'even' pseudo-instruction pads out the string with
  56.     a NUL character so  that  the  next  instruction  after the call always
  57.     starts at an even address.
  58.  
  59.     In the sub-routine the code would look something like this :-
  60.  
  61.           print     movem.l    a0/d0,-(sp)          save any registers
  62.                     move.l     8(sp),a0             fetch string address
  63.  
  64.                     sub-routine code                execute sub-routine
  65.  
  66.                     move.l     a0,8(sp)             a0=end of string+1
  67.                     movem.l    (sp)+,a0/d0          restore registers
  68.                     rts                             return
  69.  
  70.     When a sub-routine is called,  the  stack  pointer is first decremented
  71.     and then the current return address is  pushed onto the stack (4 bytes)
  72.     with the stack pointer pointing at the last byte saved. On entry to the
  73.     routine any registers which may be  corrupted  by the routine are first
  74.     pushed onto the stack (as  required).  The  next instruction (using the
  75.     'address register indirect with  displacement'  addressing mode) copies
  76.     the return address from the  stack  into  register a0. The displacement
  77.     value required in this case is 8 since the previous instruction saved 8
  78.     bytes (i.e. two longwords) onto the stack. Address register a0 will now
  79.     be pointing at the first byte of the data string in the calling program
  80.     code, the sub-routine fetches the  data  and  processes it as required.
  81.     When all the data  has  been  processed,  address  register  a0 must be
  82.     pointing at the next word after the  data string in the calling program
  83.     code (i.e. the next main program instruction).
  84.  
  85.     At the end of the  sub-routine  the  address  in address register a0 is
  86.     copied back into the stack  using  the same displacement instruction so
  87.     that the  return  instruction  will  return  program  execution  to the
  88.     correct point in the calling program.  The saved registers are restored
  89.     and the RTS instruction returns control to the calling program.
  90.  
  91.     The following sub-routine  demonstrates  a  practical  example  of this
  92.     technique.
  93.  
  94.     It is often necessary in programs to  load  a memory buffer with a text
  95.     string such as a filename or  message.  This example copies a string of
  96.     data  bytes  into  a  specified  memory  buffer.  The  calling  program
  97.     specifies the address  of the buffer  (as one longword) followed by the
  98.     data string which  is  terminated  with  a  NUL  value.  Since all data
  99.     strings in the ATARI operating system are usually terminated with a NUL
  100.     value, this character is also copied into  the buffer as well as acting
  101.     as a terminator.
  102.  
  103.     The format for the call from the main program is :-
  104.  
  105.                     bsr        copy_string          call sub-routine
  106.                     dc.l       buffer               address of buffer
  107.                     dc.b       'text string',0      string data+NUL
  108.                     even                            ensure even address
  109.                     .
  110.                     .
  111.  
  112.           buffer    ds.b       20                   destination buffer
  113.  
  114.     The operation of the  sub-routine  is  fairly self-explanatory, address
  115.     register a0 is used as a  pointer  to  the  data string, register a1 is
  116.     used as a pointer to the memory  buffer  and register d0 holds the data
  117.     between each fetch and store instruction.
  118.  
  119.     One problem which arises when byte size  data is being passed to a sub-
  120.     routine is that the data may end on an odd address. Since the processor
  121.     can only fetch instructions  from  even  addresses,  the return address
  122.     must be incremented to the next even  address  if it finishes on an odd
  123.     address but not changed if  it  finishes  on  an even address. When the
  124.     data transfer has been completed bit  0  of  the address register a0 is
  125.     tested to see  if  it  is  a  1  (odd  address)  or  0  (even address).
  126.     Unfortunately, the 68000 instruction set  does  not  include a bit test
  127.     instruction which allows this to be done  on an address register so the
  128.     a0 register is  first  copied  into  the  data  register  d0. The least
  129.     significant bit  of d0 is  tested  and  if  it  is  a  0 the routine is
  130.     terminated after first restoring the saved registers. If the bit is a 1
  131.     (an odd address) the a0 register is  incremented by one and the routine
  132.     terminated as before.  The  'even'  pseudo-instruction  in  the calling
  133.     program ensures that the  processor  fetches  the next instruction from
  134.     the correct address.
  135.  
  136.                            COPY_STRING SUB-ROUTINE.
  137.  
  138.     ;ENTRY  destination address defined as in-line data.
  139.     ;       data string defined as in-line data.
  140.     ;EXIT   string data copied into defined buffer
  141.     ;       no registers changed.
  142.  
  143.     copy_string     movem.l    a0-a1/d0,-(sp)       save regs (12 bytes)
  144.                     move.l     12(sp),a0            fetch return address
  145.                     move.l     (a0)+,a1             fetch destination addr
  146.     copy_string1    move.b     (a0)+,(a1)+          copy byte to buffer
  147.                     bne        copy_string1         was it 0 ?, no repeat
  148.                     move.l     a0,d0                copy a0 to d0
  149.                     btst       #0,d0                is address even ?
  150.                     beq        copy_string2         branch if yes
  151.                     addq.l     #1,a0                inc address if not
  152.     copy_string2    move.l     a0,12(sp)            copy ret addr to stack
  153.                     movem.l    (sp)+,a0-a1/d0       restore regs
  154.                     rts                             return
  155.  
  156.  
  157.     The above  routine  was  written  with  the  DEVPAC  2 editor/assembler
  158.     program from HiSoft. There is one point that the programmer should note
  159.     however. When using the Monitor program  to debug the main program, the
  160.     in-line data  following  the  sub-routine  will  confuse  the  debugger
  161.     program when single stepping with the  CTRL  T option (executing a sub-
  162.     routine without stepping through  it).  When  single stepping through a
  163.     program the CTRL Z option  should  be  used and the sub-routine stepped
  164.     through otherwise the debugger program will try and execute the in-line
  165.     data as instructions.
  166.