Added ENDSUBROUTINE mnemonic to c02 compiler and a02 assembler

This commit is contained in:
Curtis F Kaylor 2020-10-04 11:00:01 -04:00
parent 67514ba522
commit 3077a43859
4 changed files with 90 additions and 42 deletions

126
a02.c
View File

@ -12,6 +12,9 @@
#define DEBUG FALSE
int debug; //Ouput Debug Info
#define INCLEN 255
char incpath[INCLEN];
enum otypes {BINFIL, PRGFIL}; //Object File Types
char objtyp; //Object File Type
@ -23,16 +26,18 @@ struct sym {int block; char name[MAXLBL+1]; int bytes, value, refrd;};
struct sym symbol; //Current Symbol
struct sym symtbl[MAXSYM]; //Global Symbol Table
int symcnt; //Number of Global Labels
int blkcnt; //Number of Block Labels Generated
int blknum; //Local Label Block Number (0 = Global)
char label[MAXSTR]; //Assembly Line Label
char mnmnc[MAXSTR]; //Opcode Mnemonic
char oprnd[MAXSTR]; //Opcode Mnemonic
char oprnd[MAXSTR]; //Operand Text
char cmmnt[MAXSTR]; //Assembly Line Comment
char mcode[MAXSTR]; //Generated Bytes
char strng[MAXSTR]; //Parsed String
int opridx; //Index into Operand
char cpdchr; //Last Character Copied into oprnd
unsigned char token, opmod; //OpCode Token, Modifier
unsigned int amode; //Addressing Modes
@ -67,25 +72,52 @@ void usage(char* appnam) {
exit(EXIT_FAILURE);
}
/* Print Symbol Table */
void prtsym(void) {
fprintf(lstfil, "\n%s Symbol Table\nBlock Name Size Value Rfd\n", "Global");
for (int i=0; i<symcnt; i++) {
int refrd = (symtbl[i].refrd) ? '*' : ' ';
fprintf(lstfil, "%5d %-8s %4d %5d %c \n", symtbl[i].block, symtbl[i].name, symtbl[i].bytes, symtbl[i].value, refrd);
}
}
/* Print Error Dump Info */
void xdump(void) {
puts("Error Dump");
oprnd[opridx]=0; printf("Operand: %s\n", oprnd);
}
/* Print Error Message to Stream */
void xprint(FILE *fp, char* format, char *s) {
if (lineno) fprintf(fp, "%04d: ", lineno);
fprintf(fp, format, s);
}
/* Print Error Message and Exit */
void xerror(char* format, char *s) {
if (debug) xdump();
if (lineno) fprintf(stderr, "%04d: ", lineno);
fprintf(stderr, format, s);
xprint(stderr, format, s);
if (lstfil) xprint(stderr, format, s);
if (lstfil && symcnt) prtsym();
exit(EXIT_FAILURE);
}
/* Open File with Error Checking */
FILE * opnfil(char* name, char* mode) {
FILE * opnfil(char* name, char* mode, char* path) {
if (debug) printf("Opening file '%s' with mode '%s'\n", name, mode);
FILE *fp = fopen(name, mode);
if (!fp) {
char spec[256];
char *token = strtok(path, " ");
while (token) {
strcpy(spec, path); strcat(spec, "\\"); strcat(spec, name);
if (debug) printf("Opening file \"%s\" with mode \"%s\"\n", spec, mode);
fp = fopen(spec, mode); if (fp) break;
token = strtok(NULL, " ");
}
}
if (!fp) xerror("Error Opening File '%s'\n", name);
if (debug) printf("File Opened\n");
return fp;
}
@ -120,8 +152,11 @@ int pword(int skip, char* word) {
}
struct sym *fndsym(int block, char* name) {
if (debug) printf("Searching for Symbol %s in block %d\n", name, block);
for (int i=0; i < symcnt; i++) {
if (symtbl[i].block != block || strcmp(symtbl[i].name,name)) continue;
if (debug) printf("Found Symbol %s, block %d, size %d, value %04x\n",
symtbl[i].name, symtbl[i].block, symtbl[i].bytes, symtbl[i].value);
return &symtbl[i];
}
return NULL;
@ -129,13 +164,14 @@ struct sym *fndsym(int block, char* name) {
/* Set Symbol Value and Size */
void setsym(int value, int bytes) {
if (debug) printf("Setting Symbol %s to %d\n", symbol.name, value);
symbol.value = value;
if (bytes) symbol.bytes = bytes;
else symbol.bytes = (value > 0xFF) ? 2 : 1;
symbol.refrd = FALSE;
if (debug) printf("Set Symbol %s in block %d to value %d, size %d, referred=False\n",
symbol.name, symbol.block, symbol.bytes, symbol.value);
}
/* Add Character to Beginning of String */
void pfxstr(char c, char* s) {
for (int i=strlen(s)+1; i; i--)
@ -172,7 +208,8 @@ int plabel(void) {
/* Copy Character to Operand and Increment */
int cpychr(int c) {
if (c && toupper(*linptr) != c) return FALSE;
if (opridx < MAXSTR) oprnd[opridx++] = toupper(*linptr);
cpdchr = *linptr;
if (opridx < MAXSTR) oprnd[opridx++] = toupper(cpdchr);
linptr++;
return TRUE;
}
@ -267,10 +304,12 @@ int evlopd(int maxsiz) {
if (hilo) prns = cpychr('(');
result = evltrm();
if (result >= 0)
while (cpychr('+')) {
while (cpychr('+') || cpychr('-')) {
int opertr = cpdchr;
int opdval = evltrm();
if (opdval < 0) break;
result += opdval;
if (opertr == '+') result += opdval;
else result -= opdval;
}
if (hilo) {
if (result < 0) xerror("Hi/Low Operator Requires Operand", "");
@ -386,11 +425,18 @@ void asmprc(void) {
/* Assemble SUBROUTINE Pseudo-Op */
void asmsub(void) {
blknum++;
blknum = ++blkcnt;
sprintf(oprnd, "%d", blknum); opridx = strlen(oprnd);
if (debug) printf("Block Number set to %s\n", oprnd);
}
/* Assemble ENDSUBROUTINE Pseudo-Op */
void asmens(void) {
blknum = 0;
sprintf(oprnd, "%d", blknum); opridx = strlen(oprnd);
if (debug) printf("Block Number reset to %s\n", oprnd);
}
/* Assemble INCLUDE Pseudo-Op */
void asminf(void) {
int incidx = 0;
@ -419,11 +465,12 @@ int asmpso(int dot) {
if (debug) printf("Assembling Pseudo-Op %s, Token '%c'\n", mnmnc, token);
switch (token) {
case '=': asmequ(); break; //EQU
case 'B': asmbyt(); break; //BYTE
case 'H': asmhex(); break; //BYTE
case 'B': asmbyt(); break; //BYTE or DC
case 'H': asmhex(); break; //HEX
case 'W': asmwrd(); break; //WORD
case 'F': asmfll(); break; //FILL
case 'F': asmfll(); break; //FILL or DS
case 'S': asmsub(); break; //SUBRoutine
case 'M': asmens(); break; //ENDSubroutine
case 'I': asminf(); break; //INCLude
case '*': asmorg(); break; //ORG
case 'P': asmprc(); break; //PROCessor
@ -614,6 +661,7 @@ void pcmmnt(void) {
void addsym() {
if (symbol.value<0) xerror("Origin Not Set", "");
memcpy(&symtbl[symcnt++], &symbol, sizeof(symbol));
if (debug) printf("Added symbol %s in block %d to Symbol Table\n", symbol.name, symbol.block);
}
@ -621,7 +669,7 @@ void addsym() {
void opninc(void) {
if (debug) printf("Opening Include File %s\n", incnam);
if (lstfil) fputs("\n", lstfil);
incfil = opnfil(incnam, "r");
incfil = opnfil(incnam, "r", incpath);
savlno = lineno;
lineno = 1;
}
@ -634,7 +682,7 @@ void clsinc(void) {
incfil = NULL;
incnam[0] = 0;
lineno = savlno;
endasm = FALSE; //Clear End Flag for Return to Maun File
endasm = FALSE; //Clear End Flag for Return to Main File
}
/* Assemble Input File (Two Pass) *
@ -647,7 +695,8 @@ void asmfil(int pass) {
passno = pass; //Assembly Pass Number
if (debug) printf("Assembling Pass %d\n", pass);
lineno = 1; //Initialize Input File Line Number
blknum = 1; //Initialize Local Block Number
blkcnt = 0; //Initialize Local Block Count
blknum = 0; // and Local Block Number
orgadr = -1; //Origin Address Not Set
curadr = orgadr; //Set Current Address to Origin
if (debug) printf("Rewinding Input File\n");
@ -656,7 +705,7 @@ void asmfil(int pass) {
if (incfil) linptr = fgets(inplin, MAXSTR, incfil);
else linptr = fgets(inplin, MAXSTR, inpfil);
if (endasm || linptr == NULL) {if (incfil) {clsinc(); continue;} else break;}
if (debug) printf("%05d %04X: %s", lineno, curadr, inplin);
if (debug) printf("%1d %05d %04X: %s", passno, lineno, curadr, inplin);
lstadr = curadr; //Set List Address
mcode[0] = 0; //Clear Generated Macbine Code
plabel(); //Parse Label
@ -673,15 +722,6 @@ void asmfil(int pass) {
}
}
/* Print Symbol Table */
void prtsym(void) {
fprintf(lstfil, "\n%s Symbol Table\nBlock Name Size Value Rfd\n", "Global");
for (int i=0; i<symcnt; i++) {
int refrd = (symtbl[i].refrd) ? '*' : ' ';
fprintf(lstfil, "%5d %-8s %4d %5d %c \n", symtbl[i].block, symtbl[i].name, symtbl[i].bytes, symtbl[i].value, refrd);
}
}
/* Parse Command Line Option */
int pcoptn(char *argval) {
if (argval[0] != '-') return FALSE;
@ -701,6 +741,11 @@ void pcargs(int argc, char *argv[]) {
for (int arg = 0; arg<argc; arg++) {
if (debug) printf("Arg %d='%s'\n", arg, argv[arg]);
if (arg == 0) {strcpy(prgnam, argv[arg]); continue;}
if (strcmp(argv[arg], "-i") ==0) {
strcpy(incpath, argv[++arg]);
if (debug) printf("Include Path set to \"%s\"\n", incpath);
continue;
}
if (pcoptn(argv[arg])) continue;
switch (argnum++) {
case 0: strcpy(inpnam, argv[arg]); break;
@ -713,19 +758,20 @@ void pcargs(int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
debug = DEBUG; //Initialize Debug Flag
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)
objtyp = BINFIL; //Default Object File Type to Binary
pcargs(argc, argv); //Parse Command Line Arguments
inpfil = opnfil(inpnam, "r"); //Open Input File
outfil = opnfil(outnam, "wb"); //Open Output File
if (lstnam[0]) //If List File Name Specified
lstfil = opnfil(lstnam, "w"); // Open List File
asmfil(1); //Assemble Input File (First Pass)
asmfil(2); //Assemble Input File (First Pass)
if (lstfil && symcnt) prtsym(); //Print Symbol Table
exit(0); //Exit with No Errors
debug = DEBUG; //Initialize Debug Flag
incpath[0] = 0; //Initialize Include File Path
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)
objtyp = BINFIL; //Default Object File Type to Binary
pcargs(argc, argv); //Parse Command Line Arguments
inpfil = opnfil(inpnam, "r", ""); //Open Input File
outfil = opnfil(outnam, "wb", ""); //Open Output File
if (lstnam[0]) //If List File Name Specified
lstfil = opnfil(lstnam, "w", ""); // Open List File
asmfil(1); //Assemble Input File (First Pass)
asmfil(2); //Assemble Input File (First Pass)
if (lstfil && symcnt) prtsym(); //Print Symbol Table
exit(0); //Exit with No Errors
}

4
a02.h
View File

@ -2,7 +2,7 @@
#define MAXSTR 128 //Maximum String Length
#define MAXLBL 8 //Maximum Symbol Length
#define MAXSYM 1024 //Maximum Number of Global Labels
#define MAXSYM 1024 //Maximum Number of Labels
#define FALSE 0
#define TRUE -1
@ -45,7 +45,7 @@ struct opc {char name[5], token; int amode;};
struct opc psolst[] = {
{"BYTE", 'B', 0}, {"HEX", 'H'}, {"WORD", 'W', 0}, {"EQU", '=', 0}, {"FILL", 'F', 0},
{"INCL", 'I', 0}, {"SUBR", 'S', 0}, {"DC", 'B', 0}, {"DS", 'F', 0}, {"ALIG", 'A', 0},
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"", 0, 0}
{"ORG", '*', 0}, {"PROC", 'P', 0}, {"END", 'E', 0}, {"ENDS", 'M', 0}, {"", 0, 0}
};
struct opc opclst[] = {

View File

@ -34,6 +34,7 @@
#define ALNOP "ALIGN" //Align Pseudo-Op
#define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op
#define LOCOP "SUBROUTINE" //Local Variable Boundary Pseudo-Op
#define LOCEND "ENDSUB" //End Local Variables Pseudo-Op
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format

View File

@ -110,6 +110,7 @@ void reqlbl(char* lbname) {
void endfnc(void) {
DEBUG("label.endfnc: Ending function definition with lsrtrn set to %d\n", lsrtrn)
if (!lsrtrn) asmlin("RTS", "");
asmlin(LOCEND, "");
infunc = FALSE;
DEBUG("label.endfnc: Set infunc to %d\n", infunc)
}