M A65.DOC => A65.DOC +4 -6
@@ 679,13 679,11 @@
The FCB (Form Constant Bytes) pseudo-op allows arbitrary
bytes to be spliced into the object code. Its argument is a
- chain of zero or more expressions that evaluate to -128 thru 255
- separated by commas. If a comma occurs with no preceding
- expression, a $00 byte is spliced into the object code. The
- sequence of bytes $FE $FF, $00, $01, $02 could be spliced into
- the code with the following statement:
+ chain of one or more expressions that evaluate to -128 thru 255
+ separated by commas. The sequence of bytes $FE $FF, $00, $01, $02
+ could be spliced into the code with the following statement:
- FCB -2, -1, , 1, 2
+ FCB -2, -1, 0, 1, 2
4.4 Pseudo-ops -- FCC
M a65.c => a65.c +44 -38
@@ 76,8 76,9 @@ void main(int argc, char **argv) {
void hclose(), hopen(), hputc();
void error(), fatal_error(), warning();
- printf("6502 Cross-Assembler (Portable) Ver 0.1\n");
- printf("Copyright (c) 1986 William C. Colley, III\n\n");
+ printf("6502 Cross-Assembler (Portable) Ver 0.2n\n");
+ printf("Copyright (c) 1986 William C. Colley, III\n");
+ printf("Modifications (c) 2023 Nathan Misner\n\n");
while (--argc > 0) {
if (**++argv == '-') {
@@ 324,6 325,47 @@ static void pseudo_op() {
o = obj;
switch (opcod -> valu) {
+ case DB:
+ do_label();
+ do {
+ if ((lex()->attr & TYPE) == STR) {
+ for (s = token.sval; *s; *o++ = *s++) {
+ bytes++;
+ }
+ if ((lex()->attr & TYPE) != SEP) unlex();
+ }
+ else {
+ unlex();
+ if ((u = expr()) > 0xff && u < 0xff80) {
+ u = 0; error('V');
+ }
+ *o++ = low(u); ++bytes;
+ }
+ } while ((token.attr & TYPE) == SEP);
+ break;
+
+ case DS:
+ do_label();
+ while ((lex()->attr & TYPE) != EOL) {
+ if ((token.attr & TYPE) == STR) {
+ for (s = token.sval; *s; *o++ = *s++)
+ ++bytes;
+ if ((lex()->attr & TYPE) != SEP) unlex();
+ }
+ else error('S');
+ }
+ break;
+
+ case DW:
+ do_label();
+ do {
+ if ((lex()->attr & TYPE) == SEP) u = 0;
+ else { unlex(); u = expr(); }
+ *o++ = low(u); *o++ = high(u);
+ bytes += 2;
+ } while ((token.attr & TYPE) == SEP);
+ break;
+
case ELSE:
listhex = FALSE;
if (ifsp) off = (ifstack[ifsp] = -ifstack[ifsp]) != ON;
@@ 370,42 412,6 @@ static void pseudo_op() {
else error('L');
break;
- case FCB:
- do_label();
- do {
- if ((lex() -> attr & TYPE) == SEP) u = 0;
- else {
- unlex();
- if ((u = expr()) > 0xff && u < 0xff80) {
- u = 0; error('V');
- }
- }
- *o++ = low(u); ++bytes;
- } while ((token.attr & TYPE) == SEP);
- break;
-
- case FCC:
- do_label();
- while ((lex() -> attr & TYPE) != EOL) {
- if ((token.attr & TYPE) == STR) {
- for (s = token.sval; *s; *o++ = *s++)
- ++bytes;
- if ((lex() -> attr & TYPE) != SEP) unlex();
- }
- else error('S');
- }
- break;
-
- case FDB:
- do_label();
- do {
- if ((lex() -> attr & TYPE) == SEP) u = 0;
- else { unlex(); u = expr(); }
- *o++ = low(u); *o++ = high(u);
- bytes += 2;
- } while ((token.attr & TYPE) == SEP);
- break;
-
case IF:
if (++ifsp == IFDEPTH) fatal_error(IFOFLOW);
address = expr();
M a65.h => a65.h +17 -15
@@ 114,20 114,22 @@ all modules of the cross-assembler.
/* Line assembler (A65.C) pseudo-op opcode token values: */
-#define ELSE 1
-#define END 2
-#define ENDI 3
-#define EQU 4
-#define FCB 5
-#define FCC 6
-#define FDB 7
-#define IF 8
-#define INCL 9
-#define ORG 10
-#define PAGE 11
-#define RMB 12
-#define SET 13
-#define TITL 14
+typedef enum {
+ DB = 1,
+ DS,
+ DW,
+ ELSE,
+ END,
+ ENDI,
+ EQU,
+ IF,
+ INCL,
+ ORG,
+ PAGE,
+ RMB,
+ SET,
+ TITL
+} PSEUDO_OP;
/* Line assembler (A65.C) machine opcode attribute values: */
@@ 186,7 188,7 @@ typedef struct {
#define AND 0
#define GE 1
-#define HIGH 2
+#define HIGH 2
#define LE 3
#define LOW 4
#define MOD 5
M a65eval.c => a65eval.c +1 -1
@@ 362,7 362,7 @@ opr2: token.attr = BINARY + RELAT + OPR;
if (*p == '\n') { exp_error('"'); break; }
*p = '\0'; quote = FALSE;
if ((token.valu = token.sval[0]) && token.sval[1])
- token.valu = (token.valu << 8) + token.sval[1];
+ token.valu = (token.valu << 8) + token.sval[1];
break;
case ',': token.attr = SEP;
M a65util.c => a65util.c +3 -3
@@ 135,17 135,17 @@ OPCODE *find_code(char *nam) {
{ TWOOP, 0xc1, "CMP" },
{ CPXY, 0xe0, "CPX" },
{ CPXY, 0xc0, "CPY" },
+ { PSEUDO, DB, "DB" },
{ INCOP, 0xc6, "DEC" },
{ INHOP, 0xca, "DEX" },
{ INHOP, 0x88, "DEY" },
+ { PSEUDO, DS, "DS" },
+ { PSEUDO, DW, "DW" },
{ PSEUDO + ISIF, ELSE, "ELSE" },
{ PSEUDO, END, "END" },
{ PSEUDO + ISIF, ENDI, "ENDI" },
{ TWOOP, 0x41, "EOR" },
{ PSEUDO, EQU, "EQU" },
- { PSEUDO, FCB, "FCB" },
- { PSEUDO, FCC, "FCC" },
- { PSEUDO, FDB, "FDB" },
{ PSEUDO + ISIF, IF, "IF" },
{ INCOP, 0xe6, "INC" },
{ PSEUDO, INCL, "INCL" },
A readme.txt => readme.txt +54 -0
@@ 0,0 1,54 @@
+=====a65=====
+
+This project is essentially me modifying William Colley's "a65" assembler
+for my weird niche purposes. If you came across this repo because you have an
+existing codebase that depends on a65 v0.1, don't use this because it'll break
+your workflow.
+
+=====Why not to use this assembler=====
+- The code has that "old UNIX program" stank to it, where you have a lot of
+ buffers with hard-coded sizes and if you exceed them the program will
+ (hopefully) crash without telling you why.
+- It's fairly opinionated regarding syntax. It doesn't support a ton of 6502
+ "dialects" like all the popular assemblers do
+- It's an absolute assembler, so no linking
+- No macro support
+- I'm like 90% sure that it won't like Unicode characters (but who knows, it
+ might...)
+
+=====Why to use this assembler=====
+- The code is well laid out and easy to understand and modify in case you want
+ to fork it and use it for your own weird niche purposes.
+- It'll basically run on anything with a C compiler (although I took out the
+ K&R function declarations, so it'll have to be at least C89)
+- It assembles stuff pretty fast on today's computers
+
+=====Goals for release 0.2n=====
+- Reformat code for ANSI style function declarations - done
+- Change "FCB", "FCC", "FDB" to "DB", "DS", "DW" - done
+- Change the syntax so "DB" accepts string(s) as arguments - done
+- Give each .c file its own header file
+- Change the assembler to output binary files instead of Intel HEX
+- Allow for forcing loads/stores to not be optimized for zero page
+- Print the error messages to stdout instead of the assembler listing
+- Add a makefile for our GNU/Linux and Mac OS X using friends
+- Update A65.DOC with the new changes
+
+=====Future goals=====
+- Add a "BASE" statement that changes the PC but not the output position in
+ the file
+
+=====License=====
+
+Copyright (c) 1986 William C. Colley, III
+Changes (c) 2023 Nathan Misner
+
+This package may be used for any commercial or non-commercial purpose. It may
+be copied and distributed freely provided that any fee charged by the
+distributor of the copy does not exceed the sum of:
+1) the cost of the media the copy is written on,
+2) any required costs of shipping the copy, and
+3) a nominal handling fee.
+Any other distribution requires the written permission of the author. Also, the
+author's copyright notices shall not be removed from the program source, the
+program object, or the program documentation.<
\ No newline at end of file
A test.asm => test.asm +19 -0
@@ 0,0 1,19 @@
+ titl "sneed"
+
+foo equ $5
+bar equ $6
+
+ org $8000
+string
+ db "hello",0,1,2,3,-1,-2,-3
+ db "goodbye"
+ dw 1,2,3,4,-1,-2,-3,-4
+ jmp string
+
+start
+ lda #'a'
+ sta bar
+ jmp start
+
+
+ end<
\ No newline at end of file
A test.lst => test.lst +29 -0
@@ 0,0 1,29 @@
+ titl "sneed"
+
+ 0005 foo equ $5
+ 0006 bar equ $6
+
+ 8000 org $8000
+ 8000 string
+ 8000 68 65 6c 6c db "hello",0,1,2,3,-1,-2,-3
+ 8004 6f 00 01 02
+ 8008 03 ff fe fd
+ 800c 67 6f 6f 64 db "goodbye"
+ 8010 62 79 65
+ 8013 01 00 02 00 dw 1,2,3,4,-1,-2,-3,-4
+ 8017 03 00 04 00
+ 801b ff ff fe ff
+ 801f fd ff fc ff
+ 8023 4c 00 80 jmp string
+
+ 8026 start
+ 8026 a9 61 lda #'a'
+ 8028 85 06 sta bar
+ 802a 4c 26 80 jmp start
+
+
+ 802d end
+sneed
+
+0006 bar 0005 foo 8026 start 8000 string
+<
\ No newline at end of file