From 4863db36ee24fb488136daedcfd16ca7466ada30 Mon Sep 17 00:00:00 2001 From: "(Tim) Efthimis Kritikos" Date: Mon, 12 Feb 2024 17:51:16 +0000 Subject: [PATCH] ASM: Added support for labels in the assembler --- assembly.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++----- assembly.h | 10 ++++-- main.c | 35 +++++++++++++++++++-- test.asm | 11 ++++--- 4 files changed, 131 insertions(+), 17 deletions(-) diff --git a/assembly.c b/assembly.c index 0d45011..3025468 100644 --- a/assembly.c +++ b/assembly.c @@ -3,6 +3,8 @@ #include #include +#define MAX_LABEL_SIZE 30 +#define MAX_LABEL_SIZE_str "30" // Max instruction width is 25 characters without the null char // @@ -208,8 +210,36 @@ char *disassemble(uint32_t opcode_be){ return ret; } +int32_t parse_immediate(char* str,struct assembler_context_t *assembler_context){ + if(*str=='0'){ + uint32_t addr; + if(sscanf(str,"%06X",&addr)!=1) + return -1; + else + return addr&0x00FFFFFF; + }else{ + // Get name size + int len=0; + for(int i=0;ilabel_ll; + while(search){ + if(strncmp(str,search->name,len)==0) + return search->address; + search=search->next; + } + return -2; + } +} + +uint32_t assemble_line(char *line, struct assembler_context_t *assembler_context){ uint16_t opcode; int x; int call; @@ -246,13 +276,18 @@ uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_cont }else return 0xFFFFFFFF; while(line[x]==' ')x++; - uint32_t addr; if(line[x]=='$'){ x++; - if(sscanf(line+x,"%06X",&addr)!=1) - return 0xFFFFFFFF; - else - return opcode<<24|(addr&0x00FFFFFF); + int32_t imm=parse_immediate(line+x,assembler_context); + if(imm<0){ + switch(imm){ + default: + return 0xFFFFFFFF; + case -2: + return 0xFFFFFFFE; + } + }else + return opcode<<24|(imm&0x00FFFFFF); }else return 0xFFFFFFFF; }else{ @@ -372,11 +407,54 @@ uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_cont return 0xFFFFFFFF; }else if(strncmp(line,"RET",3)==0){ return 0x10000000; - } + }else if(*line==':') + return 0xFFFFFFF0; return 0xFFFFFFFF; } } +int assembler_context_process(char* line,struct assembler_context_t *assembler_context){ + switch(line[0]){ + case ':': + if(line[1]==0) + return 1; + else{ + char* label=malloc(MAX_LABEL_SIZE+1); + sscanf(line+1,"%"MAX_LABEL_SIZE_str"s",label); + struct label_ll_t **current; + current=&(assembler_context->label_ll); + while(*current) + current=&((*current)->next); + *current=malloc(sizeof(struct label_ll_t)); + (*current)->name=label; + (*current)->address=assembler_context->current_location; + (*current)->next=NULL; + } + break; + case 0: + return 0; + default: + assembler_context->current_location+=4; + + } + return 0; +} + +struct assembler_context_t *malloc_assembler_context(){ + struct assembler_context_t *ret; + ret=malloc(sizeof(struct assembler_context_t)); + ret->current_location=0x00000000; + ret->label_ll=NULL; + return ret; +} + void free_assembler_context(struct assembler_context_t *tofree){ + struct label_ll_t *tofree_ll=tofree->label_ll; + while(tofree_ll){ + struct label_ll_t *temp=tofree_ll; + tofree_ll=tofree_ll->next; + free(temp->name); + free(temp); + } free(tofree); } diff --git a/assembly.h b/assembly.h index ff02910..52b61cf 100644 --- a/assembly.h +++ b/assembly.h @@ -9,8 +9,12 @@ struct label_ll_t{ }; struct assembler_context_t{ - struct label_ll_t label_ll; + struct label_ll_t *label_ll; + uint32_t current_location; }; -uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_context_t *assembler_context); -void free_assembler_context(struct assembler_context_t *tofree); +uint32_t assemble_line(char *line, struct assembler_context_t *assembler_context); +int assembler_context_process(char* line,struct assembler_context_t *tofree); + +struct assembler_context_t *malloc_assembler_context(); +void free_assembler_context(struct assembler_context_t *assembler_context); diff --git a/main.c b/main.c index f41e76d..25534b7 100644 --- a/main.c +++ b/main.c @@ -85,7 +85,7 @@ int main(int argc, char* argd[] ){ if ( assemble != NULL ){ /* RUN ASSEMBLER */ - struct assembler_context_t *assembler_context=malloc(sizeof(struct assembler_context_t)); + struct assembler_context_t *assembler_context=malloc_assembler_context(); for (int i=0;iRAM[i]=0; @@ -94,6 +94,30 @@ int main(int argc, char* argd[] ){ char line [1000]; uint32_t opcode; uint32_t addr=0; + + //--------------- Build assembler context -------------------- + while(fgets(line,sizeof(line),rom)!= NULL){ + + for(int i=0;line[i];i++) + if(line[i]==0x0a) + line[i]=0; + + switch(assembler_context_process(line,assembler_context)){ + case 0: break; + default: + printf("Error in getting assembler context at %s:%d\n", infile,linec+1); + fclose(rom); + free_assembler_context(assembler_context); + free_simdata(simdata); + return 1; + } + linec++; + } + + fseek(rom, 0, SEEK_SET); + linec=0; + + //---------------------- Assembler --------------------------- while(fgets(line,sizeof(line),rom)!= NULL){ for(int i=0;line[i];i++) @@ -102,12 +126,17 @@ int main(int argc, char* argd[] ){ opcode=assemble_line(line,assembler_context); - if(opcode>0xFFFFFFF1){ - printf("Error assembling %s:%d\n", infile,linec+1); + if(opcode>=0xFFFFFFF1){ + if(opcode==0xFFFFFFFE) + printf("Error label not found %s:%d\n", infile,linec+1); + else + printf("Error assembling %s:%d\n", infile,linec+1); fclose(rom); free_assembler_context(assembler_context); free_simdata(simdata); return 1; + }else if(opcode==0xFFFFFFF0){ + ;/*it was empty, comment or label*/ }else{ simdata->RAM[addr]=(0xFF000000&opcode)>>24; addr++; diff --git a/test.asm b/test.asm index 0154e2a..db53da7 100644 --- a/test.asm +++ b/test.asm @@ -3,9 +3,12 @@ MOV $0x0001,%R0l MOV $0x0000,%R0h MOV $0x0000,%R1l MOV $0x0000,%R1h -CALL $0x0024 -CALL $0x0024 -CALL $0x0024 -HALT +CALL $SUBROUTINE +CALL $SUBROUTINE +CALL $SUBROUTINE +JMP $END +:SUBROUTINE ADD %R0,%R1 RET +:END +HALT