mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-25 06:31:25 +00:00
Updated and Debugged A02 Assembler
This commit is contained in:
parent
f94ddd63fc
commit
18088691d7
158
a02.c
158
a02.c
@ -18,9 +18,9 @@ int orgadr; //Origin Address
|
|||||||
int curadr; //Current Address
|
int curadr; //Current Address
|
||||||
int lstadr; //List Address
|
int lstadr; //List Address
|
||||||
|
|
||||||
struct sym {int block; char name[MAXSYM]; int bytes, value;};
|
struct sym {int block; char name[MAXLBL+1]; int bytes, value;};
|
||||||
struct sym symbol; //Current Symbol
|
struct sym symbol; //Current Symbol
|
||||||
struct sym symtbl[MAXGLB]; //Global Symbol Table
|
struct sym symtbl[MAXSYM]; //Global Symbol Table
|
||||||
int symcnt; //Number of Global Labels
|
int symcnt; //Number of Global Labels
|
||||||
int blknum; //Local Label Block Number (0 = Global)
|
int blknum; //Local Label Block Number (0 = Global)
|
||||||
|
|
||||||
@ -43,14 +43,17 @@ char *linptr; //Pointer into Input Buffer
|
|||||||
int lineno; //Input File Line Number
|
int lineno; //Input File Line Number
|
||||||
int opridx; //Index into Operand
|
int opridx; //Index into Operand
|
||||||
int passno; //Assembler Pass Number (1 or 2)
|
int passno; //Assembler Pass Number (1 or 2)
|
||||||
|
int savlno; //Line Number (Saved)
|
||||||
|
|
||||||
char prgnam[256]; //Assembler Path and Name (from Command Line)
|
char prgnam[256]; //Assembler Path and Name (from Command Line)
|
||||||
char inpnam[256]; //Input File Name
|
char inpnam[256]; //Input File Name
|
||||||
char outnam[256]; //Output File Name
|
char outnam[256]; //Output File Name
|
||||||
char lstnam[256]; //List File Name
|
char lstnam[256]; //List File Name
|
||||||
|
char incnam[256]; //Include File Name
|
||||||
FILE *inpfil; //Input File Pointer
|
FILE *inpfil; //Input File Pointer
|
||||||
FILE *outfil; //Output File Pointer
|
FILE *outfil; //Output File Pointer
|
||||||
FILE *lstfil; //List File Pointer
|
FILE *lstfil; //List File Pointer
|
||||||
|
FILE *incfil; //Include File Pointer
|
||||||
|
|
||||||
/* Print Error Message and Exit */
|
/* Print Error Message and Exit */
|
||||||
void xerror(char* format, char *s) {
|
void xerror(char* format, char *s) {
|
||||||
@ -59,6 +62,14 @@ void xerror(char* format, char *s) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Open File with Error Checking */
|
||||||
|
FILE * opnfil(char* name, char* mode) {
|
||||||
|
if (DEBUG) printf("Opening file '%s' with mode '%s'\n", name, mode);
|
||||||
|
FILE *fp = fopen(name, mode);
|
||||||
|
if (!fp) xerror("Error Opening File '%s'\n", name);
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip Character in Input Line *
|
/* Skip Character in Input Line *
|
||||||
* Args: c - Character to Skip *
|
* Args: c - Character to Skip *
|
||||||
* Updates: linptr */
|
* Updates: linptr */
|
||||||
@ -81,7 +92,7 @@ void skpspc(void) {
|
|||||||
int pword(int skip, char* word) {
|
int pword(int skip, char* word) {
|
||||||
int wrdlen = 0;
|
int wrdlen = 0;
|
||||||
if (skip) skpspc();
|
if (skip) skpspc();
|
||||||
while (isalnum(*linptr)) {
|
while (isalnum(*linptr) || *linptr == '_') {
|
||||||
word[wrdlen++] = toupper(*linptr);
|
word[wrdlen++] = toupper(*linptr);
|
||||||
linptr++;
|
linptr++;
|
||||||
}
|
}
|
||||||
@ -122,6 +133,7 @@ int plabel(void) {
|
|||||||
if (label[0] && fndsym(block, label)) xerror("Duplicate Label %s Encountered\n", label);
|
if (label[0] && fndsym(block, label)) xerror("Duplicate Label %s Encountered\n", label);
|
||||||
if (DEBUG) printf("Initializing Symbol %s\n", label);
|
if (DEBUG) printf("Initializing Symbol %s\n", label);
|
||||||
symbol.block = block;
|
symbol.block = block;
|
||||||
|
if (strlen(label) > MAXLBL) xerror("Label %s Too Long\n", label);
|
||||||
strcpy(symbol.name, label);
|
strcpy(symbol.name, label);
|
||||||
setsym(curadr, 0);
|
setsym(curadr, 0);
|
||||||
}
|
}
|
||||||
@ -135,7 +147,8 @@ int plabel(void) {
|
|||||||
/* Copy Character to Operand and Increment */
|
/* Copy Character to Operand and Increment */
|
||||||
int cpychr(int c) {
|
int cpychr(int c) {
|
||||||
if (c && toupper(*linptr) != c) return FALSE;
|
if (c && toupper(*linptr) != c) return FALSE;
|
||||||
oprnd[opridx++] = toupper(*linptr++);
|
if (opridx < MAXSTR) oprnd[opridx++] = toupper(*linptr);
|
||||||
|
linptr++;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +202,7 @@ struct sym *evlsym() {
|
|||||||
char name[MAXSTR];
|
char name[MAXSTR];
|
||||||
int block = (cpychr('.')) ? blknum : 0;
|
int block = (cpychr('.')) ? blknum : 0;
|
||||||
pword(TRUE, name);
|
pword(TRUE, name);
|
||||||
for (int i=0; name[i]; i++) oprnd[opridx++] = name[i];
|
for (int i=0; name[i]; i++) if (opridx<MAXSTR) oprnd[opridx++] = name[i];
|
||||||
struct sym *result = fndsym(block, name);
|
struct sym *result = fndsym(block, name);
|
||||||
if (passno == 2 && result == NULL) xerror("Undefined Symbol %s\n", name);
|
if (passno == 2 && result == NULL) xerror("Undefined Symbol %s\n", name);
|
||||||
return result;
|
return result;
|
||||||
@ -252,7 +265,7 @@ void outbyt(int b) {
|
|||||||
if (passno != 2) return;
|
if (passno != 2) return;
|
||||||
fputc(b & 0xFF, outfil);
|
fputc(b & 0xFF, outfil);
|
||||||
sprintf(bytstr, "%02X ", b);
|
sprintf(bytstr, "%02X ", b);
|
||||||
strcat(mcode, bytstr);
|
if (strlen(mcode) < 9) strcat(mcode, bytstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write Word to Output File */
|
/* Write Word to Output File */
|
||||||
@ -263,6 +276,7 @@ void outwrd(int w) {
|
|||||||
|
|
||||||
/* Assemble BYTE Pseudo-Op */
|
/* Assemble BYTE Pseudo-Op */
|
||||||
void asmbyt(void) {
|
void asmbyt(void) {
|
||||||
|
if (DEBUG) puts("Assembling BYTE Pseudo-Op");
|
||||||
do {
|
do {
|
||||||
if (cpychr('"')) { //String Operand
|
if (cpychr('"')) { //String Operand
|
||||||
while (!cpychr('"')) {outbyt(*linptr); cpychr(0); }
|
while (!cpychr('"')) {outbyt(*linptr); cpychr(0); }
|
||||||
@ -279,6 +293,14 @@ void asmwrd(void) {
|
|||||||
} while (cpychr(','));
|
} while (cpychr(','));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Assemble FILL Pseudo-Op */
|
||||||
|
void asmfll(void) {
|
||||||
|
if (DEBUG) puts("Assembling FILL Pseudo-Op");
|
||||||
|
int size = evlopd(0xFFFF);
|
||||||
|
if (DEBUG) printf("Filling %d Bytes\n", size);
|
||||||
|
for (int i=0; i<size; i++) outbyt(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Assemble EQU Pseudo-Op */
|
/* Assemble EQU Pseudo-Op */
|
||||||
void asmequ(void) {
|
void asmequ(void) {
|
||||||
if (label[0] == 0) xerror("EQUate without Label", 0);
|
if (label[0] == 0) xerror("EQUate without Label", 0);
|
||||||
@ -288,14 +310,14 @@ void asmequ(void) {
|
|||||||
/* Assemble ORG Pseudo-Op */
|
/* Assemble ORG Pseudo-Op */
|
||||||
void asmorg(void) {
|
void asmorg(void) {
|
||||||
orgadr = evlopd(0xFFFF);
|
orgadr = evlopd(0xFFFF);
|
||||||
curadr = orgadr;
|
|
||||||
lstadr = orgadr;
|
|
||||||
if (passno == 1 && symbol.name[0]) {
|
if (passno == 1 && symbol.name[0]) {
|
||||||
symbol.value = orgadr;
|
symbol.value = orgadr;
|
||||||
symbol.bytes = 2;
|
symbol.bytes = 2;
|
||||||
}
|
}
|
||||||
if (passno == 2 && objtyp == PRGFIL)
|
if (passno == 2 && objtyp == PRGFIL)
|
||||||
outwrd(orgadr);
|
outwrd(orgadr);
|
||||||
|
curadr = orgadr;
|
||||||
|
lstadr = orgadr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble PROCESSOR Pseudo-Op */
|
/* Assemble PROCESSOR Pseudo-Op */
|
||||||
@ -312,39 +334,50 @@ void asmsub(void) {
|
|||||||
if (DEBUG) printf("Block Number set to %s\n", oprnd);
|
if (DEBUG) printf("Block Number set to %s\n", oprnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble FILL Pseudo-Op */
|
/* Assemble INCLUDE Pseudo-Op */
|
||||||
void asmfll(void) {
|
void asminf(void) {
|
||||||
int size = evlopd(0xFFFF);
|
int incidx = 0;
|
||||||
for (int i=0; i<size; i++) {
|
if (DEBUG) puts("Assembling INCLUDE Pseudo-Op");
|
||||||
if (passno == 2) outbyt(0);
|
if (incfil) xerror("Nested INCLUDE not Allowed", "");
|
||||||
curadr++;
|
if (!cpychr('"')) xerror("File Name Must be Quoted", "");
|
||||||
|
printf("%d: '%c'\n", linptr, *linptr);
|
||||||
|
while (*linptr && !cpychr('"')) {
|
||||||
|
char c = *linptr; if (c == '/') c = '\\'; //Reverse Slashes for DOS/Windows
|
||||||
|
incnam[incidx++] = c;
|
||||||
|
cpychr(0);
|
||||||
}
|
}
|
||||||
|
incnam[incidx] = 0; //Terminate Include Name
|
||||||
|
if (incidx == 0) xerror("INCLUDE requires file name\n", "");
|
||||||
|
if (DEBUG) printf("Include File Set to Name to ''\n", incnam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble Pseudo-Op */
|
/* Assemble Pseudo-Op */
|
||||||
int asmpso(void) {
|
int asmpso(void) {
|
||||||
if (DEBUG) printf("Assembling Pseudo-Op Token '%c'\n", token);
|
if (lkpopc(psolst) == FALSE) return FALSE;
|
||||||
|
skpspc();
|
||||||
|
if (DEBUG) printf("Assembling Pseudo-Op %s, Token '%c'\n", mnmnc, token);
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case '=': asmequ(); break; //EQU
|
case '=': asmequ(); break; //EQU
|
||||||
case 'B': asmbyt(); break; //BYTE
|
case 'B': asmbyt(); break; //BYTE
|
||||||
case 'W': asmwrd(); break; //WORD
|
case 'W': asmwrd(); break; //WORD
|
||||||
case 'F': asmfll(); break; //FILL
|
case 'F': asmfll(); break; //FILL
|
||||||
case 'S': asmsub(); break; //SUBROUTINE
|
case 'S': asmsub(); break; //SUBRoutine
|
||||||
|
case 'I': asminf(); break; //INCLude
|
||||||
case '*': asmorg(); break; //ORG
|
case '*': asmorg(); break; //ORG
|
||||||
case 'P': asmprc(); break; //PROCESSOR
|
case 'P': asmprc(); break; //PROCessor
|
||||||
default: xerror("Undefined Pseudo-Op %s\n", mnmnc);
|
default: xerror("Undefined Pseudo-Op %s\n", mnmnc);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup Opcode */
|
/* Lookup Opcode */
|
||||||
int lkpopc(struct opc opclst[]) {
|
int lkpopc(struct opc opl[]) {
|
||||||
if (DEBUG) printf("Looking for OpCode %s\n", mnmnc);
|
if (DEBUG) printf("Looking up Mnemonic %s\n", mnmnc);
|
||||||
char mne[4]; strncpy(mne, mnmnc, 3); //Truncate Mnemonic to Three Characters
|
char mne[5]; strncpy(mne, mnmnc, 4); mne[4] = 0; //Truncate Mnemonic to Four Characters
|
||||||
for (int i=0; opclst[i].name[0]; i++) {
|
for (int i=0; opl[i].name[0]; i++) {
|
||||||
if (strcmp(opclst[i].name, mne)) continue;
|
if (strcmp(opl[i].name, mne)) continue;
|
||||||
token = opclst[i].token;
|
token = opl[i].token;
|
||||||
amode = opclst[i].amode;
|
amode = opl[i].amode;
|
||||||
if (DEBUG) printf("Found token %02X, amode %04X\n", token, amode);
|
if (DEBUG) printf("Found token %02X, amode %04X\n", token, amode);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -353,8 +386,12 @@ int lkpopc(struct opc opclst[]) {
|
|||||||
|
|
||||||
/* Check for Valid Addressing Mode */
|
/* Check for Valid Addressing Mode */
|
||||||
int chkmod(int mode) {
|
int chkmod(int mode) {
|
||||||
|
char* s = NULL; //Pointer to Addressing Mode Description
|
||||||
|
for (int i=0; amdesc[i].amode; i++)
|
||||||
|
if (amdesc[i].amode == mode) {s = amdesc[i].desc; break;}
|
||||||
|
if (DEBUG) printf("Checking Addressing Mode %s, %04X against %04X\n", s, mode, amode);
|
||||||
if (mode & amode) return TRUE;
|
if (mode & amode) return TRUE;
|
||||||
xerror("Invalid Addressing Mode", "");
|
xerror("Invalid Addressing Mode %s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assemble Branch Opcode */
|
/* Assemble Branch Opcode */
|
||||||
@ -377,6 +414,7 @@ void asmbrn(void) {
|
|||||||
|
|
||||||
/* Assemble Immediate Mode Instruction */
|
/* Assemble Immediate Mode Instruction */
|
||||||
void asmimd(void) {
|
void asmimd(void) {
|
||||||
|
if (DEBUG) printf("Assembling Immediate Opcode Token 0x%02X\n", token);
|
||||||
opval = evlopd(0xFF);
|
opval = evlopd(0xFF);
|
||||||
zpage = TRUE;
|
zpage = TRUE;
|
||||||
opmod = 0x08; //Immediate
|
opmod = 0x08; //Immediate
|
||||||
@ -404,6 +442,7 @@ void asmiaz(void) {
|
|||||||
if (chkmod(ACMLT)) opmod = 0x08; //Accumulator
|
if (chkmod(ACMLT)) opmod = 0x08; //Accumulator
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (DEBUG) printf("Assembling Absolute/ZeroPage 0x%02X\n", token);
|
||||||
zpage = (opval <= 0xff) ? TRUE : FALSE;
|
zpage = (opval <= 0xff) ? TRUE : FALSE;
|
||||||
if (zpage && chkmod(ZPAGE)) opmod = 0x04; //ZeroPage
|
if (zpage && chkmod(ZPAGE)) opmod = 0x04; //ZeroPage
|
||||||
else if (chkmod(ABSLT)) opmod = 0x0C; //Absolute
|
else if (chkmod(ABSLT)) opmod = 0x0C; //Absolute
|
||||||
@ -428,18 +467,42 @@ unsigned char fixopc(void) {
|
|||||||
return token + opmod;
|
return token + opmod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ouput Opcode Debug Info */
|
||||||
|
void dbgopc(void) {
|
||||||
|
if (DEBUG) printf("token=$%02X, opmod=$%02X, Address Mode: ", token, opmod);
|
||||||
|
switch (opmod) {
|
||||||
|
case 0x00: if (amode == IMPLD) puts("Implied"); else puts("(Indirect,X)"); break;
|
||||||
|
case 0x08: if (opval < 0) puts("Accumulator"); else puts("#Immediate"); break;
|
||||||
|
case 0x10: puts("(Indirect),Y"); break;
|
||||||
|
case 0x11: puts("(Indirect)"); break;
|
||||||
|
case 0x04: puts("ZeroPage"); break;
|
||||||
|
case 0x0C: puts("Absolute"); break;
|
||||||
|
case 0x14: puts("ZeroPage,X"); break;
|
||||||
|
case 0x1C: puts("Absolute,X"); break;
|
||||||
|
case 0x14: puts("ZeroPage,Y"); break;
|
||||||
|
case 0x18: puts("Absolute,Y"); break;
|
||||||
|
default: puts("UNKOWN");
|
||||||
|
}
|
||||||
|
if (opval < 0) puts("No Operand");
|
||||||
|
else {
|
||||||
|
printf("Operand Value %d, ", opval);
|
||||||
|
if (zpage) puts("Zero Page"); else puts("Absolute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Assemble Opcode */
|
/* Assemble Opcode */
|
||||||
int asmopc(void) {
|
int asmopc(void) {
|
||||||
opmod = 0;
|
opmod = 0;
|
||||||
|
if (asmpso()) return TRUE; //Check For/Assemble Pseudo-Op
|
||||||
if (lkpopc(opclst) == FALSE) xerror("Invalid Mnemonic %s\n", mnmnc);
|
if (lkpopc(opclst) == FALSE) xerror("Invalid Mnemonic %s\n", mnmnc);
|
||||||
if (DEBUG) printf("Assembling Opcode Token 0x%02X\n", token);
|
if (DEBUG) printf("Assembling Opcode Token 0x%02X, ", token);
|
||||||
if (DEBUG) printf("Addressing Mode Mask 0x%04X\n", amode);
|
if (DEBUG) printf("Addressing Mode Mask 0x%04X\n", amode);
|
||||||
skpspc();
|
skpspc();
|
||||||
if (amode == 0) return asmpso(); //Pseudo-Op
|
if (amode == RELTV) asmbrn(); //Branch (Relative) Instruction
|
||||||
else if (amode == RELTV) asmbrn(); //Branch (Relative) Instruction
|
|
||||||
else if (cpychr('#')) asmimd(); //Assemble Implied Instruction
|
else if (cpychr('#')) asmimd(); //Assemble Implied Instruction
|
||||||
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
|
else if (cpychr('(')) asmind(); //Assemble Indirect Instruction
|
||||||
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
|
else asmiaz(); //Assemble Implied/Accumulator/Absolute/ZeroPage Instruction
|
||||||
|
if (DEBUG) dbgopc();
|
||||||
int opcode = fixopc();
|
int opcode = fixopc();
|
||||||
if (DEBUG) printf("Writing OpCode $%02X\n", opcode);
|
if (DEBUG) printf("Writing OpCode $%02X\n", opcode);
|
||||||
outbyt(opcode);
|
outbyt(opcode);
|
||||||
@ -480,6 +543,26 @@ void addsym() {
|
|||||||
memcpy(&symtbl[symcnt++], &symbol, sizeof(symbol));
|
memcpy(&symtbl[symcnt++], &symbol, sizeof(symbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Open Include File */
|
||||||
|
void opninc(void) {
|
||||||
|
if (DEBUG) printf("Opening Include File %s\n", incnam);
|
||||||
|
if (lstfil) fputs("\n", lstfil);
|
||||||
|
incfil = opnfil(incnam, "r");
|
||||||
|
savlno = lineno;
|
||||||
|
lineno = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close Include File */
|
||||||
|
void clsinc(void) {
|
||||||
|
if (DEBUG) printf("Closing Include File %s\n", incnam);
|
||||||
|
if (lstfil) fputs("\n", lstfil);
|
||||||
|
fclose(incfil);
|
||||||
|
incfil = NULL;
|
||||||
|
incnam[0] = 0;
|
||||||
|
lineno = savlno;
|
||||||
|
}
|
||||||
|
|
||||||
/* Assemble Input File (Two Pass) *
|
/* Assemble Input File (Two Pass) *
|
||||||
* Args: pass - Assembly Pass (1 or 2) *
|
* Args: pass - Assembly Pass (1 or 2) *
|
||||||
* Requires: inpfil - Input File Pointer *
|
* Requires: inpfil - Input File Pointer *
|
||||||
@ -493,9 +576,10 @@ void asmfil(int pass) {
|
|||||||
orgadr = -1; //Origin Address Not Set
|
orgadr = -1; //Origin Address Not Set
|
||||||
curadr = orgadr; //Set Current Address to Origin
|
curadr = orgadr; //Set Current Address to Origin
|
||||||
rewind(inpfil); //Start at Beginning of Input File
|
rewind(inpfil); //Start at Beginning of Input File
|
||||||
while (!feof(inpfil)) {
|
while (TRUE) {
|
||||||
linptr = fgets(inplin, MAXSTR, inpfil);
|
if (incfil) linptr = fgets(inplin, MAXSTR, incfil);
|
||||||
if (linptr == NULL) break;
|
else linptr = fgets(inplin, MAXSTR, inpfil);
|
||||||
|
if (linptr == NULL) {if (incfil) {clsinc(); continue;} else break;}
|
||||||
if (DEBUG) printf("%05d %04X: %s", lineno, curadr, inplin);
|
if (DEBUG) printf("%05d %04X: %s", lineno, curadr, inplin);
|
||||||
lstadr = curadr; //Set List Address
|
lstadr = curadr; //Set List Address
|
||||||
mcode[0] = 0; //Clear Generated Macbine Code
|
mcode[0] = 0; //Clear Generated Macbine Code
|
||||||
@ -506,8 +590,10 @@ void asmfil(int pass) {
|
|||||||
if (passno == 2) {
|
if (passno == 2) {
|
||||||
if (lstadr < 0) hexadr[0] = 0; else sprintf(hexadr, "%04X", lstadr);
|
if (lstadr < 0) hexadr[0] = 0; else sprintf(hexadr, "%04X", lstadr);
|
||||||
fprintf(lstfil, "%05d %-4s %-9s%-7s %-5s %-16s %s\n", lineno, hexadr, mcode, label, mnmnc, oprnd, cmmnt );
|
fprintf(lstfil, "%05d %-4s %-9s%-7s %-5s %-16s %s\n", lineno, hexadr, mcode, label, mnmnc, oprnd, cmmnt );
|
||||||
|
fflush(lstfil); //Flush Output Buffer in case of Segmentation Fault
|
||||||
}
|
}
|
||||||
lineno++;
|
lineno++;
|
||||||
|
if (incnam[0] && incfil == NULL) opninc(); //Open Include File
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,16 +634,9 @@ void pcargs(int argc, char *argv[]) {
|
|||||||
///if (argnum<2) usage();
|
///if (argnum<2) usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open File with Error Checking */
|
|
||||||
FILE * opnfil(char* name, char* mode) {
|
|
||||||
if (DEBUG) printf("Opening file '%s' with mode '%s'\n", name, mode);
|
|
||||||
FILE *fp = fopen(name, mode);
|
|
||||||
if (!fp) xerror("Error Opening File '%s'\n", name);
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
lstnam[0] = 0; lstfil = NULL; //Default to No List File
|
lstnam[0] = 0; lstfil = NULL; //Default to No List File
|
||||||
|
incnam[0] = 0; incfil = NULL; //Include File Not Opened
|
||||||
lineno = 0; //No Line Number (yet)
|
lineno = 0; //No Line Number (yet)
|
||||||
objtyp = BINFIL; //Default Object File Type to Binary
|
objtyp = BINFIL; //Default Object File Type to Binary
|
||||||
pcargs(argc, argv); //Parse Command Line Arguments
|
pcargs(argc, argv); //Parse Command Line Arguments
|
||||||
@ -568,5 +647,6 @@ int main(int argc, char *argv[]) {
|
|||||||
asmfil(1); //Assemble Input File (First Pass)
|
asmfil(1); //Assemble Input File (First Pass)
|
||||||
asmfil(2); //Assemble Input File (First Pass)
|
asmfil(2); //Assemble Input File (First Pass)
|
||||||
if (lstfil) prtsym(); //Print Symbol Table
|
if (lstfil) prtsym(); //Print Symbol Table
|
||||||
|
exit(0); //Exit with No Errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
123
a02.h
123
a02.h
@ -1,8 +1,8 @@
|
|||||||
/* Definitions for A02 Assembler */
|
/* Definitions for A02 Assembler */
|
||||||
|
|
||||||
#define MAXSTR 128 //Maximum String Length
|
#define MAXSTR 128 //Maximum String Length
|
||||||
#define MAXSYM 8 //Maximum Symbol Length
|
#define MAXLBL 8 //Maximum Symbol Length
|
||||||
#define MAXGLB 1024 //Maximum Number of Global Labels
|
#define MAXSYM 1024 //Maximum Number of Global Labels
|
||||||
|
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE -1
|
#define TRUE -1
|
||||||
@ -22,83 +22,60 @@
|
|||||||
#define INDCY 0x0800 //(Indirect),Y
|
#define INDCY 0x0800 //(Indirect),Y
|
||||||
#define RELTV 0x1000 //Relative
|
#define RELTV 0x1000 //Relative
|
||||||
|
|
||||||
struct opc {char name[4], token; int amode;};
|
struct amd {int amode; char desc[12];};
|
||||||
|
struct amd amdesc[] = {
|
||||||
|
{ACMLT, "Accumulator"},
|
||||||
|
{IMMDT, "Immediate"},
|
||||||
|
{ZPAGE, "Zero Page"},
|
||||||
|
{ZPAGX, "Zero Page,X"},
|
||||||
|
{ABSLT, "Absolute"},
|
||||||
|
{ABSLX, "Absolute,X"},
|
||||||
|
{ABSLY, "Absolute,Y"},
|
||||||
|
{IMPLD, "Implied"},
|
||||||
|
{INDCT, "(Indirect)"},
|
||||||
|
{INDCX, "(Indirect,X)"},
|
||||||
|
{INDCY, "(Indirect),Y"},
|
||||||
|
{RELTV, "Relative"},
|
||||||
|
{0, ""}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct opc {char name[5], token; int amode;};
|
||||||
|
struct opc psolst[] = {
|
||||||
|
{"BYTE", 'B', 0}, {"WORD", 'W', 0}, {"EQU", '=', 0}, {"FILL", 'F', 0}, {"INCL", 'I', 0},
|
||||||
|
{"SUBR", 'S', 0}, {"ORG", '*', 0}, {"PROC", 'P', 0}, {"DC", 'B', 0}, {"DS", 'F', 0},
|
||||||
|
{"", 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
struct opc opclst[] = {
|
struct opc opclst[] = {
|
||||||
{"EQU", '=', 0},
|
{"BRK", 0x00, 0x0100}, {"NOP", 0xEA, 0x0100}, {"STP", 0xDB, 0x0100}, {"WAI", 0xCB, 0x0100},
|
||||||
{"BYT", 'B', 0},
|
{"DEX", 0xCA, 0x0100}, {"DEY", 0x88, 0x0100}, {"INX", 0xE8, 0x0100}, {"INY", 0xC8, 0x0100},
|
||||||
{"WOR", 'W', 0},
|
{"PHA", 0x48, 0x0100}, {"PHP", 0x08, 0x0100}, {"PHX", 0xDA, 0x0100}, {"PHY", 0x5A, 0x0100},
|
||||||
{"FIL", 'F', 0},
|
{"PLA", 0x68, 0x0100}, {"PLP", 0x28, 0x0100}, {"PLX", 0xFA, 0x0100}, {"PLY", 0x7A, 0x0100},
|
||||||
{"SUB", 'S', 0},
|
{"CLC", 0x18, 0x0100}, {"CLD", 0xD8, 0x0100}, {"CLI", 0x58, 0x0100}, {"CLV", 0xB8, 0x0100},
|
||||||
{"ORG", '*', 0},
|
{"SEC", 0x38, 0x0100}, {"SED", 0xF8, 0x0100}, {"SEI", 0x78, 0x0100},
|
||||||
{"PRO", 'P', 0},
|
{"TAX", 0xAA, 0x0100}, {"TAY", 0xA8, 0x0100}, {"TSX", 0xBA, 0x0100},
|
||||||
{"BRK", 0x00, 0x0100},
|
{"TXA", 0x8A, 0x0100}, {"TYA", 0x98, 0x0100}, {"TXS", 0x9A, 0x0100},
|
||||||
{"CLC", 0x18, 0x0100},
|
{"RTI", 0x40, 0x0100}, {"RTS", 0x60, 0x0100},
|
||||||
{"CLD", 0xD8, 0x0100},
|
|
||||||
{"CLI", 0x58, 0x0100},
|
{"BCS", 0xB0, 0x1000}, {"BEQ", 0xF0, 0x1000}, {"BMI", 0x30, 0x1000}, {"BVS", 0x70, 0x1000},
|
||||||
{"CLV", 0xB8, 0x0100},
|
{"BCC", 0x90, 0x1000}, {"BNE", 0xD0, 0x1000}, {"BPL", 0x10, 0x1000}, {"BVC", 0x50, 0x1000},
|
||||||
{"DEX", 0xCA, 0x0100},
|
{"BRA", 0x80, 0x1000},
|
||||||
{"DEY", 0x88, 0x0100},
|
|
||||||
{"INX", 0xE8, 0x0100},
|
{"LDA", 0xA1, 0x0EFE}, {"ADC", 0x61, 0x0EFE}, {"AND", 0x21, 0x0EFE}, {"CMP", 0xC1, 0x0EFE},
|
||||||
{"INY", 0xC8, 0x0100},
|
{"STA", 0x81, 0x0EFE}, {"SBC", 0xE1, 0x0EFE}, {"ORA", 0x01, 0x0EFE}, {"EOR", 0x41, 0x0EFE},
|
||||||
{"NOP", 0xEA, 0x0100},
|
|
||||||
{"PHA", 0x48, 0x0100},
|
{"ASL", 0x02, 0x007D}, {"ROL", 0x22, 0x007D}, {"INC", 0xE2, 0x007D}, {"LSR", 0x42, 0x007D},
|
||||||
{"PHP", 0x08, 0x0100},
|
{"ROR", 0x62, 0x007D}, {"DEC", 0xC2, 0x007D},
|
||||||
{"PHX", 0xDA, 0x0100},
|
|
||||||
{"PHY", 0x5A, 0x0100},
|
{"TRB", 0x10, 0x0024}, {"TSB", 0x00, 0x0024},
|
||||||
{"PLA", 0x68, 0x0100},
|
{"CPX", 0xE0, 0x0026}, {"CPY", 0xC0, 0x0026},
|
||||||
{"PLP", 0x28, 0x0100},
|
{"LDX", 0xA2, 0x00A6}, {"STX", 0x82, 0x00A6},
|
||||||
{"PLX", 0xFA, 0x0100},
|
|
||||||
{"PLY", 0x7A, 0x0100},
|
|
||||||
{"RTI", 0x40, 0x0100},
|
|
||||||
{"RTS", 0x60, 0x0100},
|
|
||||||
{"SEC", 0x38, 0x0100},
|
|
||||||
{"SED", 0xF8, 0x0100},
|
|
||||||
{"SEI", 0x78, 0x0100},
|
|
||||||
{"STP", 0xDB, 0x0100},
|
|
||||||
{"TAX", 0xAA, 0x0100},
|
|
||||||
{"TAY", 0xA8, 0x0100},
|
|
||||||
{"TSX", 0xBA, 0x0100},
|
|
||||||
{"TXA", 0x8A, 0x0100},
|
|
||||||
{"TXS", 0x9A, 0x0100},
|
|
||||||
{"TYA", 0x98, 0x0100},
|
|
||||||
{"WAI", 0xCB, 0x0100},
|
|
||||||
{"ADC", 0x61, 0x0EFE},
|
|
||||||
{"AND", 0x21, 0x0EFE},
|
|
||||||
{"CMP", 0xC1, 0x0EFE},
|
|
||||||
{"EOR", 0x41, 0x0EFE},
|
|
||||||
{"LDA", 0xA1, 0x0EFE},
|
|
||||||
{"ORA", 0x01, 0x0EFE},
|
|
||||||
{"SBC", 0xE1, 0x0EFE},
|
|
||||||
{"STA", 0x81, 0x0EFE},
|
|
||||||
{"ASL", 0x02, 0x007D},
|
|
||||||
{"DEC", 0xC2, 0x007D},
|
|
||||||
{"INC", 0xE2, 0x007D},
|
|
||||||
{"LSR", 0x42, 0x007D},
|
|
||||||
{"ROL", 0x22, 0x007D},
|
|
||||||
{"ROR", 0x62, 0x007D},
|
|
||||||
{"BIT", 0x20, 0x006E},
|
{"BIT", 0x20, 0x006E},
|
||||||
{"CPX", 0xE0, 0x0026},
|
|
||||||
{"CPY", 0xC0, 0x0026},
|
|
||||||
{"LDY", 0xA0, 0x006E},
|
|
||||||
{"BIT", 0x20, 0x006C},
|
|
||||||
{"STY", 0x80, 0x002C},
|
|
||||||
{"STZ", 0x60, 0x006C},
|
{"STZ", 0x60, 0x006C},
|
||||||
{"TRB", 0x10, 0x0024},
|
|
||||||
{"TSB", 0x00, 0x0024},
|
|
||||||
{"LDX", 0xA2, 0x00A6},
|
|
||||||
{"STX", 0x82, 0x00A6},
|
|
||||||
{"JMP", 0x4C, 0x0620},
|
{"JMP", 0x4C, 0x0620},
|
||||||
{"JSR", 0x14, 0x0020},
|
{"JSR", 0x14, 0x0020},
|
||||||
{"BCC", 0x90, 0x1000},
|
{"LDY", 0xA0, 0x002E},
|
||||||
{"BCS", 0xB0, 0x1000},
|
{"STY", 0x80, 0x002C},
|
||||||
{"BEQ", 0xF0, 0x1000},
|
|
||||||
{"BMI", 0x30, 0x1000},
|
|
||||||
{"BNE", 0xD0, 0x1000},
|
|
||||||
{"BPL", 0x10, 0x1000},
|
|
||||||
{"BRA", 0x80, 0x1000},
|
|
||||||
{"BVC", 0x50, 0x1000},
|
|
||||||
{"BVS", 0x70, 0x1000},
|
|
||||||
{"", 0, 0}
|
{"", 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user