diff --git a/src/Fibonacci.asm b/src/Fibonacci.asm new file mode 100644 index 0000000..8aa98fd --- /dev/null +++ b/src/Fibonacci.asm @@ -0,0 +1,40 @@ +.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 diff --git a/src/a.out b/src/a.out new file mode 100755 index 0000000..898b178 Binary files /dev/null and b/src/a.out differ diff --git a/src/main.c b/src/main.c index 7b23b8f..c2e29ec 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,8 @@ #include #include +#include "util/parse.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" @@ -10,21 +12,82 @@ int help() { " mipsToHex --help\n" " mipsToHex [ file ]\n" " mipsToHex --asm [ asmFile ]\n" + " mipsToHex -a [ asmFile ]\n" " mipsToHex --asm [ asmFile ] --hex [ hexFile ]\n" + " mipsToHex -a [ asmFile ] -x [ hexFile ]\n" ); return 0; } -int error() { - printf("There must be at least one argument."); +int error(char * msg) { + printf("\n%s\n", msg); help(); return 1; } +int printHex(struct instruction* current) { + while(current->nextInstruction != NULL) { + printf("0x%s ", convert(current)); + + current = current->nextInstruction; + } + + free(current); + return 1; +} + +int writeHex(struct instruction * current) { + while(current->nextInstruction != NULL) { + printf("0x%s ", convert(current)); + + current = current->nextInstruction; + } + + return 1; // TODO: Need to write the output to the file. +} + int main(int argc, char* args[]) { - if(argc < 2) return error(); + if(argc < 2) return error("There must be at least one argument."); if(strcmp(args[1], "-h") == 0 || strcmp(args[1], "--help") == 0) return help(); - return 0; + char * file; + //FILE * outputFile; + + // If the only argument is the input file, then set the FILE pointer. + if(argc == 2) { + printf("only 1 true arg, %s", args[1]); + file = args[1]; + } + + struct instruction * head = initParse(file); + + return printHex(head); + //if(outputFile != NULL) return writeHex(head, outputFile); + //else return printHex(head); } + + + /** + // If there are 5 arguments total, then we should have the flag for the hex output file in position 4. + } else if(argc == 5) { + printf("4 true args, %s, %s", args[3], args[4]); + if(strcmp(args[3], "-x") == 0 || strcmp(args[3], "--hex") == 0) + outputFile= fopen(args[4], "w"); + else return error("invalid argument format."); + + // Catch if the file does not exist/cannot be opened. + if(outputFile == NULL) return error("output file cannot be created or written. check permissions."); + } + + // If there are at least 3 arguments, then we should have the flag for the assembly input file in position 1. + if(argc >= 3) { + printf("at least 2 true args, %s, %s", args[1], args[2]); + if(strcmp(args[1], "--asm") == 0 || strcmp(args[1], "-a") == 0) { + file = fopen(args[2], "r"); + outputFile = NULL; + } else return error("invalid argument format."); + } + */ + + // Catch if the file does not exist/cannot be opened. diff --git a/src/output.hex b/src/output.hex new file mode 100644 index 0000000..e69de29 diff --git a/src/test/Fibonacci.asm b/src/test/Fibonacci.asm deleted file mode 100644 index e1358cb..0000000 --- a/src/test/Fibonacci.asm +++ /dev/null @@ -1,2 +0,0 @@ - add $t3, $t1, $t2 # Sum the previous and current values and save in register t3 - addi $t0, $t0, 1 # Increment counter diff --git a/src/test/a.out b/src/test/a.out deleted file mode 100755 index 2d27402..0000000 Binary files a/src/test/a.out and /dev/null differ diff --git a/src/test/output.hex b/src/test/output.hex new file mode 100644 index 0000000..31f2efd --- /dev/null +++ b/src/test/output.hex @@ -0,0 +1 @@ +0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00400008 0x00801020 0x00000024 0x00000020 0x00000020 0x00000020 0x00400008 0x00000024 0x00000020 0x00000024 0x00000020 0x00400008 0x00801020 0x00000024 0x00400008 0x00000024 0x00000020 0x0000F821 0x0000F820 0x0000F820 0x01000008 0x01200008 0x01400008 0x01600008 0x00005820 0x00005820 0x012A5820 0x012A5820 0x012A5820 0x21080001 0x01014020 0x01014020 0x01014020 0x0000F821 diff --git a/src/test/output.txt b/src/test/output.txt deleted file mode 100644 index d403e92..0000000 --- a/src/test/output.txt +++ /dev/null @@ -1,55 +0,0 @@ -Compiling... -Output... -.dataU -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: "u -f -.textT -. -main:T -li v0 4r -la a0 welcomeMessageT -syscalle -s -jal getInpute -j -jal fibonacciM -move a0 v0c -li v0 1 -syscall -s -ori v0 0 10c -syscall0 -s -getInput:1 -li v0 4t -la a0 prompti -syscallr -s -li v0 5r -syscallr -move a0 v0p -m -jr raa -j -fibonacci:p -move s1 a0p -li t0 2 -li t1 0 -li t2 1 -li t3 0 -l -while:0 -bge t0 s1 donee -add t3 t1 t2n -move t1 t2t -m -move t2 t3t -addi t0 t0 1n -a -b while -b -done:l -move v0 t2 -jr rav diff --git a/src/test/testFormats.c b/src/test/testFormats.c index 09fec03..a37d01f 100644 --- a/src/test/testFormats.c +++ b/src/test/testFormats.c @@ -22,7 +22,6 @@ int test_toBinary_0_size5() { int expectedOutput[] = { 0, 0, 0, 0, 0 }; int cmp = compareIntArray(binary, expectedOutput, size); - free(binary); return cmp; } @@ -33,7 +32,6 @@ int test_toBinary_0_size6() { int expectedOutput[] = { 0, 0, 0, 0, 0, 0 }; int cmp = compareIntArray(binary, expectedOutput, size); - free(binary); return cmp; } @@ -44,7 +42,6 @@ int test_toBinary_10_size6() { int expectedOutput[] = { 0, 0, 1, 0, 1, 0 }; int cmp = compareIntArray(binary, expectedOutput, size); - free(binary); return cmp; } @@ -55,7 +52,6 @@ int test_toBinary_20_size6() { int expectedOutput[] = { 0, 1, 0, 1, 0, 0 }; int cmp = compareIntArray(binary, expectedOutput, size); - free(binary); return cmp; } @@ -66,7 +62,6 @@ int test_toBinary_17_size16() { int expectedOutput[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1}; int cmp = compareIntArray(binary, expectedOutput, size); - free(binary); return cmp; } @@ -83,7 +78,6 @@ int test_rToBinary_sll() { int expectedOutput[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; int cmp = compareIntArray(binary, expectedOutput, 32); - free(binary); return cmp; } @@ -101,7 +95,6 @@ int test_rToBinary_add() { int expectedOutput[] = { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }; int cmp = compareIntArray(binary, expectedOutput, 32); - free(binary); return cmp; } @@ -118,7 +111,6 @@ int test_rToHex_add() { char * hex = rToHex(rFormat); char * expectedHex = "02326820"; int cmp = strcmp(hex, expectedHex); - free(hex); if(cmp < 0 || cmp > 0) return 0; else return 1; @@ -136,7 +128,6 @@ int test_rToHex_sll() { char * hex = rToHex(rFormat); char * expectedHex = "00107080"; int cmp = strcmp(hex, expectedHex); - free(hex); if(cmp < 0 || cmp > 0) return 0; else return 1; diff --git a/src/test/testParse.c b/src/test/testParse.c index b9d5036..339691b 100644 --- a/src/test/testParse.c +++ b/src/test/testParse.c @@ -4,18 +4,9 @@ #include "../util/parse.c" -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)); + printf("0x%s ", convert(current)); current = current->nextInstruction; } @@ -23,16 +14,10 @@ int traverse(struct instruction* current) { return 1; // TODO } -int test_readFile() { - struct instruction * head = initParse(filepath); - traverse(head); - return 1; -} - int main() { // filepath may be a relative or an absolute filepath //filepath = "/home/jashton/dev/mipsToHex/src/test/Fibonacci.asm"; - filepath = "Fibonacci.asm"; + char * filepath = "Fibonacci.asm"; - return test_readFile(); + return traverse(initParse(filepath)); } diff --git a/src/util/formats.c b/src/util/formats.c index 3459ded..b6fef5f 100644 --- a/src/util/formats.c +++ b/src/util/formats.c @@ -109,27 +109,31 @@ int * rToBinary(r* format) { int * opcode = toBinary(format->opcode, 6); fillArray(bin, opcode, 0, size); - free(opcode); int * rs = toBinary(format->rs, 5); fillArray(bin, rs, 6, size); - free(rs); int * rt = toBinary(format->rt, 5); fillArray(bin, rt, 11, size); - free(rt); int * rd = toBinary(format->rd, 5); fillArray(bin, rd, 16, size); - free(rd); int * shamt = toBinary(format->shamt, 5); fillArray(bin, shamt, 21, size); - free(shamt); int * funct = toBinary(format->funct, 6); fillArray(bin, funct, 26, size); - free(funct); + + // Print the binary representation. + /** + for(int i = 0; i < 32; i++) { + printf("%d", bin[i]); + if(i % 4 == 3) printf(" "); + } + + printf("\n"); // Separate the bit string from the hex + */ return bin; } @@ -148,19 +152,26 @@ int * iToBinary(i* format) { int * opcode = toBinary(format->opcode, 6); fillArray(bin, opcode, 0, size); - free(opcode); int * rs = toBinary(format->rs, 5); fillArray(bin, rs, 6, size); - free(rs); int * rt = toBinary(format->rt, 5); fillArray(bin, rt, 11, size); - free(rt); int * immediate = toBinary(format->immediate, 16); fillArray(bin, immediate, 16, size); - free(immediate); + + // Print the binary representation + /** + printf("\n"); + for(int i = 0; i < 32; i++) { + printf("%d", bin[i]); + if(i % 4 == 3) printf(" "); + } + + printf("\n"); + */ return bin; } diff --git a/src/util/functionAssigner.h b/src/util/functionAssigner.h index ff2fcaf..cb1ec4c 100644 --- a/src/util/functionAssigner.h +++ b/src/util/functionAssigner.h @@ -1,5 +1,4 @@ #define FOREACH_FUNCTION(FUNCTION) \ - FUNCTION(addi) \ FUNCTION(add) \ FUNCTION(jr) \ FUNCTION(syscall) \ @@ -12,6 +11,7 @@ FUNCTION(sltu) \ FUNCTION(sll) \ FUNCTION(srl) \ + FUNCTION(addi) \ FUNCTION(sub) \ FUNCTION(subu) \ FUNCTION(jal) \ diff --git a/src/util/functions.c b/src/util/functions.c index 37db0d8..4b56a98 100644 --- a/src/util/functions.c +++ b/src/util/functions.c @@ -19,7 +19,6 @@ void initFunctions() { // -------------------------- R FORMAT INSTRUCTIONS -------------------------- // char * addFunc(int * args) { - r* rFormat = (r*)malloc(sizeof(r)); rFormat->rd = args[0]; rFormat->rs = args[1]; rFormat->rt = args[2]; @@ -201,9 +200,19 @@ char * beqFunction(int * args) { // -------------------------- J FORMAT INSTRUCTIONS -------------------------- // +int str2int(char * numStr) { + int intVal = 0; + + while(* numStr != '\0') { + intVal *= 10; + intVal += * numStr - '0'; //0x30 ascii value of charater 0 + numStr++; + } + return intVal; +} + // Helper function to get the number of arguments. int getArgCount(struct args * a) { - printf("getArgCount "); int count = 0; while(a != NULL) { @@ -216,8 +225,6 @@ int getArgCount(struct args * a) { // 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; @@ -237,21 +244,20 @@ int * getArgs(struct args * a) { // otherwise, we have found a constant. else { - array[index] = (int) a->arg[0]; - printf("%d", array[index]); + // TODO: This is broken. Currently only gets the first digit. + array[index] = str2int(a->arg); 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) { @@ -306,20 +312,20 @@ char * funcToCall(int i, struct args * remainingArgs) { default: hex = ""; } - + free(rFormat); + free(iFormat); return hex; } // Convert a linked list instruction into hexadecimal char * convert(struct instruction * i) { - printf("convert "); initFunctions(); + struct args * remainingArgs; 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++) { + for(int i = 0; i < 13; i++) { if(strcmp(a->arg, FUNCTION_STRING[i]) == 0) { call = i; remainingArgs = a->nextArg; diff --git a/src/util/instruction.h b/src/util/instruction.h index 23840ac..9c00bca 100644 --- a/src/util/instruction.h +++ b/src/util/instruction.h @@ -1,11 +1,11 @@ typedef struct args { char * arg; - struct args *nextArg; // Allows dynamically sized lists of arguments. For eg. syscall will just be 1 element, but add has 4 elements. + struct args * nextArg; // Allows dynamically sized lists of arguments. For eg. syscall will just be 1 element, but add has 4 elements. } args; typedef struct instruction { int formatType; // 0 = R, 1 = I, 2 = J struct instruction* nextInstruction; - struct args* a; // A linked list of each argument of the instruction. + struct args * a; // A linked list of each argument of the instruction. } instruction; diff --git a/src/util/parse.c b/src/util/parse.c index 155704c..1eb6051 100644 --- a/src/util/parse.c +++ b/src/util/parse.c @@ -6,8 +6,6 @@ #include "functions.c" -FILE * file; - // Determines if the parser should keep a space, based upon if the space is surrounded by two non-space characters. int determineKeepSpace(char prior, char after) { if(&prior != (char *) NULL && !isspace(prior)) @@ -19,6 +17,8 @@ int determineKeepSpace(char prior, char after) { // Cleans up the input string to prepare for parsing into command and arguments. char * removeCommentsAndWhiteSpace(char * line) { + if(line[0] == 10) return ""; + int len = strlen(line); char tmpLine[256]; int parsedIndex = 0; @@ -36,12 +36,11 @@ char * removeCommentsAndWhiteSpace(char * line) { } else if(isspace(line[i])) { // Check if we're within bounds of the array to check whitespace - if((i - 1 >= 0) && (i + 1 < len)) { + if((i - 1 >= 0) && (i + 1 < len)) if(determineKeepSpace(line[i - 1], line[i + 1]) == 1) { tmpLine[parsedIndex] = line[i]; parsedIndex++; } - } } } @@ -69,20 +68,16 @@ void parseIntoNotation(char * bareLine, args * a) { } } +// Accepts an already verified FILE pointer to parse. Creates a Linked List to contain each instruction, with a sub Linked List +// to contain each argument of each instruction. Formatted into a custom numeric notation. instruction* initParse(char * filepath) { - // Open and read a file. - file = fopen(filepath, "r"); + FILE * file = fopen(filepath, "r"); + if(file == NULL) return NULL; // Maximum number of characters in a line is 1024. - char lines[1024]; + char lines[256]; - // Catch if the file does not exist/cannot be opened. - if(file == NULL) { - printf("%s cannot be opened.\n", filepath); - return NULL; - } - - int numFunctions = 4; // TODO: Need to obtain dynamically. + int numFunctions = 16; // TODO: Need to obtain dynamically. struct instruction* head = (instruction*) malloc(sizeof(instruction)); struct instruction* current = head; @@ -98,6 +93,5 @@ instruction* initParse(char * filepath) { current = current->nextInstruction; } - fclose(file); return head; }