-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathatasm.txt
1139 lines (974 loc) · 42.3 KB
/
atasm.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
============================================================================
ATasm v1.08 ("Not a Typewriter Release")
A mostly Mac65 compatible 6502 cross-assembler
Copyright (c) 1998-2015 Mark Schmelzenbach
e-mail: [email protected]
============================================================================
Introduction
Version History
Chapter 1: ATasm
1.1 Installation
1.2 Usage
Chapter 2: 6502 Assembly
2.1 The assembler
2.2 Opcode format
2.3 Operand format
2.4 Operators and expressions
Chapter 3: Compiler directives, Conditional assembly and Macros
3.1 Overview
3.2 *=<addr>
3.3 .DS <word>,*=*+<word>
3.4 .DC <word> <byte>
3.5 <label> = <expression>, <label> .= <expression>
3.6 .BYTE, .SBYTE, .CBYTE
3.7 .DBYTE, .WORD
3.8 .FLOAT
3.9 Conditional assembly (.IF,.ELSE,.ENDIF)
3.10 .INCLUDE filename
3.11 .INCBIN filename
3.12 .ERROR string
3.13 .WARN string
3.14 .OPT directives
3.15 .LOCAL
3.16 .MACRO <macro name>, .ENDM
3.17 .REPT <word>,.ENDR
3.18 .SET 6, <expression>
3.19 .BANK
Chapter 4: Incompatibilities
Chapter 5: A brief digression on writing ATasm
Chapter 6: Bug reports, Feature Requests and Credits
Appendix A: Legal 6502 opcodes
Appendix B: 6502 addressing modes
Appendix C: Undocumented 6502 opcodes
Appendix D: Licensing
============================================================================
Introduction
============================================================================
ATasm was born out of the desire for a fast, Atari specific
cross-assembler. With the recent advent of some quite complete Atari
emulators, I decided to brush the dust off of some (very) old projects
and code a few quick programs. Back in the good old days, when I was
programming on 'real iron,' my favorite assembler was OSS's amazing
Mac/65 cartridge. Sadly, the cartridge was 900 miles away, along with
my trusty 130XE. So, I looked around on the Internet a bit, and found
FTe's disk release of Mac/65 (v4.2). This was usable, but not nearly
as nice as the cartridge version. I also found that over the past few
years, I had become used to writing code on a 132x60 character
display, with instant compile times. I decided to use a
cross-assembler, since that seemed to fulfill my requirements. I tried
out as6502 from UMich, and Fachat's XA. Although both produced solid
code, neither one had all the Atari specific directives and features I
had become accustomed to using Mac/65.
And so, a few days later, ATasm v0.1 was created. For a long period of
time, I continued using ATasm, adding features to the assembler as I
needed them. Now, ATasm is close enough to the original Mac/65 that
the Mac/65 manual provides a good overview for ATasm. In fact, this
manual is very heavily based on the original manual. Reading the
Mac/65 manual in addition to this document is recommended, since they
develop many more examples in greater detail.
If you are familiar with the original product, then you should only
need to read chapter 5, which outlines the known differences between ATasm
and Mac/65.
============================================================================
Version History
============================================================================
version 0.90 - initial public release
version 0.91 - added '-x' command-line option, providing initial .XFD
support
version 0.92 - added '-u' command-line option, providing undocumented
opcodes; also added Appendix C in the manual
version 0.93 - updated e-mail address, removed some spurious warnings when
the .DC directive was used, fixed a problem with indirect
jmp; Thanks to Carsten Strotman for finding this bug!
version 0.94 - fixed embedded ';' in strings, jmp to zero page locations,
mapped 'LDA/STA zero,y => LDA/STA a,y to emulate Mac/65
behavior, a few minor updates to this document
version 0.95 - fixed an error with .incbin that would result in an extra
byte being stored
version 0.96 - fixed an error with missing lines at end of files,
added .OPT ERR/NO ERR, .OPT OBJ/NO OBJ
version 0.97 - fixed a bug with .incbin introduced in the 0.96
version 1.00 - added added several zp, y -> absolute address operators
(sbc/adc/and/eor/ora/cmp); Allowed compilation to
addresses >$fd00; Thanks to Manual Polik for finding these!
Fixed problem with immediate value of a comma: #',
Fixed some serious problems with macro definitions
Explicitly released the package under the GPL
version 1.01 - added raw binary output, fixed a problem with zp,y
version 1.02 - added include path and define command-line options, new .OPT
directive enabling illegal opcodes, fixed a bug with data
commands emiting code without a set origin; Beginning
of a test suite, tweaks to makefile; These changes
were all provided by B. Watson.
version 1.03 - added mapping for zero page JSR, enforce label name
restrictions, added interpretation of #$LABEL (with
warnings); These changes were suggested by Maitthias
Reichl.
version 1.04 - fixed some serious problems with macro expansion, added
fill byte command-line parameter, limited display of
errors and warnings to one pass only, initial support
of multiple passes to prevent the dreaded "PHASE
ERROR", fixed problem with command-line definitions
version 1.05 - added new directives .BANK, .SET 6, and .OPT LIST/NO
LIST; Support for enhanced/single density .ATR files;
Preliminary support for Atari++ snapshot files
version 1.06 - fixed a buffer overflow problem; added -l option to
allow label output; Compiling Windows executable with
mingw
version 1.07 - introduced .BANKNUM operator; Allow .SET 6 to forward
reference labels; Allow leading underscores
in label names; Fixed an error with command-line
defines; Allow character quoting of spaces and
semicolons; Allow comments to start without a
preceding space. Fixed local label references inside
of macros or macro parameters.
version 1.08 - Initial support of list files with -g command-line
parameter; Allow .INCBIN to honor include paths;
Missing state files no longer segfault; Double-forward
defines now throw an error rather than silently
generate bad code
============================================================================
Chapter 1: ATasm
============================================================================
1.1 Installation
The zip file includes the following files:
ATasm.txt: this file
atasm.exe: The Windows executable. This program was compiled with
TDM/MinGW, an excellent free Windows C compiler based
on gcc.
src/*.*: The source code for ATasm, including Makefile.
examples/*.m65: example assembly source code
The program should compile cleanly on all UNIX platforms.
Simply move into the source directory and type 'make'.
Notice that if you want to merge the resultant object code with an
emulator's save state, you will probably also need to get the ZLIB
library. The zlib home page is <http://www.gzip.org/zlib/>
1.2 Usage
Using ATasm is fairly simple. The program is invoked with the
following command line parameters:
atasm [-v] [-s] [-m[fname.state]] [-dsymbol=value] [-Idirectory] <fname.m65>
where:
-v: prints assembly trace
-s: prints symbol table
-u: enables undocumented opcodes
-m[fname]: defines template emulator state file
-x[fname]: saves object file to .XFD/.ATR disk image [fname]
-r: saves object code as a raw binary image
-f[value]: set raw binary fill byte to [value]
-o[fname]: saves object file to [fname]
-d[symbol=value]: pre-defines [symbol] to [value]
-l[fname]: dumps labels to file [fname]
-g[fname]: dumps debug list to file [fname]
-Idirectory: search [directory] for .INCLUDE files
-mae: treats local labels like MAE assembler
The assembly trace and symbol table dump will be sent to stdout. This
can be piped to a file if desired.
Typically, ATasm will generate a single object file 'fname.65o' This
file is in Atari's binary file format, suitable for loading into
machine memory via Atari DOS 2.5 command 'L' (or other similar methods)
However, it is also possible to assemble directly into an emulator's
memory snapshot. Versions of the Atari800 emulator (originally by
David Firth) greater than 0.9.8g, and Atari800Win versions greater
than 2.5c allow the saving and loading of the machine state. ATasm can
read in a state file, compile the source code and produce a new state
file which can then be loaded directly into the emulator with the
'Load Snapshot' option. This version of ATasm is compatible with
versions 2 and 3 of the state file specification format. As of
version 1.05, ATasm can also assemble into the snapshots generated by
Atari++ written by Thomas Richter.
Object code can also be assembled to Atari disk images used by many
Atari and SIO emulators. Disk images can either be in the raw .XFD
format or the the more formalized .ATR format. The disk image must be
either a single density or enhanced density disk formatted with Atari DOS
2.0s, Atari DOS 2.5, or compatible formats.
Ex.:
atasm sample.m65
This will assemble the file sample.m65, and generate an Atari object
file 'sample.65o'.
atasm -v -s sample.m65 | more
This will also generate 'sample.65o', but will also dump the symbol
table and verbose assembly output to the paging program 'more'.
atasm -DBASIC -DOSB= -DFOO=128 sample.m65
This too will generate 'sample.65o', but when assembling the following
defines will be observed:
1) The label 'BASIC' will have a value of 1
2) The label 'OSB' will have a value of 0
3) The lable 'FOO' will have a value of 128
Values specified on the command-line must be numbers. If you are
giving the value in hexadecimal, use the form $xxxx. Notice that the
dollar sign may need to be escaped with a '\' depending on your
command interpreter.
atasm -u iopcode.m65
This will generate the binary file 'iopcode.65o'. However the source file
can include the undocumented 6502 instructions listed in Appendix C.
Without this flag, the undocumented opcodes will generate assembly errors.
Notice that due to their undocumented status, use of these opcodes is not
recommended. However, many demo coders use them effectively -- just be
aware that many emulators may not support their use.
atasm -xdos25.xfd sample.m65
This will generate 'sample.65o' and create the file 'SAMPLE.65O'
on the .XFD image 'dos25.xfd'. There is no space between the -x
and the filename. If the file 'sample.65o' already exists on
the disk image, it WILL be overwritten. Disk images can either be in
the raw .XFD form or the the more formalized .ATR format. The disk
image must be either a single density or enhanced density disk
formatted with DOS 2.0S or 2.5.
atasm -matari800.a8s sample.m65
This will generate 'sample.65o' and create 'sample.a8s' an Atari800
emulator state file. The state file is created by reading in the
previously saved statefile 'atari800.a8s' and overlaying the binary
generated by the assembler. There is no space between the -m and the
filename. If the filename is omitted, ATasm will attempt to load the
default statefile 'atari800.a8s'.
To generate a statefile in Atari800Win, start the emulator, then select
one of option under the File=>Save State pull down menu. In the Atari800
emulator, press F1 to access the emulation menu and select the 'Save State'
option. Once you have a valid statefile, ATasm can use it as a template.
atasm -r sample.m65
This will generate a raw binary image of the object file called
sample.bin. This is useful if you are developing a VCS game to be
loaded in an emulator like stella. The image will start at the lowest
memory location that has been assembled to, and save a complete block
to the highest memory location assembled to. Any intervening space
will be filled with the value of the fill byte. By default, this is
hex value 0xff. To change the fill byte, specify the desired value
with the -f parameter. If you are specifying the byte in hexadecimal,
you may need to escape the '$' depending on your command interpreter.
============================================================================
Chapter 2: 6502 Assembly
============================================================================
2.1 The Assembler
ATasm aims to be as closely backwards compatible as possible to the
original Mac/65 cartridge. However, some limitations imposed by the
relatively small memory size of the 8-bit world have been lifted. See
chapter 4 for a list of differences between the two assemblers.
ATasm is a two-pass assembler, although it will attempt to correct
phase errors with additional passes, if necessary. It will read in the assembly source
one line at a time and, if no errors are encountered, output a binary
file. All input is case-insensitive.
Source lines have the following format:
[line number] [label] [<6502 opcode> <operand>] [ comment ]
A few items to note:
1) Line numbers are optional, and are completely ignored if they exist.
2) Labels can start with the symbols '@','?', or any letter. They
may then consist of any alphanumeric character or the symbol '_'.
Labels may not have the same name as a 6502 opcode
3) Comments must be preceeded by a ';'.
2.2 Opcode format
Refer to Appendix A for a list of valid instruction mnemonics
2.3 Operand format
Operands consist of an arithmetic or logical expression which can
consist of a mixture of labels, constants and equates.
Constants can be expressed either in hexadecimal, decimal,
binary, character or string form.
Hex constants begin with '$'
Ex: $1, $04, $ff, $1A
As used: lda #>$601
.BYTE $02,$04,$08,$10
Binary constants begin with '~'
Ex: ~101, ~11
As used: lda #~11110000
.BYTE ~00011000,~00111100,~01111110
Character constants begin with a single quote (')
Ex: 'a, 'A
As used: lda #'a+$10
.BYTE 'a,'B
Strings are enclosed in double quotes (")
Ex: "Test"
As used: .BYTE "This is a tes",'t+$80
Decimal constants have no special prefix
Ex: 10,12,128
As used: lda #12+8*[3+4]
Often, the format of the operand will determine the addressing mode of
the operator. Refer to Appendix B for a complete breakdown of valid
addressing modes, and examples of their format.
Briefly:
-Immediate operands are prefaced with '#'.
-(operand,X) and (operand),Y designate indirect addressing modes.
-operand,X and operand,Y designate indexed addressing modes.
The symbol '*' designates the current location counter, and can be
used in expression calculations.
Notice that 'A' is a reserved symbol, used for accumulator addressing.
2.4 Operators and expressions
The following operators are grouped in order of precedence. Operators
in the same group will be evaluated in a left to right manner.
Group 1: Parenthesis
[ ] Notice that these parenthesis are really braces! This
allows the assembler to disambiguate parenthetical
expressions from indexing methods
Group 2: Unary operators
> Returns the high byte of the expression.
< Returns the low byte of the expression.
- unary minus, negates an expression.
.DEF <label> Returns true if label is defined.
.REF <label> Returns true if label has been referenced.
.BANKNUM <label> Returns the current bank number of the label.
Group 3: Logical Not
.NOT Returns true if an expression is zero
Group 4: Multiplication and division
/ division
* multiplication
Group 5: Addition and subtraction
+ addition
- subtraction
Group 6: Binary operators
& binary AND
! binary OR
| binary OR (alternative representation)
^ binary EOR
Group 7: Logical comparisons
= equality, logical
> greater than, logical
< less than, logical
<> inequality, logical
>= greater or equal, logical
<= less or equal, logical
Group 8
.OR performs a logical OR
Group 9
.AND performs a logical AND
============================================================================
Chapter 3 Compiler directives, Conditional assembly, and Macros
============================================================================
3.1 Overview
ATasm implements many Mac/65 directives. However, there are several
modifiers that are simply ignored (.END,.PAGE,.TAB,.TITLE), or are
only partially implemented (.SET). For the most part, the important
directives that effect code generation are intact. Some new
directives have been added such as .DS, .INCBIN, .WARN, .BANK, and
.REPT/.ENDR. In addition, non-standard .OPT directives have been
added (see section 3.14)
In the following sections the following notation is used:
<addr> denotes an unsigned word used as a valid Atari address
<float> denotes a floating point number
<word> denotes a word value
<byte> denotes a byte value
<string> denotes a string enclosed in double quotes
<char> denotes a character preceded by a single quote
<label> denotes a legal ATasm label
<macro name> denotes a legal ATasm label used as a macro name
<expression> denotes a legal ATasm expression
<filename> denotes a system legal filename, optionally
enclosed in double quotes
Also, symbols enclosed in brackets '[' ']' are optional.
3.2 *=<addr>
This sets the origin address for assembly.
3.3 .DS <word>
*=*+<word>
(Define Storage) This reserves an area of memory at the
current address equal to size <word>.
3.4 .DC <word> <byte>
(Define Constant storage) This fills an area of memory at the
current address equal to size <word> with the byte value <byte>
3.5 <label> = <expression>
<label> .= <expression>
Assigns the specified label to a given value.
The .= directive allows a label to be assigned different values during
the assembly process. See section 3.17 for an example of using this.
3.6 .BYTE [+<byte>],<bytes|string|char>
Store byte values at the current address. If the first value
is prefaced by a '+', then that value will be used as a constant that
will be added to all the remaining bytes on that line.
Ex:
.BYTE +$80,$10,20,"Testing",'a
will generate:
90 94 D4 E5 F3 F4 E9 EE E7 E1
.SBYTE [+<byte>],<bytes|string|char>
This is the same as the .BYTE directive, but all the byte
values will be converted to Atari screen codes instead of ATASCII
values. This conversion is applied prior to the constant addition.
Ex:
.SBYTE +$80,$10,20,"Testing",'a
will generate:
90 94 D4 B4 F3 F4 E9 EE E7 E1
.CBYTE [+<byte>],<bytes|string|char>
This is the same as the .BYTE directive, except that the final
byte value on the line will be EOR'd with $80.
Ex:
.CBYTE +$80,$10,20,"Testing",'a
will generate:
90 94 D4 E5 F3 F4 E9 EE E7 61
3.7 .DBYTE <words>
Stores words in memory at the current memory address in
MSB/LSB format.
Ex:
.DBYTE $1234,-1,1
will generate:
12 34 FF FF 00 01
.WORD <words>
Stores words in memory at the current memory address in native
format (LSB/MSB).
Ex:
.WORD $1234,-1,1
will generate:
34 12 FF FF 01 00
3.8 .FLOAT <float>
Stores a 6 byte BCD floating point number in the format used
in the Atari OS ROM.
Ex:
.FLOAT 3.14156295,-2.718281828
will generate:
40 03 14 15 62 95 C0 27 18 28 18 28
3.9 .IF <expression>,.ELSE,.ENDIF
These statements form the basis for ATasm's conditional
assembly routines. They allow for code blocks to be assembled or
skipped based on the value of an expression. The expression following
the .IF directive will be evaluated and if true (or non-zero) the
statements following the .IF up to the matching .ELSE or .ENDIF will
be assembled. Otherwise, the code block will be skipped. The .ELSE
block is optional and only needed if you want one block of code to be
assembled when the expression is true and another to be assembled if
the expression is false. The end of the conditional assembly block
must be denoted with the .ENDIF directive.
3.10 .INCLUDE <filename>
Include additional files into the assembly. Using Mac/65,
.INCLUDEs could only be nested one level deep. However, ATasm allows
arbitrary nesting of .INCLUDE files. Quotes around the filename are
optional. Notice that the '#Dn:' filespec is not applicable since
ATasm is not accessing Atari disks (or disk images). Instead, the
current working directory on the host machine will be searched for the
file. The filename can include full path if desired.
3.11 .INCBIN <filename>
This includes the contents of binary file at the current
memory position. This is useful for including character sets, maps
and other large data sets without having to generate .BYTE entries.
3.12 .ERROR <string>
This will generate an assembler error, printing the message
specified in the string parameter. The error will halt assembly.
3.13 .WARN <string>
This will generate an assembler warning, printing the message
specified in the string parameter. The warning will be included in
the warning count at the end of the assembly process.
3.14 .OPT [NO] <string>
This will set or clear specific compiler options. Currently,
ATasm only implements the following options: ERR, OBJ, LIST and ILL.
By default, both ERR and OBJ options are set, while the ILL and LIST
options are off. If ERR is turned off then all warnings that would
normally be sent to the screen will be suppressed. Notice that this
behavior is subtly different than the original Mac/65 program which
suppressed both warnings and errors. OBJ is used to control whether
or not object code is stored in the binary image. Again, behavior is
changed from the original environment. Setting .OPT NO OBJ could be
useful if you wish to use label values in your source code as
reference only, without actually generating code. The ILL opt toggles
illegal opcodes availibitiy. Illegal opcodes can be used inside areas
of code surrounded by .OPT ILL, overriding the command-line parameter.
The LIST opt can be used to override the commandline -v argument
and/or turn off the generation of screen output for certain sections
of source files (for instance, long sections of data).
3.15 .LOCAL
This creates a new local label region. Within each local
region, all labels beginning with '?' are assumed to be unique within
that region. This allows libraries to be build without fear of label
collision. Notice that although Mac/65 was limited to 62 local
regions, ATasm has virtually unlimited regions (65536 regions). Local
labels may be forward referenced like other labels, but they will not
appear the symbol table dump at the end of the assembly processes.
3.16 .MACRO <macro name>, .ENDM
The .MACRO directive must be paired with an .ENDM directive.
All macros must be defined before use. Once defined, a macro can be
called with optional parameters, and are then functionally equivalent
to a user-defined opcode. However, while opcodes are by their very
nature fairly simple, macros can be quite complex. Notice that unlike
Mac/65, macros may NOT have the same name as an existing label. Macro
definitions cannot contain other macro definitions (although they can
use existing macros). All labels within a macro are assumed to be
local to that macro, but can be accessed from outside.
There are two types of macro parameters, expressions and
strings. They can be referenced by using '%' for expression parameters
and '%$' for string parameters followed by a number indicating what
parameter to use. The parameter number can be a decimal number, or a
label enclosed with parenthesis. So, %1 accesses the first parameter as an
expression, and %$1 accesses the first parameter as a string.
Parameter %0 returns the total number of parameters passed to
the macro, and %$0 returns the macro name.
When calling a macro, parameters can be separated either by
commas or by spaces.
Ex:
.MACRO VDLI
.IF %0<>1
.ERROR "VDLI: Wrong number of parameters"
.ELSE
ldy # <%1
ldx # >%1
lda #$C0
sty $0200
stx $0201
sta $D40E
.ENDIF
.ENDM
This macro sets the display list interrupt to the address
passed as its first parameter.
.MACRO ADD_WORD
.IF %0<2 OR %0>3
.ERROR "ADD_WORD: Wrong number of parameters"
.ELSE
lda %1
clc
adc %2
.IF %0=3
sta %3
.ELSE
sta %2
.ENDIF
lda %1+1
adc %2+1
.IF %0=3
sta %3+1
.ELSE
sta %2+1
.ENDIF
.ENDIF
.ENDM
This macro has different results depending on its invocation. If
called with two parameters:
ADD_WORD addr1,addr2
then the word value at addr1 is added to the word value at addr2.
However, if called with three parameters:
ADD_WORD addr1,addr2,addr3
then the result of adding the word values in addr1 and addr2 is stored
in addr3.
For more complicated macro examples, see the Mac/65
instruction manual or examine the included file 'iomac.m65' from the
original Mac/65 install.
3.17 .REPT <word>, .ENDR
The .REPT directive must be paired with an .ENDR directive. All
statements between the directive pair will be repeated <word> number
of times.
Ex:
.rept 4
asl a
.endr
generates:
asl a
asl a
asl a
asl a
and a more complicated example:
table .rept 192
.word [*-table]/2*40
.endr
generates a look-up table starting:
00 00 28 00 50 00 78 00 A0 00 C8 00 F0 00 18 01 ...
which might be useful in a hi-res graphics mode plotting routine.
Another interesting example is inspired by a question from Tom Hunt:
shapes
r .= 0
.rept 8
.dbyte shape1+r*16
r .= r+1
.endr
shape1
r .= 1
.rept 8
.dbyte ~1111000000000000/r
.dbyte ~1100000000000000/r
.dbyte ~1010000000000000/r
.dbyte ~1001000000000000/r
.dbyte ~0000100000000000/r
.dbyte ~0000010000000000/r
.dbyte ~0000001000000000/r
.dbyte ~0000000100000000/r
r .= r * 2
.endr
This will generate 8 instances of an arrow, with each instance shifted
one bit to the right. It also creates a look-up table indexing into
the top of each arrow.
3.18 .SET 6, <expression>
This directive will cause code to assemble to the current location
plus the value of the given expression. This is useful for writing
routines which can be copied from a cartridge area or bank-switched
memory address into RAM.
Note that this is the only .SET directive from the original Mac/65
that is implemented. However, ATasm's implementation is slightly
different. ATasm allows a full expression to be used as a parameter
rather than simply an address. It also allows negative values as well
as positive. Be aware that using forward defined variables inside of
the .SET region to define the expression may cause a phase error.
3.19 .BANK [<word>,<word>]
This directive was suggested by Chris Hutt to assist in building
cartridge images that are greater than 64K in length. Basically, the
.BANK directive will in essence start a new assembly in memory.
However, addresses and labels available in one .BANK can still be
referenced in the next .BANK. When saving the obj file, the banks are
appended. This allows files larger than 64K to be assembled.
So the following produces a 32K file:
*=8000
.include "bank0code.asm"
*=bfff
.byte $ff ; ensure bank takes up exacly 16K
.bank
*=8000
.include "bank1code.asm"
*=bfff
.byte $ff
This directive is also handy for coding loaders that use the INITAD
vector:
.bank
*=$4000
init
.include "initcode.asm"
.bank
*=$2e2 ; when DOS loads an address into 2e2 (INITAD, it will
.word init ; jsr immediately to that location, upon RTS
; it will continue to load...)
.bank
*=$6000
.include "restofthecode.asm"
The .BANK directive can take two optional parameters indicating what
bank should be used, and what bank should be reported by the .BANKNUM
operator. If you wish to return to a previously used bank 0 (and also
append the code in the .obj file), use the following:
.BANK 0,0
If you wish to split the .obj file, but have the .BANKNUM operator
report as bank 0, use:
.BANK ,0
============================================================================
Chapter 4: Incompatibilities with Mac/65
============================================================================
Perhaps most importantly, ATasm works with ASCII files, not ATASCII or
Mac/65 tokenized save files. If you must use a tokenized file there
are programs available to convert tokenized files to ATASCI (or load
the file in Mac/65 and LIST it to disk). Then use a filter program
such as 'a2u' to convert the ATASCII to ASCII.
1) Comment lines only begin with ';' not with '*' -- sorry
2) The character '|' can be used in place of '!' as a binary OR
3) Macros can have arbitrary number of parameters and can be nested
arbitrarily deep during invocation.
4) .INCLUDEs can be arbitrarily nested.
5) There are an unlimited number of .LOCAL regions (well, 65536 of
them)
6) Macro names must be unique and cannot be the same as an existing
label
7) Macro parameters can be separated by commas or by spaces
8) .END,.PAGE,.TAB,.TITLE, and most .SET directives are ignored
9) Extra directives .DC, .DS, .INCBIN, .WARN, .REPT/.ENDR have been
added
10) .OPT ERR, .OPT NO ERR, .OPT OBJ, .OPT NO OBJ have different
behavior than the original (see section 3.14), all other .OPT
directives are ignored.
11) Operands are reserved words and cannot be used as labels or
equates.
12) Operator precedence of unary > and < are given proper precedence.
For instance, Mac/65 will treat #>1000+2000 as #>(1000+2000), not
#(>1000)+2000 as ATasm does. This appears to be a bug in Mac/65.
If you run across other incompatibilities or have a burning desire for
a new feature, send them to me, and I will update this section (and
possibly even update ATasm's behavior)
============================================================================
Chapter 5: A brief digression on writing ATasm
============================================================================
ATasm has been in development on and off for well over five years,
evolving as needs dictated. Unfortunately, this evolution has
resulted in rather patchy code in places. For instance, originally,
the tokenizer was written as a free-form compiler(!). At the time, I
felt that it would be more useful to allow the programmer full freedom
when entering code. However, this decision means that it is then
impossible to distinguish between labels, embedded compiler
directives, and macros. This results in a few of ATasm's amusing
quirks (no embedded '.'s in labels, unique label and macro names, and
probably other darker characteristics).
When programming in 6502 assembly language, I actually tend not to
heavily use macros, conditional assembly or many other of the features
developed to make programming less burdensome. I think this is
because I originally learned assembly on the old Atari Assembler
cartridge, and never unlearned old habits. The upshot is, the macro
facilities are not heavily tested. I have successfully compiled the
sample files that come with the Mac/65 disk based assembler, but
really crazy macros may not give the anticipated result. If you
stumble across code that ATasm incorrectly handles, isolate the
shortest example that you can and send it to me. My e-mail address
can be found at the top of this file.
[Blatant plug] Also be sure to check out EnvisionPC, available at
http://atari.miribilist.com/envision/index.html. This is a very
useful cross-platform graphics utility that runs native on the PC
(Linux/Windows) or on MacOSX. It allows you to easily design all
those nifty Atari character sets and maps. The original Atari based
Envision always begged for a mouse interface... and now it exists.
EnvisionPC is a full-featured character editor and map-maker based on
the original APX Envision graphics utility. It supports ANTIC modes
2-7, 10 font banks loaded concurrently, and map sizes of up to 512x512
characters. Download it and start designing new games today!
============================================================================
Chapter 6: Bug reports, Feature Requests and Credits
============================================================================
This program would not be what it is today without the help of the
following people.
Patches and code contributions:
Mark Schmelzenbach
B. Watson
Dan Horak
Bug Reports and Feature requests:
Cow Claygill
Doug Hodson
Dan Horak
Tom Hunt
Chris Hutt
Manuel Polik
Carsten Stroten
Thompsen
Greg Troutman
B. Watson
...and many others!
============================================================================
Appendix A: Summary of 6502 Opcodes
============================================================================
ADC ADd to accumulator with Carry.
AND binary AND with accumulator.
ASL Arithmetic Shift Left. Bit0=0 C=Bit7.
BCC Branch on Carry Clear.
BCS Branch on Carry Set.
BEQ Branch on result EQual (zero).
BGE Branch Greater than or Equal (alternate form of BCS)
BIT test BITs in memory with accumulator.
BLT Branch Less Than (alternate form of BCC)
BMI Branch on result MInus.
BNE Branch on result Not Equal (not zero).
BPL Branch on result PLus.
BRK forced BReaK.
BVC Branch on oVerflow Clear.
BVS Branch on oVerflow Set.
CLC CLear Carry flag.
CLD CLear Decimal mode.
CLI CLear Interrupt disable bit.
CLV CLear oVerflow flag.
CMP CoMPare with accumulator.
CPX ComPare with X register.
CPY ComPare with Y register.
DEC DECrement memory by one.
DEX DEcrement X register by one.
DEY DEcrement Y register by one.
EOR binary Exclusive-OR with accumulator.
INC INCrement memory by one.
INX INcrement X register by one.
INY INcrement Y register by one.
JMP unconditional JuMP to new address.
JSR unconditional Jump, Saving Return address.
LDA LoaD Accumulator.
LDX LoaD X register.
LDY LoaD Y register.
LSR Logical Shift Right. (Bit7=0 C=Bit0).
NOP No OPeration.
ORA binary OR with accumulator.
PHA PusH Accumulator on stack.
PHP PusH Processor status register on stack.
PLA PulL Accumulator from stack.
PLP PulL Processor status register from stack.
ROL Rotate one bit Left (mem. or acc., C=Bit7 Bit0=C).
ROR Rotate one bit Right (mem. or acc., C=Bit0 Bit7=C).
RTI ReTurn from Interrupt.
RTS ReTurn from Subroutine.
SBC SuBtraCt from accumulator with borrow.
SEC SDt Carry flag.
SED SEt Decimal mode.
SEI SEt Interrupt disable status.
STA STore Accumulator in memory.
STX STore X register in memory.
STY STore Y register in memory.
TAX Transfer Accumulator to X register.
TAY Transfer Accumulator to Y register.
TSX Transfer Stack pointer to X register.
TXA Transfer X register to Accumulator.
TXS Transfer X register to Stack pointer.
TYA Transfer Y register to Accumulator.
============================================================================
Appendix B: 6502 Addressing modes
============================================================================
Absolute: The word following the opcode is the address of the operand.
Ex. LDA $0800
Absolute indexed X: The word following the opcode is added to
register X (as an unsigned word) to give the address of the
operand.
Ex. LDA $FE90,X
Absolute indexed Y: The word following the opcode is added to
register Y (as an unsigned word) to give the address of the
operand.
Ex. LDA $FE90,Y
Accumulator: The operand is the accumulator.
Ex. LSR A
LSR (alternate form)
Immediate mode: The operand is the byte following the opcode.
Ex. LDA #$07
Implied: The operands are indicated in the mnemonic.
Ex. CLC
Indirect absolute: The word following the opcode is the address of a
word which is the address of the operand.
Ex. JMP ($0036)
Relative: The byte following the opcode is added (as a signed word) to
the Program Counter to give the address of the operand.
Ex. BCC $03
Ex. BCC $0803 (alternate form)
Zero page absolute: The byte following the opcode is the address
on page 0 of the operand.
Ex. LDA $1F
Zero page indexed X: The byte following the opcode is added to
register X to give the address on page 0 of the operand.
Ex. LDA $2A,X
Zero page indexed Y: The byte following the opcode is added to
register Y to give the address on page 0 of the operand.
Ex. LDX $2A,Y
*Note* Although technically the opcodes LDA $20,Y and
STA $20,Y are illegal, ATasm (and many other 8-bit assemblers)
will convert this to an absolute indexed addressing mode.
Zero page indexed indirect: The byte following the opcode is added
to register X to give the address on page 0 which contains the
address of the operand.
Ex. LDA ($2A,X)
Zero page indirect indexed: The byte following the opcode is an
address on page 0. This word at this address is added to
register Y (as an unsigned word) to give the address of the
operand.
Ex. LDA ($2A),Y
============================================================================
Appendix C: Atari "Sally" 6502 Undocumented Opcodes - version 3.0, 5/17/1997
============================================================================
Original list by Freddy Offenga ([email protected])
Additional credits: Joakim Atterhal, Adam Vardy, Craig Taylor
References and list sources:
1. Illegal opcodes, WosFilm and Frankenstein,
Mega Magazine #2, December 1991
2. Illegal opcodes v2, WosFilm and Fran-ken-stein,
Mega Maga-zine #6, October 1993
3. Illegal Opcodes der 65xx-CPU, Frank Leiprecht,
ABBUC Sondermagazin 10, Top-Maga-zin Oktober 1991
4. Ergnzung zu den Illegalen OP-Codes, Peter Wtzel,
Top-M-ag-azin Januar 1992.
5. 6502 Opcodes and Quasi-Opcodes, Craig Taylor, 1992
6. Extra Instructions Of The 65XX Series CPU, Adam Vardy,
27 Sept. 1996
This appendix was taken verbatim from a list I was sent some time back. The
formatting has changed, as well as a few opcode names. Errors are probably
due to carelessness on my part, and should not reflect upon the original
compilers of this document. That being said, notice that these are
undocumented opcodes. They may or may not work on many of today's
emulators, and their behavior may not work as advertised even on real
hardware. Use these instructions at your own risk!
ANC
--------------------
AND byte with accumulator. If result is negative then carry is set.
Status flags: N,Z,C
Addressing: Immediate
ARR
-------------------
AND byte with accumulator, then rotate one bit right in accumulator and
check bit 5 and 6:
If both bits are 1: set C, clear V.