#include #include #include #include #include #include "assemble.h" void writeoutput (char *, unsigned char [], long, long); int main (int argc, char *argv[]) { FILE *f; int i, done, pass, line_no, verbose, hexout, writebinary; static Command_Node *mnemonic_head; static Label_Node *label_head; static unsigned char code[65535]; static long start_address, address, end_address; char c, filename[255], binaryname[255]; /* Get list of mnemonics and predefined labels*/ mnemonic_head = create_mnemonic_list(); label_head = create_label_list(); read_mnemonics("mnemonics", mnemonic_head); read_labels("labels", label_head); /* Clear output Buffer */ for (i=0; i<=65535; i++) code[i] = 0xFF; address = 0x200; done = 1; verbose = 0; line_no = 0; hexout = 0; writebinary = 0; while ((c = getopt (argc, argv, "a:vVhdo:")) != EOF) { switch (c) { case ('a'): printf ("Output address: %s\n", optarg); sscanf (optarg, "%lx", &address); break; case ('v'): printf ("Verbosity Level: 1\n"); verbose = 1; break; case ('V'): printf ("Verbosity Level: 2\n"); verbose = 2; break; case ('d'): hexout = 1; break; case ('h'): showhelp(); exit (EXIT_SUCCESS); break; case ('o'): strcpy (binaryname, optarg); writebinary = 1; break; } } /* Search for a filename */ for (i=1; i0) printf ("\n\nStarting Pass 1...\n\n"); start_address = 0xFFFF; end_address = 0; pass = 1; assemble (f, &start_address, &end_address, address, pass, verbose, code, label_head, mnemonic_head); fclose (f); } else { fprintf (stderr, "Unknown File: %s\n\n", filename); exit (EXIT_FAILURE); } /********************************************************************** * Pass 2 * **********************************************************************/ if ((f = fopen(filename,"r")) != NULL) { if (verbose>0) printf ("\n\nStarting Pass 2...\n\n"); start_address = 0xFFFF; end_address = 0; pass = 2; assemble (f, &start_address, &end_address, address, pass, verbose, code, label_head, mnemonic_head); fclose (f); } else { fprintf (stderr, "Unknown File: %s\n\n", filename); exit (EXIT_FAILURE); } /* Display hex dump */ if (hexout == 1) print_hex(start_address, code, (end_address - start_address)); if (writebinary == 1) writeoutput (binaryname, code, start_address, end_address); return 0; } void writeoutput (char *filename, unsigned char code[], long start_address, long end_address) { long length; FILE *f; length = end_address - start_address; if ((f=fopen(filename,"wb")) != NULL) { fwrite(&code[start_address], 1, length, f); fclose(f); } else { fprintf (stderr, "Could not open file %s for writing", filename); exit (EXIT_FAILURE); } } void showhelp() { printf ("Usage: assemble [OPTIONS] [FILE]\n"); printf ("6502 / EPE Microlab cross-assembler\n"); printf ("Assemble FILE\n\n"); printf (" -a change default output address\n"); printf (" -d print hex dump\n"); printf (" -h this helpful information\n"); printf (" -o output raw binary file\n"); printf (" -v print formatted source\n"); printf (" -V print more detailed information\n\n"); } /******************************************************************** * Do 4-column Hex Dump * ********************************************************************/ void print_hex (long start_address, unsigned char code[], int length) { int i; long address; address = start_address; printf ("\nOccupies: $%.4lX -> $%.4lX\n\n", start_address, start_address + length); for (i=0; i<=length; i+=4) { printf("$%.4lX: %.2X %.2X %.2X %.2X\n", address, code[address], code[address+1], code[address+2], code[address+3]); address += 4; } } /******************************************************************** * Display information about each line of code * ********************************************************************/ void print_info (OperandType operand, int verbose, long address, char mnemonic[], unsigned char output[]) { int i; char tmp[30], line[60]; if (verbose > 1) { printf ("\nMnemonic: %s\n", mnemonic); printf ("Operand: %s\n", operand.orig); printf ("Addressing Type: %s\n", operand.addtype_text); printf ("Value: $%.4lX\n", operand.value); printf ("Formatted: %s %s\n", mnemonic, operand.formatted); } if (verbose > 0) { sprintf (line, "$%.4lX: ", address); for (i=1; i <= ((char) output[0]); i++) { sprintf (tmp, "$%.2X ", output[i]); strcat (line, tmp); } /* Pad to 22 chars */ for (i = strlen(line); i<22; i++) line[i]=' '; line[i] = '\0'; sprintf (tmp, "%s %s", mnemonic, operand.formatted); strcat (line,tmp); /* If there's a label associated with the line, print it */ if (strcmp(operand.label, "")) { /* Pad to 38 chars */ for (i = strlen(line); i<38; i++) line[i]=' '; line[i] = '\0'; sprintf (tmp, "== (%s)", operand.label); strcat (line, tmp); } printf ("Opcode (%d bytes): %s\n", (char) output[0], line); } } /******************************************************************** * Add label to linked list and return 0 if it doesn't exist * * Return 1 if the label already exists * ********************************************************************/ int do_labels(Label_Node *head, char name[], long value) { int i; /* Convert label to upercase */ for (i = 0; i= 2) type = COMMAND_OPER; else type = COMMAND_NOOPER; return type; } /******************************************************************** * Get line from stdin. Terminate on \n * ********************************************************************/ int getline(char line[], int max) { int c; int i = 0; while ((c = getchar()) != '\n' && c != EOF) if (i < max) line [i++] = c; line[i] = '\0'; return (c == EOF) ? -1 : i; } /******************************************************************** * Return first character of line * ********************************************************************/ char getfirstchar(char line[]) { int i; for (i=0; i <= (int) strlen(line); i++) { if (isgraph(line[i])) { return line[i]; i = strlen(line); } } return '\0'; }