From f66cbfcd6430b30a83e35c404ff3979aa3a55a30 Mon Sep 17 00:00:00 2001 From: bylex Date: Thu, 3 Oct 2024 16:10:23 +0200 Subject: [PATCH] Improve assembler fix errors and add label support --- assembler.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/assembler.c b/assembler.c index 09bc341..54394fc 100644 --- a/assembler.c +++ b/assembler.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -15,19 +16,50 @@ struct inst_t uint8_t params[3]; } instruction_default = {false, 0, 0, 0, 0}; -void parse_line(FILE** input_file) +struct label_t { - char line_buffer[256]; + char* label_name; + uint16_t addr; +}; + +struct inst_t parse_line(char* line_buffer, struct label_t* labels, unsigned int* labels_len) +{ + static unsigned int labels_index = 0; + static uint16_t current_addr = 0; int token_count = 0; char* token; struct inst_t inst = instruction_default; - fgets(line_buffer, 256, *input_file); - if(line_buffer[0] == ';') { - return; + return inst; + } + else if(line_buffer[0] == '$') + { + struct label_t label; + + int i = 0; + while(i < 256) + { + if(isspace(line_buffer[i])) + { + line_buffer[i] = '\0'; + } + i++; + } + + label.label_name = malloc(256); + strcpy(label.label_name, line_buffer); + label.addr = current_addr; + if(labels_index + 1 == labels_len) + { + *labels_len = *labels_len + 16; + labels = realloc(labels, (*labels_len) * sizeof(struct label_t)); + } + labels[labels_index] = label; + labels_index++; + return inst; } else { @@ -44,6 +76,19 @@ void parse_line(FILE** input_file) uint8_t i = 0; while(i < N_INSTRUCTIONS - 1) { + int token_len = strlen(token); + if(token_len != 3) + { + int i = 0; + while(i < token_len) + { + if(isspace(token[i])) + { + token[i] = '\0'; + } + i++; + } + } if(strcmp(token, opcodes_strings[i]) == 0) { inst.instruction_code = i; @@ -58,8 +103,46 @@ void parse_line(FILE** input_file) break; case 2: // current token is second parameter - uint16_t token_int = atoi(token); - inst.params[1] = token_int; + if(token[0] == '$') + { + int i = 0; + int token_len = strlen(token); + while(i < token_len) + { + if(isspace(token[i])) + { + token[i] = '\0'; + } + i++; + } + + int j = 0; + bool label_known = false; + while(j < labels_index) + { + if(strcmp(labels[j].label_name, token) == 0) + { + inst.params[1] = (uint8_t)(labels[j].addr >> 8); + inst.params[2] = (uint8_t)(labels[j].addr); + label_known = true; + break; + } + j++; + } + if(!label_known) + { + perror("Unknown identifier\n"); + exit(1); + } + break; + } + else + { + uint16_t token_int = atoi(token); + inst.params[1] = (uint8_t)(token_int >> 8); + inst.params[2] = (uint8_t)(token_int); + break; + } break; case 3: // current token is third parameter @@ -68,10 +151,22 @@ void parse_line(FILE** input_file) token_count++; token = strtok(NULL, " "); } + current_addr = current_addr + 4; + return inst; +} + +void write_instruction(FILE** output_file, struct inst_t inst) +{ + if(inst.contains_instruction) + { + fwrite(&inst.instruction_code, sizeof(uint8_t), 4, *output_file); + } } int main(int argc, char *argv[]) { + unsigned int labels_len = 10; + struct label_t* labels = malloc(labels_len * sizeof(struct label_t)); if(argc <= 2 || argc >= 4) { @@ -86,14 +181,18 @@ int main(int argc, char *argv[]) return 1; } - FILE* output_file = fopen(argv[2], "w"); + FILE* output_file = fopen(argv[2], "wb"); if(!output_file) { perror("Cannot open output file for writing\n"); return 1; } - while(!feof(input_file)) + + unsigned int line_num = 0; + char line_buffer[256]; + while(fgets(line_buffer, 256, input_file)) { - parse_line(&input_file); + line_num++; + write_instruction(&output_file, parse_line(line_buffer, labels, &labels_len)); } } -- 2.25.1