Visit Atarimax Store


Free-Net Logo
The Atari SIG Historical Archive
Created and hosted by: atarimax.com
[ HOME | GO ATARI | 8-BIT | ST/TT | PORTFOLIO | LYNX | JAGUAR | LIBRARY ]


Article #112 (145 is last):
Newsgroups: freenet.sci.comp.atari.library
From: aa700@cleveland.Freenet.Edu (Michael Current)
Subject: TUTORIAL: Assembler/Editor, pt. 2
Posted-By: xx004 (aa700 - Michael Current)
Reply-To: aa700@cleveland.Freenet.Edu (Michael Current)
Date: Sat Jan 18 12:43:29 1992


Reprinted from A.C.E.C. BBS (614)-471-8559

                                      DEBUGGING
           
          Your assembly language programs are bound to have bugs in them.
          Asm/Ed provides a method for testing assembled object code.  When
          at the Asm/Ed EDIT prompt, type BUG and press return.  The next
          prompt will be DEBUG.  The commands for the debugger are all
          short one or two letter commands, some followed by an optional
          hexadecimal address.  To exit DEBUG type X and press return.
           
                                         DR
           
          The DR command is used to display the contents of the 6502
          registers:
           
               DR
                   A=BB  X=10  Y=20  P=B0  S=DF
           
          A is the accumulator, X and Y are the index registers, P is the
          processor status register (which includes the carry flag, zero
          flag, and etc.), and S is the stack pointer.
           
                                         CR
           
          The CR command is used to change the contents of any of the 6502
          registers.

               CR<,1,2,,DE
           
          The values specified go into the registers in the same order they
          are displayed by the DR command.  In the above example the
          accumulator is unchanged, the X register receives a 1, the Y
          register a 2, the status register remains unchanged, and the
          stack pointer is adjusted to DE.
           
                                          D
           
          The D command is used to display memory.  D3000,0 tells the
          debugger to display memory location 3000 hexadecimal.  When the
          second parameter is less than or equal to the first, only one
          location is shown.  D3000,3010 requests the debugger to display
          memory from locations 3000 through 3010.  Enter D by itself and
          the next 8 locations (3011 through 3018) will be displayed.  If
          only the second parameter is omitted, a default of 8 memory
          locations are displayed:
           
               D3000
                
               3000    10  40  20  22  34  11  12  FE
           
          Note that the output of the debugger is always in hexadecimal.
          All input addresses and register values are to be specified in
          hex as well.
           
                                          C
           
          The C command is used to change memory.  The format is:
           
               C3034<21,23,,2E
           
          The command is immediately followed by the starting hexadecimal
          address to change.  The values to be placed in memory, starting
          at the first location, are separated by commas.  Two commas in a
          row tell the debugger to skip over that memory location, leaving
          it unchanged.  In the above example memory location 3034 receives
          21, 3035 receives 23, and 3037 gets 2E.  You may use the D
          command to display memory just changed, to verify the new values.
           
                                          M
           
          The memory move command, M, is used to copy a block of memory
          from one area to another.  The command format is:
           
               Mmmmm65535 THEN ? "OUT OF RANGE":GOTO 80
               100 PRINT "INPUT NUMBER 2 ";:INPUT N2
               110 IF N2<0 OR N2>65535-N1 THEN ? "OUT OF RANGE":GOTO 100
               120 SUM = USR( 1536, N1, N2 )
               130 PRINT "NUMBER ";N1;" PLUS ";N2;" EQUALS ";SUM
               140 END
               1000 PRINT "COULD NOT FIND USR ROUTINE FILE"
               1010 PRINT "MYUSR.OBJ"
               1020 END
           
          Now we need to write an assembly language program with Asm/Ed
          that implements this USR routine.  It will accept parameters N1,
          and N2 off the stack (two, two byte integers), add them, and
          return the result to SUM through memory locations $D4 and $D5.
          Our code might appear as follows:
           
               0 ;LIST#D:MYUSR.ASM
               10 ;ASM ,,#D:MYUSR.OBJ
               11 SUM = $D4
               12 NUM1 = $E0
               13 NUM2 = $E2
               20  *=1536     ; Assemble for PAGE 6
               30 ADDTHEM PLA ; First off the stack is parameter count
               40  BEQ ERROR  ; Always check for no parameters ERROR
               50  CMP #2     ; Did we get exactly 2 parameters?
               60  BEQ AOK
               70  TAX        ; No, clean up stack and return safely
               80 CLEANUP PLA ; Two bytes per parameter
               90  PLA
               100  DEX       ; Get all the parameters off?
               110  BNE CLEANUP ; when all gone, just the valid return addr
               120 ERROR RTS  ; is at the top of the stack for the RTS
               130 ; We have valid input, compute the sum
               140 ; The first parameter in the USR call (after the addr)
               150 ; is the first parameter off the stack, high byte
               160 ; low byte sequence.  REMEMBER this!
               170 AOK PLA    ; Get NUM1, high byte
               180  STA NUM1+1
               190  PLA       ; Get NUM1, low byte
               200  STA NUM1
               210  PLA       ; Get NUM2, high byte
               220  STA NUM2+1
               230  PLA       ; Get NUM2, low byte
               240  STA NUM2
               250 ; Now we have the data in temporary storage
               260 ; and the stack is cleared of parameters.
               270 ; Just the return address (to get us back to BASIC)
               280 ; is at the top of the stack - which gets pulled off
               290 ; into the program counter automatically by the RTS
               300 ; instruction.
               310  CLC       ; Must clear the carry flag first
               320  LDA NUM1  ; Low byte of first integer to add
               330  ADC NUM2  ; Add to low byte of second integer
               340  STA SUM   ; And store in low byte of their SUM
               350  LDA NUM1+1 ; Now add high bytes, leave carry alone
               360  ADC NUM2+1 ; It "carries over" from previous add
               370  STA SUM+1  ; And their summation is complete
               380  RTS       ; Back to BASIC
           
          Enter this program with Asm/Ed and execute the instructions in
          the first two comment lines.  When you get an assembly with no
          errors, your file D:MYUSR.OBJ should be ready to test with the
          first BASIC program.
           
          Work at this until it performs as expected.  As you become more
          adept at writing USR routines, you may wish to develop utilities
          for converting OBJ files into a series of BASIC DATA statements,
          so you can simply READ and POKE them without using messy file I/O
          to initialize the USR routine.  It takes a relatively long time
          to install USR routines by poking them into memory or strings,
          but once in place they execute amazingly fast.
           
          You will find that USR routines are incredibly difficult to
          debug.  You need to initialize them and call them from BASIC.  If
          you mess up the stack or some other operation, the computer
          usually crashes inexplicably.  It isn't easy to debug USR
          routines from DEBUG, because you will have to write sophisticated
          test routines to stuff all sorts of test values on the stack.
           
                                Stand Alone Assembly

          Sooner or later you will get tired of USR routines (mostly
          because they are so difficult to debug).  When you do, it is time
          to take the plunge into writing a stand alone assembly language
          program.  Then you will get into the complexities of keyboard
          input, screen output, disk I/O, and printer output from the
          Asm/Ed environment.  Complete libraries of routines, such as a
          "graphics package" that performs the equivalent of BASIC's
          GRAPHICS, COLOR, PLOT, and DRAWTO, will become a necessity.  This
          is where BOOT CAMP will help the most.  In the months to come you
          will learn everything from keyboard input to floating point
          processing, all from the assembly language level.  Most of our
          listings are in Mac/65 format.  With the exception of macros
          (Asm/Ed is not a macro assembler), most changes to Asm/Ed
          compatibility will be minor.
           
          As an example of a stand alone assembly language program, and an
          illustration of its raw speed, we present the following
          demonstration.  First type this BASIC program and run it.  While
          it executes (it will take about 12 minutes), read the remainder
          of this article to see how the same functions can be performed in
          assembly language:
           
               10 DINDEX=88:REM Screen RAM pointer
               20 SCREEN=PEEK(DINDEX)+256*PEEK(DINDEX+1)
               30 FOR X=0 TO 255
               40 A=X
               50 FOR Y=0 TO 255
               60 POKE SCREEN+Y,A
               70 NEXT Y
               80 NEXT X
           
          At location DINDEX is a two byte "pointer".  Memory locations 88
          and 89 hold the address of the beginning of screen RAM.  The
          equation in line 20 calculates the variable SCREEN, which we use
          as a direct pointer, for the POKE in line 60.  In our assembly
          language equivalent of the above program, this problem is even
          EASIER to solve.  (This is seldom the case however, most things
          are much harder to do in assembly language.  This demonstration
          is designed purposefully to show the strengths and speed of
          assembly language.)  Next two loops are setup.  The inner Y loop
          is used to poke the current value of X into the first 256 screen
          RAM locations.  You will see these characters fill the top
          portion of your display.  All ATASCII values from 0 through 255
          are poked, with the help of the X loop.  The variable A was used
          simply for a more symmetrical comparison with the assembly code
          to follow.
           
          Let this BASIC program run to completion.  Time it carefully,
          study the sweep second hand of your watch creep slowly along.
          Feel the annoying impatience of this terribly slow program creep
          up your spine.  When you finally get the READY prompt, reboot
          your computer with Asm/Ed and enter this equivalent assembly
          language program:

               0 ;LIST#D:SCREEN.ASM
               1 ;ASM,,#D:SCREEN.OBJ
               2  *=$3400
               3 RUNAD=$2E0
               10 DINDEX = 88 ; Screen RAM pointer
               20 ; We don't have to compute SCREEN, we use post indexed
               addressing
               30 START LDX #0 ; Initialize variables for loops
               40  LDY #0
               50 STORE TXA   ; Place screen character into A register
               60 PUTIT STA (DINDEX),Y ; Place character on screen
               70  INY ; Next screen location
               80  BNE PUTIT ; Y register "wraps around" to zero after 255
               90  INX
               100  BNE STORE ; NEXT X
               110  RTS  ; Return control to DOS
               120  *= RUNAD
               130  .WORD START ; So we can load and run from DOS
           
          Now execute the two commands in the first two comment lines at
          the top of the listing.  If you get no assembly errors then you
          will have a file SCREEN.OBJ that is ready to load and run.  Go to
          DOS and execute a binary 'L'oad of the file SCREEN.OBJ.  It will
          run immediately after loading and return control back to DOS
          after performing all 65,536 "POKES" of characters to screen
          memory.  Did you catch it?  You probably didn't if you blinked.
          This version of the program takes barely a second to run!  If you
          want to watch the show for a while, and exit to DOS when a KEY is
          pressed, for example, modify your program as follows:
           
               15 CH = 764 ; Keyboard buffer
               ...
               101  LDA #255
               102  CMP CH    ; key pressed?
               103  BEQ START ; Nope, loop
               104  STA CH    ; Yes, clear out key buffer and exit to DOS
           
          List this version to disk and reassemble it.  When loaded from
          DOS, it will "poke" all those ATASCII patterns to the screen
          continuously until you press any key on the keyboard.  To
          RANDOMIZE the show, make these changes:
           
               16 RANDOM = 53770 ; Always a random number here
               ...
               50 STORE
               60 PUTIT LDA RANDOM ; Get a random fill character
               61  STA (DINDEX),Y ; Place character on screen
           
           
          Notice how I always added a meaningful label for each important
          memory location.  Avoid the use of code such as LDA 53770.  The
          proper use of labels makes it much easier to see exactly WHAT
          your program does and HOW it gets the job done.

          If you didn't pay much attention to ANALOG's Master Memory Map
          series, I strongly recommend that you go back and read it all.
          Even if you do not understand all of it, you will learn a lot.  A
          good memory map is the key to unleashing all the power of your
          computer.  Compute!'s Mapping The Atari, Revised Edition is also
          a very good reference guide.  As a 6502 Assembly language
          reference manual, I use 6502 Assembly Language Programming by
          Leventhal.  This is a general reference for the 6502
          microprocessor, and does not have any specifics on the Atari
          computer.  It does detail all the 6502 assembly mnemonics, and
          provides examples of multiply, divide, and other useful routines.
           
          When you find that Asm/Ed is too slow to suit your tastes, as you
          build larger and more sophisticated programs, consider upgrading
          to Mac/65.  This macro assembler supports the use of INCLUDE
          files, allowing you to easily import "canned routines" that have
          already been debugged.  It's MACRO capabilities allow you to
          define high level constructs that vastly simplify the development
          of assembly programs.  With a good MACRO library (such as
          OSS/ICD's Mac/65 Toolkit or QuickCode from Stardust Software),
          your assembly source code will resemble BASIC or some other high
          level language, while retaining all the power and speed of pure
          assembly language.  Mac/65 is the absolute FASTEST native 6502
          assembler I have ever used, bar none.  (Mad Mac for the Atari ST
          will assemble 6502 code that blows the doors off Mac/65; but
          that's a whole new ball game.)
           
          Welcome to the fast and complicated world of assembly language
          programming.  I hope this guide will inspire you to put that
          inexpensive Asm/Ed cartridge to work on all those fantastic ideas
          that old faithful Atari BASIC never could handle.
           
          By: Matthew J. W. Ratcliff, Ratware Softworks, 32 S. Hartnett
          Ave., St. Louis, MO  63135


-- 
 Michael Current, Cleveland Free-Net 8-bit Atari SIGOp   -->>  go atari8  <<--
   The Cleveland Free-Net Atari SIG is the Central Atari Information Network
      Internet: currentm@carleton.edu / UUCP: ...!umn-cs!ccnfld!currentm
      BITNET: currentm%carleton.edu@interbit / Cleveland Free-Net: aa700





Visit Atarimax Store