~ndiddy/a65

a501e2a907a6c56ea5e3981944760e0cd4e31aca — Nathan Misner 4 months ago c6029c2
changed syntax for the better
8 files changed, 171 insertions(+), 63 deletions(-)

M A65.DOC
M a65.c
M a65.h
M a65eval.c
M a65util.c
A readme.txt
A test.asm
A test.lst
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