all repos — nand2tetris @ 3d7b57086cfd40e7f87306605b6ec2f7cc7f74f2

my nand2tetris progress

Rewrite: Parse C-type comp field, add output file
x1phosura x1phosura@x1phosura.zone
Mon, 13 Feb 2023 03:59:42 -0800
commit

3d7b57086cfd40e7f87306605b6ec2f7cc7f74f2

parent

1c1e42a8e01158d697c02a22f3b44c67d37c833b

1 files changed, 56 insertions(+), 43 deletions(-)

jump to
M projects/06/assembler2/assembler2.cprojects/06/assembler2/assembler2.c

@@ -40,21 +40,17 @@ uint16_t symbol_vals[MAX_SYMBOLS + sizeof(reserved_vals)];

uint16_t symbol_index; uint16_t next_var_address = 16; -void print_binary_word16(uint16_t w) -{ - unsigned char i; - char binary_string[17]; - for (i = 0; i < 16; ++i, w <<= 1) - binary_string[i] = (((w >> 15) & 0x01) != 0) ? '1' : '0'; - binary_string[16] = '\0'; - printf("%s\n", binary_string); -} -static void print_rom_binary(uint16_t *rom, size_t rom_size) +static void write_rom_binary(FILE *fp) { - size_t i; - for (i = 0; i < rom_size; ++i) - print_binary_word16(rom[i]); + size_t i, k; + char bin_str[17]; + for (i = 0; i < rom_index; ++i) { + for (k = 0; k < 16; ++k, rom[i] <<= 1) + bin_str[k] = (((rom[i] >> 15) & 0x01) != 0) ? '1' : '0'; + bin_str[16] = '\0'; + fprintf(fp, "%s\n", bin_str); + } } static size_t skip_whitespace(const char *line, size_t n)

@@ -64,14 +60,14 @@ for (i = 0; is_whitespace(line[i]) && i < n; ++i);

return i; } -static void debug_dump_all_symbols() -{ - size_t i; - DBGLOG("-------- DEBUG SYMBOL DUMP --------\n"); - for (i = 0; i < symbol_index; ++i) - DBGLOG("symbol (%s, %hu)\n", symbol_strs[i], symbol_vals[i]); - DBGLOG("-------- END SYMBOL DUMP --------\n"); -} +//static void debug_dump_all_symbols() +//{ +// size_t i; +// DBGLOG("-------- DEBUG SYMBOL DUMP --------\n"); +// for (i = 0; i < symbol_index; ++i) +// DBGLOG("symbol (%s, %hu)\n", symbol_strs[i], symbol_vals[i]); +// DBGLOG("-------- END SYMBOL DUMP --------\n"); +//} static char *lookup_symbol(const char *str, uint16_t *val) {

@@ -136,7 +132,6 @@ if (c != ')')

return err("error: no matching ')' found for label\n"); label_str[i - 1] = '\0'; - return add_symbol(label_str, (uint16_t)instruction_offset); }

@@ -175,9 +170,33 @@ /* returns comp bits 0b0acccccc

*/ bool parse_c_type_comp(const char *line, uint16_t *comp) { - // also length check here since it's not being done in parse_c_type() - *comp = 0x32; - return true; + size_t i; + char comp_str[5]; + char *comp_tb[] = {"0", "1", "-1", "D", "A", "M", "!D", "!A", + "!M", "-D", "-A", "-M", "D+1", "A+1", "M+1", "D-1", + "A-1", "M-1", "D+A", "D+M", "D-A", "D-M", "A-D", + "M-D", "D&A", "D&M", "D|A", "D|M"}; + char comp_vals[] = {0x2a, 0x3f, 0x3a, 0x0c, 0x30, 0x70, 0x0d, 0x31, + 0x71, 0x0f, 0x33, 0x73, 0x1f, 0x37, 0x77, 0x0e, + 0x32, 0x72, 0x02, 0x42, 0x13, 0x53, 0x07, + 0x47, 0x00, 0x40, 0x15, 0x55}; + + for (i = 0; i < 5 && !is_whitespace(line[i]) && line[i] != ';' + && line[i] != '/'; ++i) + comp_str[i] = line[i]; + + comp_str[i] = '\0'; + if (i > 4) + return err("syntax error: invalid comp field '%s'\n", comp_str); + + for (i = 0; i < (sizeof(comp_tb) / sizeof(comp_tb[0])); ++i) { + if (strncmp(comp_tb[i], comp_str, 3) == 0) { + *comp = (uint16_t)comp_vals[i]; + return true; + } + } + + return err("syntax error: invalid comp field '%s'\n", comp_str); } /* returns jump bits 0b00000jjj

@@ -223,9 +242,6 @@ comp_start = &line[i+1];

} else if (c == ';') jump_start = &line[i+1]; } - - DBGLOG("C-type, offset %lu, line %lu | %s \n", instruction_offset, - file_line_no, line); // only comp field is mandatory; dest/jump are optional, may not exist if (comp_start == NULL)

@@ -359,9 +375,6 @@ continue; // first pass: if not label, ignore line

} } - if (first_pass) - debug_dump_all_symbols(); - return ret; }

@@ -371,13 +384,18 @@

int main(int argc, char *argv[]) { FILE *in_file, *out_file; - char *in_file_path, *out_file_path; - if (argc != 3) // requires 2 arguments - die(usage_msg); // TODO: eventually support STDOUT + char *in_file_path; + if (argc == 2) { + out_file = stdout; + } else if (argc == 3) { + out_file = fopen(argv[2], "wb"); + if (out_file == NULL) + die("failed to open output file for writing\n"); + } else { + die(usage_msg); + } in_file_path = argv[1]; - out_file_path = argv[2]; - in_file = fopen(in_file_path, "r"); if (in_file == NULL) die("failed to open assembly file for reading\n");

@@ -385,19 +403,14 @@

if(!pass(in_file, true)) // first pass die("failed to parse labels/variables in file\n"); + //debug_dump_all_symbols(); if (fseek(in_file, 0, SEEK_SET)) die("failed to re-read file from beginning\n"); - DBGLOG("SECOND PASS\n"); if(!pass(in_file, false)) // second pass die("failed to parse assembly in file\n"); - out_file = fopen(out_file_path, "wb"); - if (out_file == NULL) - die("failed to open output file for writing\n"); - - //fwrite(rom, rom_index, 1, out_fp); // TODO: double-check - print_rom_binary(rom, rom_index); + write_rom_binary(out_file); if (fclose(in_file)) die("failed to close assembly file\n"); if (fclose(out_file))