ASM: Added support for labels in the assembler

This commit is contained in:
(Tim) Efthimis Kritikos 2024-02-12 17:51:16 +00:00
parent 41fed482fe
commit 4863db36ee
4 changed files with 131 additions and 17 deletions

View File

@ -3,6 +3,8 @@
#include <stdlib.h>
#include <stdio.h>
#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;i<MAX_LABEL_SIZE+1;i++){
if(i==MAX_LABEL_SIZE)
return -2;
if(str[i]==0||str[i]=='\n'||str[i]==' '){
break;
}else
len++;
}
uint32_t assemble_line(char *line, __attribute__((unused)) struct assembler_context_t *assembler_context){
struct label_ll_t *search=assembler_context->label_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)
int32_t imm=parse_immediate(line+x,assembler_context);
if(imm<0){
switch(imm){
default:
return 0xFFFFFFFF;
else
return opcode<<24|(addr&0x00FFFFFF);
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);
}

View File

@ -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);

33
main.c
View File

@ -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;i<ADDR_SIZE;i++)
simdata->RAM[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){
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++;

View File

@ -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