succesfully parsing and outputing into converter. two main bugs, the converter adds 1 to the end somehow, and for the addi instruction it's registering that there are multiple free() statements

This commit is contained in:
Josh Ashton
2023-10-13 16:00:22 -06:00
parent 233c1ba1d9
commit 160cf8d9a0
8 changed files with 241 additions and 162 deletions
-7
View File
@@ -2,9 +2,6 @@
#include <stdlib.h>
#include <string.h>
#include "util/registers.h"
#include "util/functions.c"
int help() {
printf(
"\nA CLI-based tool to convert MIPS assembly instructions in a .asm file into hexadecimal instructions in a .hex file.\n"
@@ -29,9 +26,5 @@ int main(int argc, char* args[]) {
if(argc < 2) return error();
if(strcmp(args[1], "-h") == 0 || strcmp(args[1], "--help") == 0) return help();
initFunctions();
for(int i = 0; i < 32; i++)
printf("%d: %s\n", i, REGISTER_STRING[i]);
return 0;
}
-51
View File
@@ -1,53 +1,2 @@
.data
welcomeMessage: .asciiz "Welcome to a MIPS assembly Fibonacci Sequence calculator!\nThis will calculate the nth term of the Fibonacci Sequence.\n"
prompt: .asciiz "Enter a number (n, input n > 2) to find the nth term:"
foundTerm: .asciiz "The nth term is: "
.text
main:
li $v0, 4 # syscall 4 is to print a string
la $a0, welcomeMessage # store the ascii string in register a0
syscall # print
jal getInput # get the user input
jal fibonacci # calculate the nth fibonacci term
move $a0, $v0 # move the returned term to register a0
li $v0, 1 # syscall 1 is to print an int
syscall # print
ori $v0, $0, 10 # system call code 10 for exit
syscall # exit the program
getInput:
li $v0, 4 # syscall 4 is to print a string
la $a0, prompt # store the ascii string in register a0
syscall # print
li $v0, 5 # syscall 5 is for reading an int
syscall # read an int from the user
move $a0, $v0 # load input into register a0
jr $ra # return to caller
fibonacci:
move $s1, $a0 # Copy the nth term
li $t0, 2 # Counter
li $t1, 0 # Prev value
li $t2, 1 # Current value
li $t3, 0 # Next value
while:
bge $t0, $s1, done # While the counter is less than n
add $t3, $t1, $t2 # Sum the previous and current values and save in register t3
move $t1, $t2 # Shift current value to previous value
move $t2, $t3 # Shift next value to current value
addi $t0, $t0, 1 # Increment counter
b while # Jump back to start of while loop
done:
move $v0, $t2 # Move current value to register v0
jr $ra # Return to caller
Executable
BIN
View File
Binary file not shown.
+19 -1
View File
@@ -6,8 +6,26 @@
char * filepath;
int traverse(struct instruction* current) {
while(current->nextInstruction != NULL) {
struct args* currentArgs = current->a;
while(currentArgs != NULL) {
printf("%s ", currentArgs->arg);
currentArgs = currentArgs->nextArg;
}
printf("\n");
printf("%s\n", convert(current));
current = current->nextInstruction;
}
return 1; // TODO
}
int test_readFile() {
initParse(filepath);
struct instruction * head = initParse(filepath);
traverse(head);
return 1;
}
+1 -1
View File
@@ -1,4 +1,5 @@
#define FOREACH_FUNCTION(FUNCTION) \
FUNCTION(addi) \
FUNCTION(add) \
FUNCTION(jr) \
FUNCTION(syscall) \
@@ -13,7 +14,6 @@
FUNCTION(srl) \
FUNCTION(sub) \
FUNCTION(subu) \
FUNCTION(addi) \
FUNCTION(jal) \
#define GENERATE_ENUM(ENUM) ENUM,
+196 -62
View File
@@ -2,6 +2,10 @@
#include <stdlib.h>
#include "formats.c"
#include "registers.h"
#include "functionAssigner.h"
#include "instruction.h"
r* rFormat;
i* iFormat;
@@ -14,10 +18,11 @@ void initFunctions() {
}
// -------------------------- R FORMAT INSTRUCTIONS -------------------------- //
char * add(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * addFunc(int * args) {
r* rFormat = (r*)malloc(sizeof(r));
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 32;
// Unused in add instruction.
@@ -26,10 +31,10 @@ char * add(int * args[]) {
return rToHex(rFormat);
}
char * addu(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * adduFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 33;
// Unused in addu instruction.
@@ -38,10 +43,10 @@ char * addu(int * args[]) {
return rToHex(rFormat);
}
char * and(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * andFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 36;
// Unused in and instruction.
@@ -50,8 +55,8 @@ char * and(int * args[]) {
return rToHex(rFormat);
}
char * jr(int * args[]) {
rFormat->rs = *args[0];
char * jrFunction(int * args) {
rFormat->rs = args[0];
rFormat->funct = 8;
// Unused in jr instruction.
@@ -62,10 +67,10 @@ char * jr(int * args[]) {
return rToHex(rFormat);
}
char * nor(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * norFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 39;
// Unused in nor instruction.
@@ -74,10 +79,10 @@ char * nor(int * args[]) {
return rToHex(rFormat);
}
char * or(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * orFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 37;
// Unused in or instruction.
@@ -85,10 +90,10 @@ char * or(int * args[]) {
return rToHex(rFormat);
}
char * slt(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * sltFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 42;
// Unused in slt instruction.
@@ -97,10 +102,10 @@ char * slt(int * args[]) {
return rToHex(rFormat);
}
char * sltu(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * sltuFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 43;
// Unused in sltu instruction.
@@ -109,10 +114,10 @@ char * sltu(int * args[]) {
return rToHex(rFormat);
}
char * sll(int * args[]) {
rFormat->rd = *args[0];
rFormat->rt = *args[1];
rFormat->shamt = *args[2];
char * sllFunction(int * args) {
rFormat->rd = args[0];
rFormat->rt = args[1];
rFormat->shamt = args[2];
rFormat->funct = 0;
// Unused in sll instruction.
@@ -121,10 +126,10 @@ char * sll(int * args[]) {
return rToHex(rFormat);
}
char * srl(int * args[]) {
rFormat->rd = *args[0];
rFormat->rt = *args[1];
rFormat->shamt = *args[2];
char * srlFunction(int * args) {
rFormat->rd = args[0];
rFormat->rt = args[1];
rFormat->shamt = args[2];
rFormat->funct = 2;
// Unused in sll instruction.
@@ -133,10 +138,10 @@ char * srl(int * args[]) {
return rToHex(rFormat);
}
char * sub(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * subFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 34;
// Unused in sll instruction.
@@ -145,10 +150,10 @@ char * sub(int * args[]) {
return rToHex(rFormat);
}
char * subu(int * args[]) {
rFormat->rd = *args[0];
rFormat->rs = *args[1];
rFormat->rt = *args[2];
char * subuFunction(int * args) {
rFormat->rd = args[0];
rFormat->rs = args[1];
rFormat->rt = args[2];
rFormat->funct = 35;
// Unused in sll instruction.
@@ -158,40 +163,169 @@ char * subu(int * args[]) {
}
// -------------------------- I FORMAT INSTRUCTIONS -------------------------- //
char * addi(int * args[]) {
char * addiFunction(int * args) {
iFormat->opcode = 8;
iFormat->rt = *args[0];
iFormat->rs = *args[1];
iFormat->immediate = *args[2];
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
char * addiu(int * args[]) {
char * addiuFunction(int * args) {
iFormat->opcode = 9;
iFormat->rt = *args[0];
iFormat->rs = *args[1];
iFormat->immediate = *args[2];
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
char * andi(int * args[]) {
char * andiFunction(int * args) {
iFormat->opcode = 12;
iFormat->rt = *args[0];
iFormat->rs = *args[1];
iFormat->immediate = *args[2];
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
char * beq(int * args[]) {
char * beqFunction(int * args) {
iFormat->opcode = 4;
iFormat->rt = *args[0];
iFormat->rs = *args[1];
iFormat->immediate = *args[2];
iFormat->rt = args[0];
iFormat->rs = args[1];
iFormat->immediate = args[2];
return iToHex(iFormat);
}
// -------------------------- J FORMAT INSTRUCTIONS -------------------------- //
// Helper function to get the number of arguments.
int getArgCount(struct args * a) {
printf("getArgCount ");
int count = 0;
while(a != NULL) {
count++;
a = a->nextArg;
}
return count;
}
// Converts a linked list of arguments into an int array of arguments.
int * getArgs(struct args * a) {
printf("getArgs ");
int * array = (int *) calloc(getArgCount(a), sizeof(int));
int index = 0;
int update = 0;
while(a != NULL) {
// check for valid register
for(int i = 0; i < 32; i++) {
if(strcmp(a->arg, REGISTER_STRING[i]) == 0) {
array[index] = i;
index++;
update = 1;
}
}
// if we found a register, reset the update value to detect a register in the next argument.
if(update == 1) update = 0;
// otherwise, we have found a constant.
else {
array[index] = (int) a->arg[0];
printf("%d", array[index]);
index++;
}
// move to the next argument.
a = a->nextArg;
}
return array;
}
// Helper function to determine what function to call given an input int
char * funcToCall(int i, struct args * remainingArgs) {
printf("funcToCall ");
int * args = getArgs(remainingArgs);
char * hex;
switch (i) {
case 0:
hex = addFunc(args);
break;
case 1:
hex = adduFunction(args);
break;
case 2:
hex = andFunction(args);
break;
case 3:
hex = jrFunction(args);
break;
case 4:
hex = norFunction(args);
break;
case 5:
hex = orFunction(args);
break;
case 6:
hex = sltFunction(args);
break;
case 7:
hex = sltuFunction(args);
break;
case 8:
hex = sllFunction(args);
break;
case 9:
hex = srlFunction(args);
break;
case 10:
hex = subFunction(args);
break;
case 11:
hex = subuFunction(args);
break;
case 12:
hex = addiFunction(args);
break;
case 13:
hex = addiuFunction(args);
break;
case 14:
hex = andiFunction(args);
break;
case 15:
hex = beqFunction(args);
break;
default:
hex = "";
}
return hex;
}
// Convert a linked list instruction into hexadecimal
char * convert(struct instruction * i) {
printf("convert ");
initFunctions();
struct args * a = i->a;
int call = 0;
struct args * remainingArgs;
// Go through each of the available functions and find a match for the first argument, and get the remaining args
for(int i = 0; i < 4; i++) {
if(strcmp(a->arg, FUNCTION_STRING[i]) == 0) {
call = i;
remainingArgs = a->nextArg;
break;
}
}
return funcToCall(call, remainingArgs);
}
+1 -1
View File
@@ -1,5 +1,5 @@
typedef struct args {
int arg;
char * arg;
struct args *nextArg; // Allows dynamically sized lists of arguments. For eg. syscall will just be 1 element, but add has 4 elements.
} args;
+24 -39
View File
@@ -4,9 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include "formats.c"
#include "registers.h"
#include "functionAssigner.h"
#include "functions.c"
FILE * file;
@@ -56,63 +54,50 @@ char * removeCommentsAndWhiteSpace(char * line) {
}
// Parse a line of assembly into numerical representations for the function (eg. add = 0), registers, offset, etc.
int * parseIntoNotation(char * bareLine) {
int numFunctions = 20; // TODO: Need to obtain dynamically.
//char * tokens = strtok(bareLine, " ");
void parseIntoNotation(char * bareLine, args * a) {
char * token = strtok(bareLine, " ");
args * current = a;
while (token != NULL) {
current->arg = token;
token = strtok(NULL, " ");
int cmd;
for(int i = 0; i < numFunctions; i++)
if(strcmp(token, FUNCTION_STRING[i]) == 0) cmd = i;
int * notation = (int *)calloc(4, sizeof(int));
int counter = 1;
while (token != NULL)
{
// Compare only the first token to all available functions.
if(counter == 0) {
if(token != NULL) {
current->nextArg = (args*) malloc(sizeof(args));
current = current->nextArg;
}
if(counter == 0) break;
// Compare subsequent tokens to available registers.
for(int i = 0; i < 32; i++) {
if(strcmp(token, REGISTER_STRING[i]) == 0) {
notation[counter] = i;
counter++;
continue;
}
}
printf("%s ", token);
token = strtok(NULL, " ");
}
return notation;
}
int initParse(char * filepath) {
instruction* initParse(char * filepath) {
// Open and read a file.
file = fopen(filepath, "r");
// Maximum number of characters in a line is 1024.
char lines[256];
char lines[1024];
// Catch if the file does not exist/cannot be opened.
if(file == NULL) {
printf("%s cannot be opened.\n", filepath);
return 0;
return NULL;
}
int numFunctions = 4; // TODO: Need to obtain dynamically.
struct instruction* head = (instruction*) malloc(sizeof(instruction));
struct instruction* current = head;
// Get each line of the file, remove comments and whitespace, and attempt to parse
while(fgets(lines, sizeof(lines), file)) {
struct args* argsHead = (args*) malloc(sizeof(args));
current->a = argsHead;
char * line = removeCommentsAndWhiteSpace(lines);
int * notation = parseIntoNotation(line);
parseIntoNotation(line, argsHead);
current->nextInstruction = (instruction*) malloc(sizeof(instruction));
current = current->nextInstruction;
}
fclose(file);
return 1;
return head;
}