Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * file: assembler.c
- * author: matthew.james.bird@gmail.com
- *
- * usage of assembler for the hack assembly language.
- *
- */
- #include "assemble.h"
- int main(int argc, char* argv[])
- {
- // check input is correct
- if (argc != 3)
- {
- fprintf(stderr, "Usage: assembler source outputn");
- return 1;
- }
- // open source file
- FILE* source = fopen(argv[1], "rb");
- if (source == NULL)
- {
- fprintf(stderr, "Error: cannot open source file %sn", argv[1]);
- return 1;
- }
- // open output file
- FILE* output = fopen(argv[2], "wb");
- if (output == NULL)
- {
- fprintf(stderr, "Error: cannot open output file %sn", argv[2]);
- fclose(source);
- return 1;
- }
- if (assemble(source, output) == false)
- {
- printf("Quitting.n");
- return 1;
- }
- return 0;
- }
- /**
- * file: assemble.h
- * author: matthew.james.bird@gmail.com
- *
- * assembler for the hack assembly language.
- *
- */
- #include <stdio.h>
- #include <stdbool.h>
- #define MAX_A 32767
- #define COMP_TABLE_SIZE 28
- #define JUMP_TABLE_SIZE 7
- #define MAX_SYMBOL_SIZE 10
- // node for symbol and its translation
- typedef struct symNode
- {
- char symbol[MAX_SYMBOL_SIZE];
- char translation[17];
- struct symNode* next;
- }
- symNode;
- // node for comp code and its translation
- typedef struct compNode
- {
- char entry[4];
- char translation[8];
- }
- compNode;
- // node for jump code and its translation
- typedef struct jumpNode
- {
- char entry[4];
- char translation[4];
- }
- jumpNode;
- /**
- * assemble: translates source assembly file into machine code.
- * returns true on success, else false;
- */
- bool assemble(FILE* source, FILE* output);
- /**
- * addSym: add the symbol-translation pair to the start of the linked list beginning with head.
- * returns true on success, else false.
- */
- bool addSym(const char* symbol, const char* translation, int line);
- /**
- * buildTables: builds the table for comp/jump codes and their translations.
- * returns true on success, else false.
- */
- bool buildTables(void);
- /**
- * clearTables: frees the tables of comp/jump codes and their translations.
- */
- void clearTables(void);
- /**
- * decodeA: reads in an A instruction from source, and outputs the a-instruction to out, converted to binary.
- * returns source line number, or -1 if error.
- */
- int decodeA(FILE* source, FILE* output, int line);
- /**
- * writeComp: translates comp and outputs it to output.
- * returns true on success, else false.
- */
- bool writeComp(char* comp, FILE* output);
- /**
- * writeJump: translates jump and outputs it to output.
- * returns true on success, else false.
- */
- bool writeJump(char* jump, FILE* output);
- /**
- * decodeC: reads in a C instruction from source (first char is c), and outputs the C-instruction to out, converted to binary.
- * returns line number, or -1 on error.
- */
- int decodeC(char c, FILE* source, FILE* output, int line);
- /**
- * loadLabels: populates the symbol dictionary with all of the labels in the file.
- * returns true on success, else false;
- */
- bool loadLabels(FILE* source);
- /**
- * file: assemble.c
- * author: matthew.james.bird@gmail.com
- *
- * assembler for the hack assembly language.
- *
- * usage: assembler source output
- */
- #include "assemble.h"
- #include <stdio.h>
- #include <stdbool.h> // bool type
- #include <ctype.h> // isspace(), isdigit()
- #include <stdlib.h> // atoi()
- #include <string.h> // strcpy(), strcmp(), strchr()
- // head for symbol dictionary linked list
- symNode* symHead;
- // table for comp codes and their translations
- compNode* compDict[COMP_TABLE_SIZE];
- // table for jump codes and their translations
- jumpNode* jumpDict[JUMP_TABLE_SIZE];
- const char* compCodes[COMP_TABLE_SIZE] = {"0", "1", "-1", "D", "A", "!D", "!A", "-D", "-A",
- "D+1", "A+1", "D-1", "A-1", "D+A", "D-A", "A-D",
- "D&A", "D|A", "M", "!M", "-M", "M+1", "M-1", "D+M",
- "D-M", "M-D", "D&M", "D|M"};
- const char* compTranslations[COMP_TABLE_SIZE] = {"0101010", "0111111", "0111010", "0001100",
- "0110000", "0001101", "0110001", "0001111",
- "0110011", "0011111", "0110111", "0001110",
- "0110010", "0000010", "0010011", "0010011",
- "0000000", "0010101", "1110000", "1110001",
- "1110011", "1110111", "1110010", "1000010",
- "1010011", "1000111", "1000000", "1010101"};
- const char* jumpCodes[JUMP_TABLE_SIZE] = {"JGT", "JEQ", "JGE", "JLT", "JNE", "JLE", "JMP"};
- const char* jumpTranslations[JUMP_TABLE_SIZE] = {"001", "010", "011", "100", "101", "110", "111"};
- /**
- * addSym: add the symbol-translation pair to the start of the linked list beginning with head.
- * returns true on success, else false;
- */
- bool addSym(const char* symbol, const char* translation, int line)
- {
- // construct the new node
- symNode* temp = malloc(sizeof(symNode));
- if (temp == NULL)
- {
- fprintf(stderr, "Error (line %d): cannot malloc new symbol node.n", line);
- return false;
- }
- strcpy(temp->symbol, symbol);
- strcpy(temp->translation, translation);
- if (symHead != NULL) // list not empty
- {
- temp->next = symHead;
- }
- symHead = temp;
- return true;
- }
- /**
- * buildTables: builds the table for comp/jump codes and their translations.
- */
- bool buildTables(void)
- {
- int i;
- // build comp table
- for (i = 0; i < COMP_TABLE_SIZE; i++)
- {
- compNode* temp = malloc(sizeof(compNode));
- if (temp == NULL)
- {
- fprintf(stderr, "Error: cannot create comp tablen");
- return false;
- }
- strcpy(temp->entry, compCodes[i]);
- strcpy(temp->translation, compTranslations[i]);
- compDict[i] = temp;
- }
- // build jump table
- for (i = 0; i < JUMP_TABLE_SIZE; i++)
- {
- jumpNode* temp = malloc(sizeof(jumpNode));
- if (temp == NULL)
- {
- fprintf(stderr, "Error: cannot create jump tablen");
- return false;
- }
- strcpy(temp->entry, jumpCodes[i]);
- strcpy(temp->translation, jumpTranslations[i]);
- jumpDict[i] = temp;
- }
- // load default register symbols into symbol table
- int v;
- int k;
- int j;
- for (i = 0; i < 16; i++)
- {
- char* tempSym = malloc(4);
- if (tempSym == NULL)
- {
- fprintf(stderr, "Error: cannot create register tablen");
- return false;
- }
- char* tempTran = malloc(17);
- if (tempTran == NULL)
- {
- fprintf(stderr, "Error: cannot create register tablen");
- return false;
- }
- tempSym[0] = 'R';
- sprintf(tempSym+1, "%d", i);
- v = i;
- k = 0;
- for (j = 15; j >= 0; j--, k++)
- {
- tempTran[k] = '0' + ((v >> j) & 1);
- }
- tempTran[k] = '