I'm having difficulty with the directives i figured out a duplication issue but i still can't get it to
work as intended. It's supposed to be a mips compiler that handles a subset of mips instruction
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this
license
* Click nbfs://nbhost/SystemFileSystem/Templates/cFiles/main.c to edit this template
*/
/*
* File: main.c
* Author: Andrew Schelb
*
* Created on March 7, 2023, 2:51 PM
*/
#include
#include
#define TEXT_SEGMENT 0x0200
#define DATA_SEGMENT 0x0000
#define MAX_SIZE 1024
typedef struct {
char* name;
int opcode;
int funct;
int rs;
int rt;
int rd;
int imm;
int add;
} Instruction;
typedef struct {
int n;
int size;
char* name;
} Directive;
// MIPS Instructions
Instruction instructions[] = {
{"add", 0, 32, 0, 0, 0, 0, 0},
{"addu", 0, 33, 0, 0, 0, 0, 0},
{"sub", 0, 34, 0, 0, 0, 0, 0},
{"sll", 0, 0, 0, 0, 0, 0, 0},
{"slt", 0, 42, 0, 0, 0, 0, 0},
{"addi", 8, 0, 0, 0, 0, 0, 0},
{"lui", 15, 0, 0, 0, 0, 0, 0},
{"ori", 13, 0, 0, 0, 0, 0, 0},
{"lw", 35, 0, 0, 0, 0, 0, 0},
{"sw", 43, 0, 0, 0, 0, 0, 0},
{NULL, 0, 0, 0, 0, 0, 0, 0}
};
// MIPS Directives
Directive directives[] = {
{0, 0, ".text"},
{1, 0, ".data"},
{2, 1, ".dbyte"},
{3, 4, ".integer"},
{-1, 0, NULL}
};
// Function Prototypes
Instruction* getInstruction(char*);
Directive* getDirective(char*);
int getRegisterNumber(char*);
int parseInstruction(char*, int*, int*);
int parseDirective(char*, int*, int*);
void assemble(char*, int*);
int main(int argc, char** argv) {
// Checking command line arguments
if (argc < 2) {
printf("Usage: %s n", argv[0]);
return -1;
}
// Initializing memory
int text_segment[MAX_SIZE];
int data_segment[MAX_SIZE];
memset(text_segment, 0, MAX_SIZE);
memset(data_segment, 0, MAX_SIZE);
// Assembling
assemble(argv[1], text_segment);
// Writing to output file
FILE* fp = fopen(argv[2], "wb");
fwrite(data_segment, 1, MAX_SIZE, fp);
fwrite(text_segment, 1, MAX_SIZE, fp);
fclose(fp);
return 0;
}
// Assembling the input file
void assemble(char* filename, int* text_segment) {
int line_number = 0;
int text_offset = 0;
int data_offset = 0;
char line[256];
FILE* fp = fopen(filename, "r");
while (fgets(line, 256, fp)) {
// Handling blank lines
if (strcmp(line, "n") == 0) {
continue;
}
// Parsing line
char* label = NULL;
char* instruction = NULL;
char* directive = NULL;
char* operands = NULL;
label = strtok(line, ":");
instruction = strtok(NULL, " nt");
directive = strtok(NULL, " nt");
operands = strtok(NULL, "nt");
// Handling instructions
if (instruction) {
// Parsing instruction
int opcode = 0;
int funct = 0;
int rs = 0;
int rt = 0;
int rd = 0;
int imm = 0;
int add = 0;
if (parseInstruction(instruction, &opcode, &funct)) {
rs = getRegisterNumber(strtok(operands, ","));
rt = getRegisterNumber(strtok(NULL, ","));
if (opcode == 0) {
rd = getRegisterNumber(strtok(NULL, ","));
} else {
imm = atoi(strtok(NULL, ","));
}
// Generating machine code
int machine_code = 0;
machine_code |= (opcode << 26);
machine_code |= (rs << 21);
machine_code |= (rt << 16);
machine_code |= (rd << 11);
machine_code |= (imm << 0);
machine_code |= (add << 0);
machine_code |= (funct << 0);
// Writing machine code to text segment
text_segment[text_offset] = machine_code;
text_offset += 1;
}
}
// Handling directives
if (directive) {
// Parsing directive
int type = 0;
int size = 0;
if (parseDirective(directive, &type, &size)) {
char* token = strtok(operands, ",");
while (token) {
int value = 0;
sscanf(token, "%d", &value);
// Handling .dbyte
if (type == 2) {
data_segment[data_offset] = value;
data_offset += 1;
}
// Handling .integer
if (type == 3) {
int* int_ptr = (int*)&data_segment[data_offset];
*int_ptr = value;
data_offset += size;
}
token = strtok(NULL, ",");
}
}
}
} // End of while loop
fclose(fp);
}
// Freeing memory
free(line);
// Handling missing .text directive
if (text_offset == 0) {
printf("Error: No .text directive found.n");
exit(-1);
}
// Parsing instruction and returning opcode and funct
int parseInstruction(char* instruction, int* opcode, int* funct) {
Instruction* current = instructions;
while (current->name != NULL) {
if (strcmp(current->name, instruction) == 0) {
*opcode = current->opcode;
*funct = current->funct;
return 1;
}
current++;
}
return 0;
}
// Parsing directive and returning type and size
int parseDirective(char* directive, int* type, int* size) {
Directive* current = directives;
while (current->name != NULL) {
if (strcmp(current->name, directive) == 0) {
*type = current->n;
*size = current->size;
return 1;
}
current++;
}
return 0;
}
// Getting register number
int getRegisterNumber(char* reg) {
if (reg[0] == '$') {
if (reg[1] == 's' && reg[2] >= '0' && reg[2] <= '7') {
return reg[2] - '0' + 16;
} else if (reg[1] == 't' && reg[2] >= '0' && reg[2] <= '9') {
return reg[2] - '0' + 8;
} else if (strcmp(reg, "$zero") == 0) {
return 0;
} else if (strcmp(reg, "$sp") == 0) {
return 29;
} else if (strcmp(reg, "$fp") == 0) {
return 30;
} else if (strcmp(reg, "$ra") == 0) {
return 31;
}
}
return -1;
}
// Getting instruction from name
Instruction* getInstruction(char* name) {
Instruction* current = instructions;
while (current->name != NULL) {
if (strcmp(current->name, name) == 0) {
return current;
}
current++;
}
return NULL;
}
// Getting directive from name
Directive* getDirective(char* name) {
Directive* current = directives;
while (current->name != NULL) {
if (strcmp(current->name, name) == 0) {
return current;
}
current++;
}
return NULL;
}
The assembler generates an output file of size 1KB consisting of 512B of data segment (begins at
0x0000) and 512B of text segment (begins at 0x0200). Since each data and instruction is 4B
long, there will be at maximum 128 word data and at maximum 128 instruction words. This file
can be considered a binary executable file. Do not try to open this file as it causes an error.
The assembler does not detect syntax errors and assumes the assembly input is correctly formed.
This example assumes big-endian.
For a sample assembly input file (test.asm):
.data .integer 120
.dbyte 8 .
integer 121
.text
addi $1,$0,10
lw $2,123($4)
sw $3,4($1)
add $10,$0,$0
sub $11,$0,$0
sll $4,$4,10
lui $5,123
slt $10,$0,$0
ori $11,$0,10
addu $6,$10,$13

Im having difficulty with the directives i figured out a duplicatio.pdf

  • 1.
    I'm having difficultywith the directives i figured out a duplication issue but i still can't get it to work as intended. It's supposed to be a mips compiler that handles a subset of mips instruction /* * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license * Click nbfs://nbhost/SystemFileSystem/Templates/cFiles/main.c to edit this template */ /* * File: main.c * Author: Andrew Schelb * * Created on March 7, 2023, 2:51 PM */ #include #include #define TEXT_SEGMENT 0x0200 #define DATA_SEGMENT 0x0000 #define MAX_SIZE 1024 typedef struct { char* name; int opcode; int funct; int rs; int rt; int rd; int imm; int add; } Instruction; typedef struct { int n; int size; char* name; } Directive; // MIPS Instructions Instruction instructions[] = {
  • 2.
    {"add", 0, 32,0, 0, 0, 0, 0}, {"addu", 0, 33, 0, 0, 0, 0, 0}, {"sub", 0, 34, 0, 0, 0, 0, 0}, {"sll", 0, 0, 0, 0, 0, 0, 0}, {"slt", 0, 42, 0, 0, 0, 0, 0}, {"addi", 8, 0, 0, 0, 0, 0, 0}, {"lui", 15, 0, 0, 0, 0, 0, 0}, {"ori", 13, 0, 0, 0, 0, 0, 0}, {"lw", 35, 0, 0, 0, 0, 0, 0}, {"sw", 43, 0, 0, 0, 0, 0, 0}, {NULL, 0, 0, 0, 0, 0, 0, 0} }; // MIPS Directives Directive directives[] = { {0, 0, ".text"}, {1, 0, ".data"}, {2, 1, ".dbyte"}, {3, 4, ".integer"}, {-1, 0, NULL} }; // Function Prototypes Instruction* getInstruction(char*); Directive* getDirective(char*); int getRegisterNumber(char*); int parseInstruction(char*, int*, int*); int parseDirective(char*, int*, int*); void assemble(char*, int*); int main(int argc, char** argv) { // Checking command line arguments if (argc < 2) { printf("Usage: %s n", argv[0]); return -1; } // Initializing memory int text_segment[MAX_SIZE]; int data_segment[MAX_SIZE];
  • 3.
    memset(text_segment, 0, MAX_SIZE); memset(data_segment,0, MAX_SIZE); // Assembling assemble(argv[1], text_segment); // Writing to output file FILE* fp = fopen(argv[2], "wb"); fwrite(data_segment, 1, MAX_SIZE, fp); fwrite(text_segment, 1, MAX_SIZE, fp); fclose(fp); return 0; } // Assembling the input file void assemble(char* filename, int* text_segment) { int line_number = 0; int text_offset = 0; int data_offset = 0; char line[256]; FILE* fp = fopen(filename, "r"); while (fgets(line, 256, fp)) { // Handling blank lines if (strcmp(line, "n") == 0) { continue; } // Parsing line char* label = NULL; char* instruction = NULL; char* directive = NULL; char* operands = NULL; label = strtok(line, ":"); instruction = strtok(NULL, " nt"); directive = strtok(NULL, " nt"); operands = strtok(NULL, "nt"); // Handling instructions if (instruction) { // Parsing instruction int opcode = 0;
  • 4.
    int funct =0; int rs = 0; int rt = 0; int rd = 0; int imm = 0; int add = 0; if (parseInstruction(instruction, &opcode, &funct)) { rs = getRegisterNumber(strtok(operands, ",")); rt = getRegisterNumber(strtok(NULL, ",")); if (opcode == 0) { rd = getRegisterNumber(strtok(NULL, ",")); } else { imm = atoi(strtok(NULL, ",")); } // Generating machine code int machine_code = 0; machine_code |= (opcode << 26); machine_code |= (rs << 21); machine_code |= (rt << 16); machine_code |= (rd << 11); machine_code |= (imm << 0); machine_code |= (add << 0); machine_code |= (funct << 0); // Writing machine code to text segment text_segment[text_offset] = machine_code; text_offset += 1; } } // Handling directives if (directive) { // Parsing directive int type = 0; int size = 0; if (parseDirective(directive, &type, &size)) { char* token = strtok(operands, ","); while (token) {
  • 5.
    int value =0; sscanf(token, "%d", &value); // Handling .dbyte if (type == 2) { data_segment[data_offset] = value; data_offset += 1; } // Handling .integer if (type == 3) { int* int_ptr = (int*)&data_segment[data_offset]; *int_ptr = value; data_offset += size; } token = strtok(NULL, ","); } } } } // End of while loop fclose(fp); } // Freeing memory free(line); // Handling missing .text directive if (text_offset == 0) { printf("Error: No .text directive found.n"); exit(-1); } // Parsing instruction and returning opcode and funct int parseInstruction(char* instruction, int* opcode, int* funct) { Instruction* current = instructions; while (current->name != NULL) { if (strcmp(current->name, instruction) == 0) { *opcode = current->opcode; *funct = current->funct; return 1;
  • 6.
    } current++; } return 0; } // Parsingdirective and returning type and size int parseDirective(char* directive, int* type, int* size) { Directive* current = directives; while (current->name != NULL) { if (strcmp(current->name, directive) == 0) { *type = current->n; *size = current->size; return 1; } current++; } return 0; } // Getting register number int getRegisterNumber(char* reg) { if (reg[0] == '$') { if (reg[1] == 's' && reg[2] >= '0' && reg[2] <= '7') { return reg[2] - '0' + 16; } else if (reg[1] == 't' && reg[2] >= '0' && reg[2] <= '9') { return reg[2] - '0' + 8; } else if (strcmp(reg, "$zero") == 0) { return 0; } else if (strcmp(reg, "$sp") == 0) { return 29; } else if (strcmp(reg, "$fp") == 0) { return 30; } else if (strcmp(reg, "$ra") == 0) { return 31; } } return -1;
  • 7.
    } // Getting instructionfrom name Instruction* getInstruction(char* name) { Instruction* current = instructions; while (current->name != NULL) { if (strcmp(current->name, name) == 0) { return current; } current++; } return NULL; } // Getting directive from name Directive* getDirective(char* name) { Directive* current = directives; while (current->name != NULL) { if (strcmp(current->name, name) == 0) { return current; } current++; } return NULL; } The assembler generates an output file of size 1KB consisting of 512B of data segment (begins at 0x0000) and 512B of text segment (begins at 0x0200). Since each data and instruction is 4B long, there will be at maximum 128 word data and at maximum 128 instruction words. This file can be considered a binary executable file. Do not try to open this file as it causes an error. The assembler does not detect syntax errors and assumes the assembly input is correctly formed. This example assumes big-endian. For a sample assembly input file (test.asm): .data .integer 120 .dbyte 8 . integer 121 .text addi $1,$0,10
  • 8.
    lw $2,123($4) sw $3,4($1) add$10,$0,$0 sub $11,$0,$0 sll $4,$4,10 lui $5,123 slt $10,$0,$0 ori $11,$0,10 addu $6,$10,$13