Improve assembler
authorbylex <mbilek06@gmail.com>
Thu, 3 Oct 2024 14:10:23 +0000 (16:10 +0200)
committerbylex <mbilek06@gmail.com>
Thu, 3 Oct 2024 14:10:23 +0000 (16:10 +0200)
fix errors and add label support

assembler.c

index 09bc341e86b321a00948f875fd4426286b38fbe3..54394fc5d357d013a3a8c5155fccfa260d4276c9 100644 (file)
@@ -1,3 +1,4 @@
+#include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdbool.h>
@@ -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));
        }
 }