The document describes a MIPS assembler program that takes assembly code as input and generates a 1KB binary executable file consisting of a 512B data segment and 512B text segment. The assembler handles a subset of MIPS instructions and directives to assemble and link the program, filling the segments with machine code and data in a big-endian format. It provides sample assembly code and describes the output file generated by the assembler.
Im having difficulty with the directives i figured out a duplicatio.pdf
1. 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[] = {
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;
}
// 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;
7. }
// 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
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