-
Notifications
You must be signed in to change notification settings - Fork 2
/
README.txt
1125 lines (769 loc) · 35.4 KB
/
README.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
ASM6502 Assembler Manual
========================
Copyright 2022-2023 by Bernd Boeckmann
1 Where to get
--------------
Latest source and binaries may be found at:
- https://github.com/boeckmann/asm6502
- https://codeberg.org/boeckmann/asm6502
Binaries are provided for Windows, DOS, and OS/2. A Unix make
file is provided which should be easily adaptable to any ANSI C
conformant compiler.
There is a port of the Commodore 64 KERNAL v3 and BASIC v2 source to
ASM6502. If it is of interest to you, get it at:
- https://github.com/boeckmann/c64krnl
2 Introduction
--------------
ASM6502 is a small two-pass assembler for the MOS Technology 6502
microprocessor used in many home computers of the 8-bit era. It
consists of under 3K lines of C code and can be built with compilers
conformant to the C89 standard.
ASM6502 implements some advanced features, like local labels,
conditional assembly, optimization of opcodes, and the ability to
produce listing files. It is powerful enough to produce byte-exact
replicas of the Commodore C64 KERNAL and BASIC ROMs.
The assembler outputs plain binary files.
The following listing contains a small sample program. It is
the classic hello world for the Commodore C64. To assemble it,
invoke the assembler with the source, output, and listing files as
arguments:
asm6502 helloc64.a65 -o helloc64.prg -l helloc64.lst
1: ; C64 Hello World
2:
3: LOAD_ADDR = $0801
4:
5: .word LOAD_ADDR
6: .org LOAD_ADDR
7:
8: CHROUT = $FFD2
9: SYS = $9E
10:
11: basic_upstart:
12: .word @end, 10
13: .byte SYS, " 2062",0
14: @end .word 0
15:
16: start:
17: ldx #0
18: @l lda hello@msg,x
19: jsr CHROUT
20: inx
21: cpx #hello@len
22: bne @l
23: rts
24:
25: hello:
26: @msg .byte "HELLO, WORLD!", CR, LF
27: @len = @ - @msg
28:
29: CR = 13
30: LF = %1010
3 Concepts and Terminology
--------------------------
The task of an assembler is to translate an _assembler
source_ containing human-readable _instructions_ to a _binary
representation_ the processor understands. This binary
representation is called _machine code_. There is a one-to-one
mapping between the human-readable instructions contained in the
assembler source and the generated machine code.
Each instruction a processor understands is given a name, called
_mnemonic_. This name is chosen so that it describes to the
programmer what the instruction does. Every instruction is also
assigned a numeric value, called the operation code or _opcode_.
This is what gets written by the assembler as machine code to an
output file. The opcode is interpreted by the processor to decide
what to do.
Beside the instruction itself, additional information may be
required to process it. The additional information is provided in
the source by one or more _arguments_ following the mnemonic. In
machine code this additional information is encoded in binary form
following the opcode.
`ADC #42' is an example of an instruction, where ADC is the
mnemonic identifying the instruction, and #42 is the argument. This
particular instruction, understood by the MOS6502 processor, adds
the value 42 to the value stored in processor register A. It then
writes the result back to A.
The set of instructions a CPU understands is called _instruction
set_. There are many different kinds of CPUs and instruction sets.
As a result, there is not something like `the assembler', but there
are many of them, all adapted to one or more specific instruction
sets. ASM6502 is an assembler that is adapted to the instruction set
of the MOS6502 processor family.
Beside generating an output file containing machine code, ASM6502
may also generate a _listing file_ containing a _program listing_.
This listing shows the lines of the assembler source side-by-side to
the generated machine code in hexadecimal notation.
Pos Addr Code Line# Assembler text
0000 0000 69 2A 1: ADC #42
0002 0002 E8 2: INX
Pos indicates the position of the instructions regarding the output
file. Addr represents the _location_ or _address_ of the code while
it is executed.
Let's further elaborate what the arguments to instructions may be.
In the example above, `#42' is a numeric value that is directly used
to do the addition. It is therefore called an _immediate_ value, and
the mode the processor operates in is called _immediate addressing_
mode. The `INX' instruction above implicitly operates on a register
called X. For this reason it is called _implicit addressing_. Often,
the argument specifies a memory location. This memory location may
be given relative to the start of the address space. This it is
called _absolute addressing_. If the memory location is specified
relative to some other location, we call it _relative addressing_.
Sometimes one does not want to encode a fixed memory location into
the machine instruction, but instead use the content of some memory
location as the address to operate on. This is called _indirect
addressing_.
The sequence of instructions executed by the processor may be
altered by the programmer utilizing special machine instructions.
Some of these instructions modify this sequence unconditionally,
and some alter it if a special condition is met. The instructions
are called _jump_ or _branching_ instructions. The information of
the _jump target_ is encoded as address within the instruction. The
assembler supports the programmer by letting him specify a jump
target by giving it a name, called _label_. In the introductory
example, `basic_upstart', `start', and `hello' are labels.
One task of an assembler is to assign an address to every label the
programmer defines. Sometimes this is not that easy. For example,
a label may be used as a jump target before it is defined in the
assembler source. This is called _forward-reference_. That is the
reason ASM6502 is a so called two-pass assembler. In the first pass,
the assembler processes the whole file to determine the addresses of
all labels. In the second pass all required information is provided,
and the machine code is generated.
Using forward-references can sometimes lead to non-optimal machine
code, because the assembler has to guess the size of the forward-
referenced `thing'. In that case the programmer can support the
assembler by giving a hint what type the referenced `thing' is. Some
_multi-pass assemblers_ process the source more than two times and
can optimize the machine code even in cases they encounter forward-
referenced labels. But for the sake of simplicity ASM6502 does not
do that.
Beside labels the programmer may also define _variables_. Variables
may be assigned any kind of mathematical expression. Variables and
labels are also called _symbols_, and the name identifying them is
referred to as _identifier_.
Character sequences which by itself provide a value to the
assembler, like the character sequence `42' that represents the
numeric value 42, are considered to be _literals_.
4 Syntax and Semantics
----------------------
The following chapter describes the data model and the syntax
accepted by the assembler.
4.1 Input Files
Input files should have .a65 as extension to distinguish it from
files written for other assemblers. The files should be encoded in
the ASCII or UTF-8 character sets.
4.2 Data Types
Two data types are known to the assembler:
- _byte_: 8-bit, storing whole numbers between 0 and 255.
- _word_: 16-bit, storing positive whole numbers between 0 and
65535. Negative numbers may also be stored in the range from -
32768 to -1. Negative numbers are stored in two-complement
representation.
There is no distinct boolean type. In a boolean context, any value
other than zero is considered to be a boolean true.
4.3 Symbols
The assembler distinguishes two types of case-sensitive symbols:
_labels_ and _variables_. A label stores the address of the
instruction or data that is currently assembling. It is defined
at the beginning of a line by appending its name with a colon.
The colon may be left out if the label name is not an instruction
mnemonic.
A variable is defined by assigning an expression to it. In the
following example, hello is a label, and CHROUT is a variable.
CHROUT = $ffd2
hello: jmp CHROUT
Labels and variables may be of type byte or word. A label is of type
byte if it is assigned an address within the first 256 bytes (zero-
page). Otherwise, it is of type word. The data type of a variable
is that of the expression assigned to it, unless it is forward-
referenced.
Forward-referenced means that a symbol is used in an expression
before it is defined. Forward-referenced symbols are _always_ of
type word, regardless of what is assigned to them.
If a variable is assigned a value multiple times, it must be the
same value. Otherwise, it is an illegal redefinition. Labels may not
be defined more than once.
Variables and labels may be defined locally by prepending their name
with @. They are then associated with the previous non-local label
defined. They may be referenced within expressions locally by @name
or with their qualified name label@name outside their local scope.
Example:
jmp hello@l ; fully qualified label reference
hello:
@l jmp @l ; local label reference
4.4 Expressions
There are many places where expressions may occur, for example on
the right side of a variable definition or as an argument to a
machine instruction.
Every expression is either of type byte, word or of unknown type.
Every expression also has a defined numeric value or an undefined
value.
4.4.1 Primitive Expressions
The most primitive form of an expression is a numeric constant,
which can be given in decimal, hexadecimal, or binary. The value of
the constant determines its type.
5 ; decimal byte constant
$a ; hexadecimal byte constant
$4711 ; hexadecimal word constant
%1011 ; binary byte constant
-1 ; word constant $FFFF (2-complement)
A byte-sized value can be forced to be of type word by prepending
zeros.
$00a ; hex word constant because more than 2 digits
0123 ; decimal word constant because more than 3 digits
A character enclosed by ' is evaluated to its ASCII value.
'x' ; byte typed ASCII character code of x
The address counter symbol @ returns the address of the currently
assembled instruction. The symbol .? returns an undefined value of
unknown type.
.? ; undefined value
@ ; current address
Label and variable names evaluate to their respective value.
LOAD_ADDR = 2048
lda LOAD_ADDR ; load memory cell 2048 into accumulator
4.4.2 Operator Precedence
Expressions may be composed of arithmetic sub-expressions. Operator
precedence is respected.
The supported operations from highest to lowest precedence are:
- Expressions enclosed by parentheses ()
- bit-wise complement ~, logical negation !, and is-defined ?
operators, all unary and right-associative
- Multiplication *, division /, bit-wise and &, logical left <<
and right >> shift
- Unary plus and binary addition +, unary minus and subtraction -,
bit-wise or |, exclusive or ^
- Unary low < and high > byte select, lossless unary conversion
operators [b] and [w]
- The comparison operators are ==, !=, <, >, <=, >=
- Logical and &&
- Logical or ||
- Defined-or-else ?:
4.4.3 Arithmetic and bit-wise Operators
The usual semantics for the arithmetic operators apply.
If there is an undefined argument to one of the arithmetic
operators, the result value is undefined. Type inference is
performed as such that if any of the arguments is of type word, the
result is of type word. The result is also of type word if it would
otherwise overflow the range of type byte.
The bit-wise complement operator ~ respects the data type when
toggling bits. This means that ~1 becomes $FE, and not $FFFE.
Examples:
2+3*5 ; value 17
$4700 | $11 ; is $4711
255+255 ; of type word because >255
4.4.4 Byte-select and Conversion Operators
The low-byte select operator < returns the low byte of a word-sized
expression, or the unmodified value of a byte-sized expression. The
high-byte select operator > returns the high byte of a word-sized
expression shifted eight bits to the right. It returns zero for
byte-sized expressions. The resulting data type of both operators is
byte. If applied to an undefined argument, the result is undefined.
The convert to byte [b] and convert to word [w] operators change the
data type of their expression. If the expression does not fit into a
byte, [b] raises an error. The operators also change the type of the
undefined value while retaining undefined as a value.
4.4.5 Comparison and Logical Operators
The comparison operators return 1 as true value, and 0 as false
value.
They return an undefined value if at least one of their arguments is
undefined, with the logical or || operator being an exception. It
returns true if at least one of its arguments is true.
The logical negation operator ! is right-associative.
4.4.6 Is-defined Operator
The unary, right associative is-defined operator ? returns true, if
its argument is defined. Otherwise, false is returned. The result is
of type byte.
4.4.7 Defined-or-else Operator
The defined-or-else operator ?: returns its first argument if it is
defined, otherwise its second. It is left-associative.
Example:
Y = .?
Z = X ?: Y ?: $DEAD ; assign $DEAD to Z
; because X and Y are undefined
4.5 Line Format
A line may either contain a statement or a conditional statement
or none of them. A statement it either a variable definition, an
instruction or a directive. Instructions and directives may be
preceded by a label definition. Also, a label definition may stand
for its own. Conditional statements are .IF, .ELSE, and .ENDIF.
These may not be preceded by a label. Each line may end with a
comment. Comments are started by semicolon and ignored by the
assembler.
start: ; line consisting only of a label
loop: BNE loop ; label and instruction
msg .byte "Hello" ; label followed by a directive
X = 42 ; variable definition
.if X == 42 ; conditional statement
4.6 Directives
Directives instruct the assembler to do certain things. They may or
may not produce output data. Names of directives start with a dot.
The directives currently known to the assembler are:
4.6.1 .ALIGN
Aligns the address counter to the next multiple of the first
argument, and emits the number of bytes necessary to perform the
alignment. If the second byte-sized argument is given, this value is
used as fill-byte. Otherwise, the fill-byte is zero.
.ALIGN 4 ; align @ to a multiple of 4
.ALIGN $100, $EA ; align to next page, fill with $EA
4.6.2 .ASSERT and .ASSERT1
Tests if the expression given first argument returns a true value,
otherwise terminates with an error. .ASSERT runs on pass two, and
ASSERT1 runs on pass one. The arguments following the first are
handled like the .ECHO directive does it.
Example:
.ASSERT 2 > 1, "arithmetic implementation is flawed"
4.6.3 .BINARY Directive
Copies binary data from a file to the output file. Numeric
expressions specifying a start offset and a length may be given
as arguments. If a length is given, the start offset must also be
specified.
Example:
.BINARY "SPRITE.DAT". ; copies the whole file
.BINARY "SPRITE.DAT", $10 ; skip the first 16 bytes
.BINARY "SPRITE.DAT", $10, 64 ; copy 64 bytes from offset 16
4.6.4 .BYTE Directive
Produces one or more output bytes. The arguments are separated by a
comma. Numeric expressions or strings may be used as arguments. The
values of numeric expressions must fit into a byte. Strings must be
enclosed by ".
Example:
.BYTE 1
.BYTE 47, 11
.BYTE "Hello, World", 13, 10
4.6.5 .CPU Directive
Selects the instruction set the assembler understands depending on
the given CPU type.
.CPU 6502 ; targets the NMOS 6502 CPU
.CPU 65C02 ; targets the CMOS 65C02 CPU (experimental)
4.6.6 .ECHO and .ECHO1 Directives
Print the arguments to standard output. .ECHO does it on the
second assembler pass, while .ECHO1 does it on the first pass. The
arguments may either be strings or numeric expressions, separated by
comma. Numeric expressions may be prefixed by the format specifier
[$] to output the number in hexadecimal format. Otherwise, it is
printed in decimal.
Example:
.ECHO "hexadecimal representation of ", 4711, " is ", [$]4711
4.6.7 .ERROR directive
Aborts the assembly along with file name and line number
information. Accepts the same parameters as .ECHO for the error
message.
4.6.8 .FILL Directive
Starting from the current position of the output file, emits as many
bytes as given by the first argument. If the second argument is
given, the region is filled with its byte-sized value. Otherwise, it
is filled with zero. The address counter @ is increased accordingly.
Example:
.FILL 100 ; fill 100 bytes with zero
.FILL 16, $EA ; insert 16 NOPs ($EA) into the code
4.6.9 .IF, .IFN, .ELSE and .ENDIF Directives
Conditionally assembles code if the condition of the argument to .IF
or .IFN is met. For .IF, the condition is met if the argument yields
a defined value other than zero. For .IFN, the condition is met if
the argument does not yield a defined value or the value is zero.
If the condition is met, the code between .IF or .IFN and .ELSE is
assembled, or between .IF or .IFN and .ENDIF, if .ELSE is not given.
If the argument to .IF or .IFN is not met and .ELSE is specified,
the code between .ELSE and .ENDIF is assembled.
.IF and .IFN treat an undefined expression like a boolean false.
The conditional directives may _not_ be preceded by a label.
Example:
C64 = 1
.IF C64
.ECHO "I am assembled for the C64"
.ELSE
.ECHO "I am assembled for the PET"
.ENDIF
In listing files, the unprocessed lines are indicated by a minus
after the line number instead of a colon.
4.6.10 .IFDEF and .IFNDEF Directives
An argument to .IFDEF is considered true, if its value is defined.
An argument to .IFNDEF is considered true, if its value is
undefined. Otherwise, the directives behave like their .IF and .IFN
counterparts.
4.6.11 .INCLUDE Directive
Substitutes the directive with the assembler source contained in the
file given as argument.
Example:
.INCLUDE "c64prg.i65"
4.6.12 .LIST and .NOLIST Directives
If a listing file is given via command line, listing generation is
initially enabled. If the user wants some parts of the code to be
excluded from the listing, the region can be surrounded by .NOLIST
and .LIST statements.
If listing generation is disabled when an .INCLUDE statement is
processed, .LIST inside the included file has no effect.
A .NOLIST inside an include file does not propagate to the parent
file.
4.6.13 .ORG Directive
Sets the address counter to the numeric value of the argument. Does
not modify the offset into the output file. This means that .ORG
can not be used to `jump around' in the output file. May be used
multiple times.
Example:
.ORG $0801
4.6.14 .REPEAT and .ENDREP
Repeats the block of code enclosed by .REPEAT and .ENDREP the number
of times given by the argument to .REPEAT.
Example:
.REPEAT 30 ; ...for 30 overscan scanlines...
sta WSYNC
.ENDREP
4.6.15 .SYM and .NOSYM Directives
Selectively enables or disables the inclusion of defined labels and
variables in the symbol map for specific code regions. .SYM enables
it (default), and .NOSYM disables it. The symbol map is part of the
program listing.
4.6.16 .WARNING Directive
Prints a warning along with file name and line number information.
Accepts the same parameters as .ECHO for the warning message.
4.6.17 .WORD Directive
Produces one or more output words.
Example:
.WORD $0801, 4711
4.7 Addressing Modes
Every assembler instruction consists of a mnemonic identifying
the machine instruction followed by at most one numeric argument
including addressing mode specifiers. Instruction mnemonics are
case-insensitive. The assembler supports all MOS6502 addressing
modes:
4.7.1 Implicit and Accumulator Addressing
Either no argument or accumulator is implicitly assumed by the
instruction
CLC ; clear carry
ROR ; rotate accumulator right
4.7.2 Immediate Addressing
The byte-sized argument is encoded in the byte following the opcode.
The argument for the assembler instruction is prefixed by # to
indicate an immediate value. The argument may be any expression
yielding a byte-sized numeric value.
LDA #42 ; load value 42 into the accumulator
4.7.3 Relative Addressing
Relative addressing is only used by branch instructions. The branch
offset in the range of -128 to 127 is encoded by the byte following
the opcode. The assembler interprets the argument, which may be any
numeric expression, relative to the current address counter.
loop: BNE loop
4.7.4 Absolute Addressing
A word-sized address is encoded following the opcode byte. The
assembler interprets any word-sized expression following an
instruction mnemonic as an absolute address.
LDA $4711 ; load contents of address $4711 into the accumulator
4.7.5 Zero-page Addressing
A byte-sized address is encoded following the opcode byte. The
assembler interprets any byte-sized expression following an
instruction mnemonic as a zero-page address.
LDA $47 ; load contents of address $47 into the accumulator
LDA >$4711 ; load contents of address $47 into the accumulator
4.7.6 Absolute X and Absolute X Addressing
The address is encoded in the word following the opcode and
displaced by the contents of the X or Y register.
LDA $4711,X ; load contents of address $4711 displaced by X
LDA $4711,Y ; load contents of address $4711 displaced by Y
4.7.7 Zero-page X and Zero-page Y Addressing
The address is encoded in the byte following the opcode displaced by
the contents of the X or Y register.
LDA $47,X ; A = contents of address $47 displaced by X
LDX $11,Y ; X = load contents of address $47 displaced by Y
4.7.8 Indirect Addressing
The word-sized address is stored in the memory location given by
the word-sized argument. In assembler syntax, an indirect address
is indicated by enclosing the argument in parentheses, like in the
following.
JMP ($4711)
The following one is a syntax error, because the assembler assumes
indirect addressing mode instead of a sub-expression grouped by
parentheses:
JMP (2+3)*1000
To correct this, you may rewrite it as:
JMP +(2+3)*1000
or
JMP ((2+3)*1000)
4.7.9 Indexed Indirect by X and Indirect Indexed by Y Addressing
Indexed indirect by X addresses the byte referenced by the contents
of the word stored at zero-page address b + X. Indirect indexed
by Y adds Y to the address word stored in zero-page address b to
calculate the address to operate on.
b = 15
ORA (b,X)
ORA (b),Y
A Command Line Syntax
---------------------
Usage: asm6502 input -o output [options]... [VAR=number]...
Options:
-q be quiet, unless an error occurred
-o output set output file name
-l listing set optional listing file name
-w0 disable all warnings
-w1 enable warnings (default)
-w2 enable warnings and hints
Variables defined from the command line are known to the assembler
when assembling files. The numbers are parsed like number literals
in the source code.
B Instruction Reference
-----------------------
In the following instruction list, #$42 is a representative for a
byte-sized immediate value. This value may be substituted by any
other byte-sized value. $15 is a representative for a zero-page
memory address, and $4711 is a representative for a word-sized
memory address.
The first hexadecimal value on a line is the instruction opcode
followed by at most two bytes of additional data defined by the
instruction argument. The syntax of the different addressing modes
is described in one of the previous chapters.
B.1 ADC - add with carry
Flags: N Z C V
69 42 adc #$42
65 15 adc $15
75 15 adc $15,x
6D 11 47 adc $4711
7D 11 47 adc $4711,x
79 11 47 adc $4711,y
61 15 adc ($15,x)
71 15 adc ($15),y
B.2 AND - bit-wise and with accumulator
Flags: N Z
29 42 and #$42
25 15 and $15
35 15 and $15,x
2D 11 47 and $4711
3D 11 47 and $4711,x
39 11 47 and $4711,y
21 15 and ($15,x)
31 15 and ($15),y
B.3 ASL - arithmetic shift left
Flags: N Z C
0A asl
06 15 asl $15
16 15 asl $15,x
0E 11 47 asl $4711
1E 11 47 asl $4711,x
B.4 BCC - branch if carry cleared
90 FE bcc @
B.5 BCS - branch if carry set
B0 FE bcs @
B.6 BEQ - branch if equal
F0 FE beq @
B.7 BIT - test bits
Negative flag becomes the bit 7 of the operand, overflow flag
becomes bit 6 of the operand. Zero flag is set if the bit-wise and
operation between the accumulator and the operand is zero, otherwise
it is cleared.
Flags: N Z V
24 15 bit $15
2C 11 47 bit $4711
B.8 BMI - branch if negative
30 FE bmi @
B.9 BNE - branch if not equal
D0 FE bne @
B.10 BPL - branch if positive
10 FE bpl @
B.11 BRK - force break
BRK cannot be masked by setting interrupt disable flag. Forces the
processor to continue at the address stored in the IRQ vector $FFFE.
Pushes the flags with set break (B) flag to differentiate from a
hardware interrupt. RTI and PLP ignore the break flag.
Flags: I=1
00 brk
B.12 BVC - branch if overflow flag cleared
50 FE bvc @
B.13 BVS - branch if overflow flag set
70 FE bvs @
B.14 CLC - clear carry flag
Flags: C=0
18 clc
B.15 CLD - clear decimal flag
Flags: D=0
D8 cld
B.16 CLI - clear interrupt disable flag
Flags: I=0
58 cli
B.17 CLV - clear overflow flag
Flags: V=0
B8 clv
B.18 CMP - compare with accumulator
Flags: N Z C
C9 42 cmp #$42
C5 15 cmp $15
D5 15 cmp $15,x
CD 11 47 cmp $4711
DD 11 47 cmp $4711,x
D9 11 47 cmp $4711,y
C1 15 cmp ($15,x)
D1 15 cmp ($15),y
B.19 CPX - compare with X register
Flags: N Z C
E0 42 cpx #$42
E4 15 cpx $15
EC 11 47 cpx $4711
B.20 CPY - compare with Y register
Flags: N Z C
C0 42 cpy #$42
C4 15 cpy $15
CC 11 47 cpy $4711
B.21 DEC - decrement
Flags: N Z
C6 15 dec $15
D6 15 dec $15,x
CE 11 47 dec $4711
DE 11 47 dec $4711,x
B.22 DEX - decrement X register
Flags: N Z
CA dex
B.23 DEY - decrement Y register
Flags: N Z
88 dey
B.24 EOR - exclusive or
Flags: N Z
49 42 eor #$42
45 15 eor $15
55 15 eor $15,x
4D 11 47 eor $4711
5D 11 47 eor $4711,x
59 11 47 eor $4711,y
41 15 eor ($15,x)
51 15 eor ($15),y
B.25 INC - increment
Flags: N Z
E6 15 inc $15
F6 15 inc $15,x
EE 11 47 inc $4711
FE 11 47 inc $4711,x
B.26 INX - increment X register
Flags: N Z
E8 inx
B.27 INY - increment Y register
Flags: N Z
C8 iny
B.28 JMP - jump
4C 11 47 jmp $4711
6C 11 47 jmp ($4711)
B.29 JSR - call subroutine
20 11 47 jsr $4711
B.30 LDA - load accumulator
Flags: N Z
A9 42 lda #$42
A5 15 lda $15
B5 15 lda $15,x
AD 11 47 lda $4711
BD 11 47 lda $4711,x
B9 11 47 lda $4711,y
A1 15 lda ($15,x)
B1 15 lda ($15),y
B.31 LDX - load X register
Flags: N Z
A2 42 ldx #$42
A6 15 ldx $15
B6 15 ldx $15,y
AE 11 47 ldx $4711
BE 11 47 ldx $4711,y
B.32 LDY - load Y register
Flags: N Z
A0 42 ldy #$42
A4 15 ldy $15
B4 15 ldy $15,x
AC 11 47 ldy $4711
BC 11 47 ldy $4711,x
B.33 LSR - logical shift right
Flags: N=0 Z C
4A lsr
46 15 lsr $15
56 15 lsr $15,x
4E 11 47 lsr $4711
5E 11 47 lsr $4711,x
B.34 NOP - no-operation
EA nop
B.35 ORA - bit-wise or with accumulator
Flags: N Z
09 42 ora #$42
05 15 ora $15
15 15 ora $15,x
0D 11 47 ora $4711
1D 11 47 ora $4711,x
19 11 47 ora $4711,y
01 15 ora ($15,x)
11 15 ora ($15),y
B.36 PHA - push accumulator on stack
48 pha
B.37 PHP - push flags on stack
08 php
B.38 PLA - pop accumulator from stack
Flags: N Z
68 pla
B.39 PLP - pop flags from stack