@L}5 _$% l0$)$$Hȱ$ UhL" `e$$%`$%`  R@P!( L(1   Y I`  d  Ld M * @  $ % CC$$)%1 Udߥ$9%: !0 S$% DD˙`  }J)Lr d M * @  $ % CC$$)%1 Udߥ$9%: !0 S$%} DD˙`  }J)Lr J  ((  p L ()   J}L= ( L 0q A    IB JC;? D W } LL  ` W )LA!  ߰")-݆ p" } $G@LL 08`Q")<2Q0 -G$Ș݆ UL# ; p8(()(0ʥ)NQ` }$GȘ݆LU )L ݆ L GȘ ݆LL )W>Z   HH)H }p h  hyhy D L> L JJ    ! LA*` BF }7'8  M HN H` 8 Z  \LdJJ!"! GFE@F (!L }EE !E^ ^ E E7EȩEdE/EȩE  D } .L }  ;F d  ;?F7F? ( .   Z D LL d } . D  L    p  E` , d)  D L) 0BM݊L݉} ML  N݆ L NLML [ TEqEHȱEqEh 0Gȹ G} HLL GɛL  LFREE SECTORS G) *Gȩ GȽG GȌ*jj >G} C8jJ3j2CD( C202C ԠBX` N 1? l LlD:RAMDISK}.COMLu L1 L ;LHL  T`  `8  ɐ     `TU  } L ? .  t`GBJ ~DEHI B V0dV!}QDEHI VF9 ,0 ,0 s0hhL  L` H hDHEh"}DEL8HI4 0 HI,0 0  9 .G VLO#},0 L4*IJ`llD1:AUTORUN.SYSNEED MEM.SAV TO LOAD THIS FILE.D8:MEM.SAV J y08 B|DEHI$} V0 0`B;DEL`?<0LV`@ʆ v s? F0Ξ05: [ BDEHI%} VY8 B V  @  /DE `E:D8:DUP.SYSERROR-SAVING USER MEMORY ON DISKTYPE Y TO &}STILL RUN DOS B;DE J  (` 9 V⪍ ઍ  -'}LLu ÝDEHILV 9 .l 9 .l  `` s$B BH(}I|DE V BLV nB,DE JLV B V BLVDEIʩ BꭝLu } 3E:}DISK OPERATING SYSTEM II VERSION COPYRIGHT 1984 ATARI CORP.A. DISK DIRECTORY I. FORMAT DISKB. RUN CARTRIDG*}E J. DUPLICATE DISKC. COPY FILE K. BINARY SAVED. DELETE FILE(S) L. BINARY LOADE. RENAME FILE M. RUN AT ADDRES+}SF. LOCK FILE N. CREATE MEM.SAVG. UNLOCK FILE O. DUPLICATE FILEH. WRITE DOS FILES P. FORMAT SINGLEL !N',}#"&))9(&*)/h)''-&؆莟R'S  vL/ˢ L }Insert DOS 2.0s, type Y Λx -}DEfHI 1莏#q! @ y0ɛ8A0,' ȅ 1 1ild! 1L!NO SUCH ITEMSELECT.} ITEM OR FOR MENU! 0 .z:*{}.|{ 1 0 0JB 18L%|DL/}%DIRECTORY--SEARCH SPEC,LIST FILE?[# 0 0 &|D3" 1L!NOT A DISK FILEN !B 1L!E# 1 !BD0}ED:}:1BJ|DE 1DEBHI 1 h0ߢ 0.1}  0?詛 1 y0YЛ 1 ;#L" ;#L! BL1TYPE "Y" TO DELETE...DELETE FILE SPEC2}COPY--FROM, TO?OPTION NOT ALLOWED ASMED3 TXT 232 COPYING---D1:ASMED3.TXTl# 0|D .L/%#3}##JB|DE 1BHID#E 1#0: B 1L!#͑### B 1#c$0SY4}S1}:## # # .#Ƚ# # 𩛙## 1,#PD#ELJ- <.BJD#E 5}1 1HH 0hh|DL%1}:̳# L% #D#EL% 1 0 . .0O% 1L!WILD CARDS NOT A6}LLOWED IN DESTINATION 0 <.|K}N 2 FORMAT. t* 5) 1L!`) 0NΞ 0 L1) 1 L!BAD LOAD FILELOAD FROM WHAT FILE?) 0 ?}0#B 1L!WHAT FILE TO LOCK?) 0 0$B 1L!WHAT FILE TO UNLOCK?DUP DISK-SOURCE,DEST DRIVES?TYPE "Y" IF OK TO US@}E PROGRAM AREACAUTION: A "Y" INVALIDATES MEM.SAV.FE! +L1   `*  70 2 2A} 0.* 1 y0 0)INSERT BOTH DISKS, TYPE RETURN^, 1 y038逍 N, 1L! ,B}C, t*  Lx+, 0 ^, 1 y0 , ,0,0 ,L+ ,I0 ,Vǭ0C}Ξ, 0 }, 1 y0C,ШC, 0K'!" H H 'h h Lx+!EF 5L1L!D,I,HhD}` NOT ENOUGH ROOMINSERT SOURCE DISK,TYPE RETURNINSERT DESTINATION DISK,TYPE RETURNE}`  `8 rL1`-* 1P* 1 y0Y`hhL!NAME OF FILE TO MOVE?- 0 0|DL% <.F},^ 1 70 0 .@L# .BJ 1  DEHIB V L1 ,} 1 70,L.  G}JB|,#P#DE 1 HI BDEHHII 1 B 1 ,^ 1 70,0La- B V,#PH},^ 1 70 0L#L!-* 1P* 1 y0Yj383}mm ݭI}}`8}``|* ? ɛ,`|:-)| / 1L!`DESTINATION CANT BE DOJ}S.SYS0 0H{ 24Δ 28/L!/) 2 Π 2 0 ξK}hAΞB,0 J 1 BDEHI,HÝDE 1HIHIDELSAVE-GIVE L}FILE,START,END(,INIT,RUN)O S0 1`BDEPHI V` S0H 1 L!M}0 0 1L~0`PLEASE TYPE 1 LETTER,0`hhL! 70 1L0L<1 ,;ɛ7,"ɛ:ݦ1ݥN}A"D|ݤD|ȩ:|ȩ|ɛ,,(/+.ީ1 1,ɛ`轤{NAMEO} TOO LONG B VL!` L1I H1EΝDL1|mDiE` V0`8d/8 i:222 1 LP}!ERROR- 128ɛ+,' 20*.. өr2 1``2TOO MANY DIGITSINVALID HEXAQ}DECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8 uR} ECIMAL PARAMETER800 0 8 00`,0'D800 H,ɛh`2L1NEED D1 THRU D8 u The Atari Assembler Editor Reference By Matthew J. W. Ratcliff T} Released 20-NOV-89 I teethed on the Atari Assembler Editor (Asm/Ed) cartridge way back in 198U}2. Now, nearly seven years later, it is becoming more popular than ever. Why? Well, I have seen several mail ordV}er ads over the past year offering Asm/Ed for only $10 or even as little as $5. Here's the hitch, no docW}umentation. A lot of Atari cartridges were left over from the Warner days, when the Tramiel family took X}over the company. It seems that thousands of cartridges were sold "by the pound", with no boxes or documY}entation, just to clear out the warehouses. Now many of you Atarians have decided that Asm/Ed was too good to passZ} up at such a low price, because you just know that someday you will learn assembly language programming.[} This article is for you, the Atarian who took the plunge and bought the Asm/Ed cartridge wit\}hout documentation. I won't pretend to teach you how to write your own assembly language programs (altho]}ugh I'm bound to toss in a bit of free advice along the way), our Boot Camp series will do that job well ^}enough. I hope to give you a quick comparison between BASIC and assembly language, to illustrate the major speed d_}ifferences. I will also cover the mechanics of writing a USR routine to help speed up BASIC programs and`} a stand alone assembly program that may be executed from DOS. The Asm/Ed cartridge will worka} with any DOS (disk operating system) from Atari DOS 2.0s all the way through DOS-XE and even the SpartaDb}OS X cartridge. The Asm/Ed cartridge itself is made up of three basic components, the Editor, Assembler, and c} Debugger. I will present a quick reference for all the commands of each section of the cartridge, and then led}ad you through the creation of your first program. After booting your Atari with Asm/Ed instae}lled, and control is sent to the cartridge, the EDIT prompt will appear. From here you can begin enterinf}g your assembly "source code", with line numbers, assembly mnemonics, and comments. The editor is line og}riented, requiring line numbers. They are used for reference while editing only, and are not used as part of the ph}rogram itself, as in BASIC. Editor i} NEW The NEW command clears all assembly source j}code from memory, providing a clean slate for entry of a new program. NEW will irrevocably erase your prk}ogram from memory, so always be certain to save important code before using this command to start somethil}ng else. I highly recommend using a comment as the first line of every program, similar to the following: m} 10 ;LIST#D:USRTEST1.ASM It is easy to forget what file you are working on, or make a n}typographical error when using the LIST command. Saving a file to the wrong place can ruin a lot of work in a big o}hurry. By placing the LIST command, followed by the correct file name, in a comment, you may simply dispp}lasy that line and use the full screen editor to eliminate the line number and comment character (the semq}icolon), press RETURN, and execute the proper save command every time. This good habit has saved me countless hourr}s of frustration. Use it! DEL This comms}and DELetes lines of code. The format is: DEL xx - Delete line xx from the program. t} DEL xx,yy - Delete lines xx through yy from the program. NUM u} NUMber lines automatically, for fast entry of source code. If no starting number is specified, thev} program begins with the last line number currently in your program, plus 10. Type your code and commentw}s, pressing RETURN when each line is complete. Press RETURN only to stop auto-entry of code. Do NOT use full screx}en editing functions to change lines previously entered, while still in the NUM mode. This will give unpy}redictable results. The command format follows: NUM - Increments by the number 10z} after each line. NUM nn - Begin line entry at line nn,increment by 10. NUM nn,mm - Forces t{}he next statement number to be nn and the increment to be mm. The last command format ma|}y be used to insert new lines between code that already exists (e.g. NUM 11,1 to enter up to 9 lines of c}}ode between lines 10 and 20). REN RENumber the fil~}e. It will resequence all the line numbers of the source file. The command format is below: } REN - Renumber starting with 10, increment by 10. REN nn - Renumber in icrement of nn}, start with 10. REN nn,mm - Renumber by nn, starting with mm. You might think that} you can load a LISTed BASIC program, and use this to renumber it. In fact you can, except that all the GOTO } and GOSUB statements will not be resolved. For very small BASIC programs you can do this, but you are better }off using a renumber utility. When inserting a lot of new code, REN may be used to space the line number}s wide apart, thus allowing entry of more new code with the NUM entry method between consecutive lines of } source code. This is a bit archaic by today's standards, but works well. Should you move on to IBM PC based asse}mblers, or other sophisticated machines, you will find no such animal as a line number. You simply creat}e and edit your source code in a word processor like environment. The assembler can easily resolve all t}he source code and labels without the need for those pesky line numbers. Asm/Ed and Mac/65 users must continue to} deal with them, however. FIND The FIND co}mmand can be used to help locate any string of text anywhere in the program. This is the command format: } FIND/THIS/ - Find the first occurrence of the characters "THIS", and display the line it} is found on. FIND/THIS/A - Find all occurrences of "THIS". Each line is listed to the disp}lay as it is located. Pressing control-1 will throttle screen scrolling. FIND/THIS/xx - Find} the string "THIS" on line number xx. The line is listed, if found. FIND/THIS/xx,yy,A - Find al}l occurrences of "THIS" from lines xx through yy, inclusive. Note that when searching, t}he line numbers themselves are ignored (you don't search the line numbers, when looking for a particular }number). In the examples above the string of interest was delimited by the slash (/) character. Any matched pair }of characters may be used as delimeters. The following would be used to find all occurrences of the slas}h character in your program: FIND */*,A } REP REPlace strings in the file: REP/OLD/NEW/ -} Replace the first occurrence of "OLD" with "NEW". REP/OLD/NEW/,A - Replace ALL occurrences of }"OLD" with "NEW". Use the All option with care. REP/OLD/NEW/xx,yy - Replaces the first occurre}nce of "OLD" with "NEW", in the line number range xx to yy. REP/OLD/NEW/xx,yy,A - Replace all o}ccurrences of "OLD" by "NEW" in lines xx through yy. REP/OLD/NEW/xx,yy,Q - Replace with query. } You will be prompted to press Y for each replace. File Comman}ds The following commands may all be associated with files: LIST -} Display or save lines of source code PRINT - Same as list but omit line numbers ENTER} - Retrieve source program SAVE - Save an object program (assembled code) LO}AD - Load an object program In BASIC filenames are enclosed by quotes, such as SAVE}"D:MYFILE.BAS". In Asm/Ed the filename is preceded by the pound sign (#); no quotes are used. Filenames you may u}se are shown here: #E: - The screen editor, used by default with } some commands such as LIST. #P: - Refers to the printer. #C: - This is} used in reference to the Atari program recorder. #Dn:filename.ext - This is a disk file. The }'n' refers to drive number, which may be from 1 to 8, depending on the DOS and drive configurat}ion you employ. If no drive number is specified, drive number 1 is defaulted. The name of the } file may be up to 8 alphanumeric characters, followed by a period and optional 3 character extender. The ext}ender may be anything you wish. ASM or SRC is generally used for assembly source files, and OB}J or COM for executable object files. LIST } The LIST command is used to display, print, or save to a file assembly source code. The formats are: } LIST - List the entire program to the screen. LIST nn,mm - Display lines nn} through mm. LIST #P: - Print the entire source program. LIST #C: - List the source} code to cassette. LIST #D:FL.ASM - List the entire program to FL.ASM on disk drive number 1. } LIST #D:FT.SRC,10,100 - List lines 10 through 100 to file FT.SRC. Any file}name or device specification may be followed by the line number range specification. The PRINT command functions e}xactly like LIST, except that the line numbers are not output. Since assembly source files REQUIRE line }numbers, it won't be very useful to PRINT your program to disk and attempt to ENTER it later. This would} hopelessly confuse Asm/Ed; always LIST source code to disk. EN}TER The ENTER command is used to retrieve a previously LISTed source file. A valid input dev}ice must be specified such as: ENTER#D:MYFILE.ASM ENTER#C: If you wish t}o merge a program, append a ",M" to the ENTER command, such as: ENTER #D:ROUTINES.ASM,M} This merge works the same as the following sequence would in Atari BASIC: } LOAD "D:MYPROG.BAS" ENTER "D:NEWSUBS.LST" The lines are merged. If any line num}bers in the file to be merged match those of the file already in memory, the merge file takes precedence.} If you wish to append a file to a current working program it may be best to ENTER the merge file first, } RENumber it with some large range such as 20000,1 and then LIST it out to a temporary file. Then ENTER your main }program, and finally enter with the merge option this renumbered file. } SAVE Use the SAVE command to write a block of memory, such as an object program, to a} file. Let's say your program begins at $4000 (with an *=$4000 at the top of your assembly code). After } the ASM command, you see the final address was $41FE. Then, to create a binary image of this file, which may be l}oaded and run later, enter the following command: SAVE #D:MYFILE.OBJ < 4000,41FE } Note that the addresses are always assumed to be in hexadecimal, and you do not specify a dollar sig}n ($) to indicate this on the SAVE command line. You may also SAVE to the cassette (#C:). With the prope}r ASM command, your object files may be created automatically, as we will see. Note that you may assemble your } program in memory, and then go to DOS and use the DOS memory save command to create this object file as well}. (The advantage of the DOS memory save command is that you can specify the RUN address as well, so that} your program automatically executes when you perform a binary load. There are ways to set this up with }the ASM command as well.) ASM Once you have create}d your assembly source code and LISTed it to a file for safe keeping, it is time to assemble it. This is } Asm/Ed's primary function, to convert your source code into executable object code. When you issue the ASM comman}d, the current file in memory is scanned for syntax errors. If it understands all your source code, all }the assembly mnemonics are converted into equivalent binary codes and written to memory or a file. } Care must be taken that your code assembles to an area of memory which does not conflict with your source code}. Before assembling a program for the first time always enter the SIZE command. Three hexadecimal number}s will be displayed, such as: 10F4 1345 9C1F The first number indi}cates where in memory your source code begins, just above DOS's basic memory requirements. The second nu}mber is where, in memory, your source code ends. The final address is the top of useable RAM. At the top of your }program will always be a statement similar to the following: 0 *=$4000 } This tells the assembler to start building your object code at memory location 4000 hexadecimal, the program }origin. This address may be any number between the second and third numbers reported by the SIZE command}, with some notable limitations, when assembling to memory. It may be any value above the first number, }so long as you assemble to a file. If you wish for your program to assemble into lower memory, you } may use the LOMEM command. This must be the first command entered, once you start up Asm/Ed and receive the }EDIT prompt. The format is: LOMEM xxxx, where xxxx is the hexadecimal address to set the new low memory v}alue. This is the first address value reported by the SIZE command detailed above. For example, if you }want your program to load at address $2400, and you know the object code will be 4K or less, then use LOMEM $3400 (}$1000 is 4K bytes). Then ENTER your program, and use *=$2400 at the top of the file to set the origin. }Then the program may be assembled in RAM to RAM safely, so long as your object code does not grow beyond }4K. If you plan to write stand alone assembly programs, which may be loaded from DOS with the} binary 'L'oad command, I recommed an origin of $3400. This will set the start address of your code abov}e both DOS.SYS and DUP.SYS RAM in Atari DOS, any version through DOS-XE, as well as any version of SpartaDOS. } Unlike BASIC, you must manage memory yourself. If your program origin is too close to the second }number from the size command the assembler may get confused. The assembler must build a symbol table and} assign some temporary storage as it processes your source code. It starts building this information from the } end of your source code, and grows upward. If the symbol table runs into the area where the object code is b}eing stored in RAM, the assembler is likely to generate a lot of erroneous PHASE errors. If your origin }is set too high, your object code will run into display memory and eventually out of room. Th}ese problems may be avoided in several ways. The general form of the ASM command is: AS}M #D:SOURCE, #D:LIST, #D:OBJECT The first filename in the ASM command represents the file your } assembly source code is stored in. This allows you to assemble from disk (but not cassette, since Asm/Ed require}s multiple passes through the file). If this field is empty (simply place a comma immediately after the }ASM command), then the source code is assumed to be in memory. The second filename specifies a listing f}ile, where a complete "assembled listing" is routed. This will usually be the printer (#P:). If this field is lef}t empty, the listing goes to the screen. The listing always goes somewhere; it cannot be turned off as i}t can in Mac/65. However, assembler "directives" may be used to control the output of a listing, as we s}hall see. The third field is the filename where the object code will be stored. If this field is not specified, y}our program is assembled to memory. Always make a current listing of your program on disk or cassette be}fore issuing the ASM command. If you have set up memory mapping improperly, the source code will get clob}bered in a big hurry. Assembler Directives Directives, or p}seudo operations (pseudo-ops), are special instructions to the assembler. They can be used to control li}sting format, program title for listing, allocation of memory, and more. In general, assembler directives begin wi}th a period (.), followed by some key word and associated parameters. } OPT The OPTions directive controls assembler output. They are as follows: } .OPT NOLIST - Suppress output of listing during assembly. .OPT LIST - Output assembly} listing, default. .OPT NOOBJ - Do not generate any object code during ass}embly. .OPT OBJ - Output object code, default. .OPT NOERR - Do not d}isplay error messages while assembling. There is no good reason to ever use this option. } .OPT ERR - Display error messages when assembling, default. .O}PT NOEJECT - Do not skip 4 lines at the bottom of each page, when outputting the listing. .OP}T EJECT - Skip 4 lines at the end of each page, default. More than one option may be} placed on a single line, such as .OPT NOLIST,NOOBJ. Note that the Mac/65 assembler defaults to .OPT NOO}BJ; it does not generate object code unless explicitly told to with the .OPT OBJ directive. Asm/Ed is just the opp}osite. Whenever you are assembling your program frequently, working out syntax and undefined label errors}, it is generally wise to have a .OPT NOOBJ near the top of your program. When you are ready to generate} code and start test running it, then change it back to .OPT OBJ. Ti}tle and Page The title and page directives are designed to make your assembly listings easier} to read. The title directive is generally used to specify the name of your program, revision, and date. The } page directive can be used to force a page break and optionally output some text. For example: } 10 .TITLE "Attack Of The Killer Dweebies, Version 1.0" 20 .PAGE "Program equates" } ... ... 200 .PAGE "Graphics Routines" ... ... 300 } .PAGE "High Score Routine" Tab The TAB directive }is used to set the spacing of the fields of your assembly code for listings. The command format is: } 10 .TAB 12, 17, 27 The above example illustrates the defaults used by Asm/Ed. These } may be set to any position you find most suitable for your printer listings. The first number indicates the }field where the mnemonics (assembly opcodes) will appear, the second for the operands, and the third for }the comment field. For example, suppose your program has a lot of long labels with a maximum of 15 chara }cters. Then you may wish to set the tabs as follows: 10 .TAB 20, 25, 40 wh }ich would make for a prettier listing on the printer. BYTE, DBYTE and WORD } The BYTE, DBYTE, and WORD directives are used to reserve storage in memory, similar to variables in } BASIC. Labels may be associated with these directives for easy reference. For example: } 100 LDA STORAGE 110 LDX STORAGE+1 ... 500 STORAGE .BYTE 34, $45 } In the above the statement at line 100 will fetch the first value at location STORAGE, which is } the number 34 following the BYTE directive. In line 110 the X register will receive the data value 45 h }exadecimal. Note that the assembler will perform the address arithmetic "STORAGE+1" automatically. The BYTE direc }tive may also be used to reserve storage for strings, such as: 100 LDA #STRING/$100 } 110 LDX #STRING&$FF ... 320 STRING .BYTE "This is a test", 155 } In line 320 the BYTE directive reserves storage for a string initialized to "This is a test" followed by a 155 ( }ATASCII carriage return). The code in lines 100 and 110 fetches the address of the label STRING, placing } its address high byte in A and low byte in X. This technique will be commonly used to pass the address }of data collections (such as strings or data tables) to subroutines. The DBYTE directive rese }rves two consecutive memory locations, generally used for numbers greater than 256, in high byte, low byt }e order. For example: 1000 DATA .DBYTE 258 The above will result in two byt }es of memory being reserved at location DATA, with the values 1 and 2 respectively (1*256 + 2 equals 258) }. Addresses are stored in low byte, high byte format as expected by the 6502 microprocessor. The WORD directive i }s used for this, such as: 100 *=$3400 110 START LDA #45 . }.. 290 RTS ;End of program 300 *=$2E0 310 .WORD START } In line 100 the origin of the program, or program counter, is set to 3400 hexadecimal. The first line of cod }e, with the label START, will then be assembled into your computer's memory at $3400. At line 300 the pr }ogram counter is reset to $2E0. At line 310 we have the WORD directive, immediately followed by the labe }l START. The assembler will "backtrack" as it processes your source code, realize that START refers to memory loca }tion $3400, and place this value (low byte, high byte sequence) in memory at $2E0, $2E1 respectively. Th !}is is a special location, $2E0, commonly referred to by name as RUNAD in Atari memory maps. When you ass "}emble a program to disk, which will be loaded and run from DOS, you use the above technique to set the run address #}of your program. When the program ends with an RTS, control is returned to DOS. Most game programs do n $}ot end, but you will use this technique for many utilities. As we will see later, a BRK instruction is u %}sed, instead of RTS, when testing programs from Asm/Ed's debugger. L &}abel Directive You do not have string, integer, and floating point variables in assembly lang '}uage, the way you do with Atari BASIC. As we saw above, you must set up your own storage and interpret it (} properly. There are no automatic mechanisms in assembly language for managing variables. To make life easier, y )}ou will want to attach meaningful labels to constant values, such as: 10 RUNAD = $2E0 *} ... 1000 *=RUNAD 1010 .WORD START It is much easier to tel +}l from this example that the intended run address of our program is defined at the label START. In the p ,}revious example for the WORD directive, we simply had the number $2E0. Unless you want to memorize a lot of memory -} locations, employ meaningful labels wherever practical. Labels are used for reference when y .}ou want to GOTO (JMP) or GOSUB (JSR) in assembly language. For example: 10 PROMPT .BYTE /} "PRESS RETURN TO CONTINUE",155 ... 100 LDA #PROMPT/$100 110 LDX #PROMPT&$FF 0} 120 JSR PRINTSTRING ... 500 PRINTSTRING STA ICBADR+1 ;Print the string pointed t 1}o 510 STX ICBADR ;by A & X registers ... Labels may also b 2}e used in branch instructions such as: 50 CONTINUE LDA TABLE,X ... 1 3}00 DEX ; Decrement our loop counter, x register 110 BEQ EXITLOOP 120 BNE CONTINUE 4} 130 EXITLOOP STA RESULT ... In the above example we have set up a loop, similar 5} to a BASIC FOR/NEXT loop, between the labels CONTINUE and EXITLOOP. In line 100 the X register is decre 6}mented by 1 (we assume it was initialized by some code previous to line 50). If the result of the DEX in 7}struction is zero (BEQ) then control will be passed to EXITLOOP. If the X register has not gone to zero (BNE) the 8} control is sent back up to CONTINUE. As a result of DEX the zero flag can only be set (BEQ) or cleared ( 9}BNE), so we have exhausted the possibilities. It would have been equally valid to use: :}120 JMP CONTINUE Generally, whenever you have the choice between a JMP and Bxx (branch) inst ;}ruction, use the branch. It will require less memory and work faster. The problem is that a branch is limited <} to plus or minus about 127 bytes from the current position. If you try to branch too far, you will get an a =}ssembly error. Then JMP instructions, or combinations of JMP and branch instructions may be required. >} Origin Directive We have already used the "*=" directive in ?} many of the previous examples. This tells the assembler to "set the program counter to the following ad @}dress". The address may be some number, or a label, or some expression (so long as the assembler may resolve A} it to a fixed value). Some examples are: 100 *=$3400 ; Always a safe place to start a pro B}gram ... 300 START = $4400 310 *=START ... 500 * C}=START + 439 ... 600 HERE *=*+45 ; Reserve 45 bytes of storage at HERE D} Take note of the spacing used in all of our examples. Any label always begins one space after the line number, r E}eferred to as the label field. The opcode field begins at least one space after the start of the label f F}ield. If a line of code has no label on it, then your assembly mnemonics may begin two spaces after the G}line number. At least one space after the op code field will begin the operand field. This field is optional sinc H}e not all assembly mnemonics have an opcode (such as DEX, or INY). Anything after the operand field is ig I}nored by the assembler, and assumed to be the comment field. A comment can take up an entire line, when J}the label field begins with a semicolon. Below is a sample line of code with all four fields: K} LABEL OP OPERAND COMMENT CODE --|-----|-----|-------|-------------------- L}---------- 10 START LDA #155 ;Get Carriage return character M} IF Directive The IF directive is used for "conditional assembly". This may be used to ena N}ble, or disable the generation of some "test code", for example, based on the value of a number, label, or O} expression. For example: 10 DEBUG = 0 ;Enable my debugging test code ... P} 300 .IF DEBUG @ENDOFDEBUG 310 ; Debugging test routines start here ... Q}500 ENDOFDEBUG ; End of debugging code If the expression (DEBUG above) is equal to zero, then everythin R}g from the line following the IF directive to the specified label (ENDOFDEBUG) is assembled. When you ar S}e satisfied that your code works, don't throw away all that useful testing code. Simply change line 10 t T}o DEBUG = 1 and reassemble your program. If you do not understand the use of conditional assembly, don't worry. U} I have only used it a few times in the past seven years, and generally you don't need it at all. V} END Directive The Asm/Ed manual recommends that every program hav W}e one .END directive, as the last line. It really isn't necessary, since the assembler knows when to sto X}p (it runs out of source code to assemble). If you place a .END in the middle of your program inadverten Y}tly, all code after it will be ignored and not be assembled. I seldom use a .END in any of my assembly code. Z} (continued in asmed2.txt)' 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, typ ]}e 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 o `}f the 6502 registers: DR A=BB X=10 Y=20 P=B0 S=DF a} A is the accumulator, X and Y are the index registers, P is the processor status register (which includes th b}e carry flag, zero flag, and etc.), and S is the stack pointer. c} CR The CR command is used to change the contents of any of the 6502 registers. d} CR<,1,2,,DE The values specified go into the registers in the same order they are display e}ed by the DR command. In the above example the accumulator is unchanged, the X register receives a 1, the Y f} register a 2, the status register remains unchanged, and the stack pointer is adjusted to DE. g} D The D command is used to display memory. D3000,0 tells the q}&?B%DOS SYSB*)DUP SYSBSASMED1 TXTB[ASMED2 TXTB LRAMDISK COMBUINTRO BASBO[AUTORUN SYS debugger to display memory location 3000 hexadecimal. When the second parameter is less than or equal to the r} first, only one location is shown. D3000,3010 requests the debugger to display memory from locations 30 s}00 through 3010. Enter D by itself and the next 8 locations (3011 through 3018) will be displayed. If o t}nly the second parameter is omitted, a default of 8 memory locations are displayed: D300 u}0 3000 10 40 20 22 34 11 12 FE Note that the output of the de v}bugger is always in hexadecimal. All input addresses and register values are to be specified in hex as we w}ll. C The C command is used to change memory. Th x}e format is: C3034<21,23,,2E The command is immediately followed by the star y}ting hexadecimal address to change. The values to be placed in memory, starting at the first location, a z}re 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 14 }0 END 1000 PRINT "COULD NOT FIND USR ROUTINE FILE" 1010 PRINT "MYUSR.OBJ" 1020 E }ND Now we need to write an assembly language program with Asm/Ed that implements this USR rou }tine. 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 w }e 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 par }ameters off? 110 BNE CLEANUP ; when all gone, just the valid return addr 120 ERROR RTS ; is a }t the top of the stack for the RTS 130 ; We have valid input, compute the sum 140 ; The first p }arameter 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, hig }h 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 p }ulled 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 SU }M 350 LDA NUM1+1 ; Now add high bytes, leave carry alone 360 ADC NUM2+1 ; It "carries over" f}rom previous add 370 STA SUM+1 ; And their summation is complete 380 RTS ; Back to BAS}IC 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 writi}ng 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 tak}es a relatively long time to install USR routines by poking them into memory or strings, but once in plac}e they execute amazingly fast. You will find that USR routines are incredibly difficult to de}bug. 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 becau }se 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, a}nd printer output from the Asm/Ed environment. Complete libraries of routines, such as a "graphics packa}ge" 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 for}mat. With the exception of macros (Asm/Ed is not a macro assembler), most changes to Asm/Ed compatibilit}y will be minor. As an example of a stand alone assembly language program, and an illustratio}n 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. (T}his 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 se}e 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.OB%}J 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 B)}NE 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 ru+}n from DOS Now execute the two commands in the first two comment lines at the top of the list,}ing. 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 con.}trol 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 wan0}t to watch the show for a while, and exit to DOS when a KEY is pressed, for example, modify your program as follows1}: 15 CH = 764 ; Keyboard buffer ... 101 LDA #255 1022} CMP CH ; key pressed? 103 BEQ START ; Nope, loop 104 STA CH ; Yes, clear out key buff3}er and exit to DOS List this version to disk and reassemble it. When loaded from DOS, it wil4}l "poke" all those ATASCII patterns to the screen continuously until you press any key on the keyboard. To 5} RANDOMIZE the show, make these changes: 16 RANDOM = 53770 ; Always a random number here 6} ... 50 STORE 60 PUTIT LDA RANDOM ; Get a random fill character 61 STA (7}DINDEX),Y ; Place character on screen Notice how I always added a meaningful label for each8} important memory location. Avoid the use of code such as LDA 53770. The proper use of labels makes it 9}much easier to see exactly WHAT your program does and HOW it gets the job done. If you didn't pay much a:}ttention to ANALOG's Master Memory Map series, I strongly recommend that you go back and read it all. Eve;}n if you do not understand all of it, you will learn a lot. A good memory map is the key to unleashing all the pow<}er 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. Th>}is is a general reference for the 6502 microprocessor, and does not have any specifics on the Atari compu?}ter. It does detail all the 6502 assembly mnemonics, and provides examples of multiply, divide, and other useful r@}outines. When you find that Asm/Ed is too slow to suit your tastes, as you build larger and mA}ore sophisticated programs, consider upgrading to Mac/65. This macro assembler supports the use of INCLUDE B} files, allowing you to easily import "canned routines" that have already been debugged. It's MACRO capabilitiesC} allow you to define high level constructs that vastly simplify the development of assembly programs. WiD}th a good MACRO library (such as OSS/ICD's Mac/65 Toolkit or QuickCode from Stardust Software), your asseE}mbly source code will resemble BASIC or some other high level language, while retaining all the power and speed of F}pure assembly language. Mac/65 is the absolute FASTEST native 6502 assembler I have ever used, bar none.G} (Mad Mac for the Atari ST will assemble 6502 code that blows the doors off Mac/65; but that's a whole nH}ew ball game.) Welcome to the fast and complicated world of assembly language programming. II} hope this guide will inspire you to put that inexpensive Asm/Ed cartridge to work on all those fantastic ideas J} that old faithful Atari BASIC never could handle. By: Matthew J. W. Ratcliff, Ratware Softworks,K} 32 S. Hartnett Ave., St. Louis, MO 63135 68<<  B JKIHiDiELV`L8 8 BLV`LxM}8t8l Lu8hihiHHȱȱL8c !#3`Lu8JJJJ`H 8h`HN}ȩh Q8L8 Z8L8 8L8 8L8 8L8S:@9E:E9H '9 H9I9 8 '9h)0ICO}9D9L8 L :::: :Lr:::IEL[::i:iIIL[:`:i::iQ}::L:`L{:w:w: C`L:L: D8:MEM.SAV: 8| 9 '9`L:L: D:DUP.SYS:̩ 8R} x:ɀL: '9`88 |9Y:X: '9L); D8:DUP.SYS; 8::88 9 '98? :`;WL`; 9S}Ln; ` :Y;Y;L;L;)} Setting Up ATARI 130XE Ram Disk; 9L; ; -9  T} L;D8:; :9 :Y;L@BDFHIKMOQRTVWYZ\^_abcefhijkmnopqrstuvwwxyzz{||}}~~~Y"Y TYPE A KEY TYPE A KEY]} $Y+YpVY0-Y3Y0VYA$Y6Y6Y 7YY^ŗ4Ŗ,*Oȥȥ eem6Y^}eƒЫe揦`YYe`YY`YYȩ-ȩY`YY*Y+Y`YY"/_}`ZZZZZ.ZHZЭYL+ZYЭYЭZh@1Z1Z2Z2Z3ZZMNX)NXi iNX1Z"&YZZԩ`}/Y2Z2Z61Z/Z&YZԬZ/YZ/Y1Zl/Z`ZZPXIZPX JXKXZ JXKX`Z[OX a}POXTOXQXSXZZ8QXZSXZ8ZZJZ*ZPX FXGXZ Y YZ 7Y YZ FXGXZ 7Yb}ZmZ Y Y YQXJJJJZZJJJJZH)8ZZh) ZYH)8ZZh) ZY`[[Z8RXQX ZQX8RXc} QX`ZPX ZZQX Z`[\ZPX ZRXQX ZQXZ mRXQX`"\B\$/Z%0Z@ԩ \!\ \䦆`C\e\3 \Z!\d} "\Z`m\\!/ 6Y Z Z0f\1g\$0Y1`\\ m\\\!X\iRXX\ [Le}\ [L\\i2`\]h\#Y8 Y C\`]P]/Z \0Z!\ "\ Yf\0g\1f}Ԡh\`Q]\] \ \ ]`@Og}h}i}j}k}??B?BB?B?B?B?BBBBBB~~~~~~Bl}BBBBB??B?BB?B?B?B?m}n}o}B?B?B?B?B??B?BBBBBBBB~~~~~~p}~BBBBBBBB?B?B?B?B??B?Bq}r}s}??B?BBB?B?B?BBBBBB~~~t}~~~BBBBBB??B?BBB?B?B?u}v}w}B?B?B?B?B??B?BBBBBBBB~x}~~~~~~BBBBBBBB?B?B?B?B??B?By}z}{}???BB?B?B?B?BBBB|}B~~~~~BBBBB???BB?B?B?B?}}~}}B?B?B?B?B?B?B?BBBB}BBBBB~~~~~~~~BBBBBBBBB?B?B?B?B?B?B?B}}}?B?B?B?B?B?B?B?}BBBBBBB~~~~~~~BBBBBBB?B?B?B?B?B?B?B?}}}0?}<<333g111c1}11c111c111g11 1}X1_1g111c111c111c}331c1c}?01c1g3c1c1c1c1c1?c@1c1?}cb1cw1Ǐcv0xw>߀@@}@@@@}@@@@}@@ ! `pp@@````0@}`````0@?`a|1@1pqc``c`0`@9pQ```0Da0c@}9Z```0Da0`@9Ja``?ƨa0`@9Lc``0a0`@9Df``0a0`@}9Dd``0a0`@g1p@f8ddf8d0`@?p89Ǐ~38|@}@@@@}@@@}@gOǀ@B $$$!H@@B $$!H@C$O}@B '!H@@B@ $!H@@B $D$!@@B$#'}ǀ@P]Q]}EiͩkΩ͙kCopj`j {j`Hi͝Νh`L"SAB.}ORTNI:D"NURͩkΩ͙kCopj`j {j`Hi͝Νh`L"SAB.