add basic function, program can give a result
This commit is contained in:
parent
da2e75e912
commit
8968433f33
73
submit/lc4.c
73
submit/lc4.c
@ -7,49 +7,64 @@
|
||||
/************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "lc4_memory.h"
|
||||
#include "lc4_loader.h"
|
||||
#include "lc4_disassembler.h"
|
||||
|
||||
/* program to mimic pennsim loader and disassemble object files */
|
||||
|
||||
int main (int argc, char** argv) {
|
||||
|
||||
/* leave plenty of room for the filename */
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* leave plenty of room for the filename */
|
||||
|
||||
char filename[100];
|
||||
|
||||
/**
|
||||
* main() holds the linked list &
|
||||
* only calls functions in other files
|
||||
*/
|
||||
/**
|
||||
* main() holds the linked list &
|
||||
* only calls functions in other files
|
||||
*/
|
||||
|
||||
/* step 1: create head pointer to linked list: memory */
|
||||
/* do not change this line - there should no be malloc calls in main() */
|
||||
|
||||
row_of_memory* memory = NULL ;
|
||||
/* step 1: create head pointer to linked list: memory */
|
||||
/* do not change this line - there should no be malloc calls in main() */
|
||||
|
||||
row_of_memory *memory = NULL;
|
||||
|
||||
/* step 2: determine filename, then open it */
|
||||
/* TODO: extract filename from argv, pass it to open_file() */
|
||||
/* step 2: determine filename, then open it */
|
||||
/* TODO: extract filename from argv, pass it to open_file() */
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <object_file.obj>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
strcpy(filename, argv[1]);
|
||||
FILE *file = open_file(filename);
|
||||
if (file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* step 3: call function: parse_file() in lc4_loader.c */
|
||||
/* TODO: call function & check for errors */
|
||||
if (parse_file(file, &memory) != 0) {
|
||||
fclose(file);
|
||||
return -1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
/* step 3: call function: parse_file() in lc4_loader.c */
|
||||
/* TODO: call function & check for errors */
|
||||
/* step 4: call function: reverse_assemble() in lc4_disassembler.c */
|
||||
/* TODO: call function & check for errors */
|
||||
if (reverse_assemble(memory) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* step 5: call function: print_list() in lc4_memory.c */
|
||||
/* TODO: call function */
|
||||
print_list(memory);
|
||||
|
||||
/* step 4: call function: reverse_assemble() in lc4_disassembler.c */
|
||||
/* TODO: call function & check for errors */
|
||||
/* step 6: call function: delete_list() in lc4_memory.c */
|
||||
/* TODO: call function & check for errors */
|
||||
if (delete_list(&memory) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* step 5: call function: print_list() in lc4_memory.c */
|
||||
/* TODO: call function */
|
||||
|
||||
|
||||
/* step 6: call function: delete_list() in lc4_memory.c */
|
||||
/* TODO: call function & check for errors */
|
||||
|
||||
|
||||
/* only return 0 if everything works properly */
|
||||
return 0 ;
|
||||
/* only return 0 if everything works properly */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -7,12 +7,121 @@
|
||||
/************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "lc4_memory.h"
|
||||
|
||||
int reverse_assemble (row_of_memory* memory)
|
||||
{
|
||||
/* if you use binary constants, they should be proceeded by a 0b as in 0b011 for decimal 3 */
|
||||
/* without the 0b, constants with leading zeroes will be considered octal constants, not binary */
|
||||
/* hex constants starting with 0x can also be used */
|
||||
return 0 ;
|
||||
int reverse_assemble(row_of_memory *memory) {
|
||||
row_of_memory *current = memory;
|
||||
while (current != NULL) {
|
||||
if (current->assembly == NULL) {
|
||||
unsigned short instr = current->contents;
|
||||
unsigned short opcode = (instr >> 12) & 0xF;
|
||||
char *assembly = (char *)malloc(50);
|
||||
if (assembly == NULL) {
|
||||
return -1;
|
||||
}
|
||||
switch (opcode) {
|
||||
case 0x0: // NOP or BR
|
||||
if (instr == 0x0000) {
|
||||
sprintf(assembly, "NOP");
|
||||
} else {
|
||||
unsigned short n = (instr >> 11) & 0x1;
|
||||
unsigned short z = (instr >> 10) & 0x1;
|
||||
unsigned short p = (instr >> 9) & 0x1;
|
||||
short offset = instr & 0x1FF;
|
||||
if (offset & 0x100) {
|
||||
offset |= 0xFE00;
|
||||
}
|
||||
char condition[4] = "";
|
||||
if (n) strcat(condition, "n");
|
||||
if (z) strcat(condition, "z");
|
||||
if (p) strcat(condition, "p");
|
||||
if (condition[0] == '\0') {
|
||||
sprintf(assembly, "NOP");
|
||||
} else {
|
||||
sprintf(assembly, "BR%s #%d", condition, offset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x1: { // Arithmetic operations
|
||||
unsigned short sub_opcode = (instr >> 3) & 0x7;
|
||||
unsigned short Rd = (instr >> 9) & 0x7;
|
||||
unsigned short Rs = (instr >> 6) & 0x7;
|
||||
if (((instr >> 5) & 0x1) == 0) {
|
||||
unsigned short Rt = instr & 0x7;
|
||||
switch (sub_opcode) {
|
||||
case 0x0:
|
||||
sprintf(assembly, "ADD R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
case 0x1:
|
||||
sprintf(assembly, "MUL R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
case 0x2:
|
||||
sprintf(assembly, "SUB R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
case 0x3:
|
||||
sprintf(assembly, "DIV R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
default:
|
||||
sprintf(assembly, "INVALID");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
short imm5 = instr & 0x1F;
|
||||
if (imm5 & 0x10) {
|
||||
imm5 |= 0xFFE0;
|
||||
}
|
||||
sprintf(assembly, "ADD R%d, R%d, #%d", Rd, Rs, imm5);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x5: { // Logical operations
|
||||
unsigned short sub_opcode = (instr >> 3) & 0x7;
|
||||
unsigned short Rd = (instr >> 9) & 0x7;
|
||||
unsigned short Rs = (instr >> 6) & 0x7;
|
||||
if (((instr >> 5) & 0x1) == 0) {
|
||||
unsigned short Rt = instr & 0x7;
|
||||
switch (sub_opcode) {
|
||||
case 0x0:
|
||||
sprintf(assembly, "AND R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
case 0x1:
|
||||
sprintf(assembly, "NOT R%d, R%d", Rd, Rs);
|
||||
break;
|
||||
case 0x2:
|
||||
sprintf(assembly, "OR R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
case 0x3:
|
||||
sprintf(assembly, "XOR R%d, R%d, R%d", Rd, Rs, Rt);
|
||||
break;
|
||||
default:
|
||||
sprintf(assembly, "INVALID");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
short imm5 = instr & 0x1F;
|
||||
if (imm5 & 0x10) {
|
||||
imm5 |= 0xFFE0;
|
||||
}
|
||||
sprintf(assembly, "AND R%d, R%d, #%d", Rd, Rs, imm5);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0xF: { // TRAP
|
||||
unsigned short trapvect8 = instr & 0xFF;
|
||||
sprintf(assembly, "TRAP x%02X", trapvect8);
|
||||
break;
|
||||
}
|
||||
/* Handle other opcodes similarly */
|
||||
default:
|
||||
// sprintf(assembly, "UNIMPLEMENTED");
|
||||
assembly = NULL;
|
||||
break;
|
||||
}
|
||||
current->assembly = assembly;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -7,21 +7,68 @@
|
||||
/************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "lc4_memory.h"
|
||||
|
||||
/* declarations of functions that must defined in lc4_loader.c */
|
||||
|
||||
FILE* open_file(char* file_name)
|
||||
{
|
||||
return NULL ;
|
||||
FILE *open_file(char *file_name) {
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
if (file == NULL) {
|
||||
perror("Error opening file");
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
int parse_file (FILE* my_obj_file, row_of_memory** memory)
|
||||
|
||||
/* remember to adjust 16-bit values read from the file for endiannness
|
||||
* remember to check return values from fread() and/or fgetc()
|
||||
*/
|
||||
|
||||
{
|
||||
return 0 ;
|
||||
/* Helper function to read a 16-bit word from the file */
|
||||
unsigned short read_half_word(FILE *file) {
|
||||
unsigned char bytes[2];
|
||||
if (fread(bytes, 1, 2, file) != 2) {
|
||||
return 0;
|
||||
}
|
||||
return (bytes[0] << 8) | bytes[1];
|
||||
}
|
||||
|
||||
int parse_file(FILE *my_obj_file, row_of_memory **memory) {
|
||||
while (!feof(my_obj_file)) {
|
||||
unsigned short header = read_half_word(my_obj_file);
|
||||
if (feof(my_obj_file)) {
|
||||
break;
|
||||
}
|
||||
unsigned short address = read_half_word(my_obj_file);
|
||||
unsigned short n = read_half_word(my_obj_file);
|
||||
|
||||
if (header == 0xCADE || header == 0xDADA) {
|
||||
/* Code or Data section */
|
||||
for (int i = 0; i < n; i++) {
|
||||
unsigned short contents = read_half_word(my_obj_file);
|
||||
add_to_list(memory, address + i, contents);
|
||||
}
|
||||
} else if (header == 0xC3B7) {
|
||||
/* Symbol section */
|
||||
char *label = (char *)malloc(n + 1);
|
||||
if (label == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (fread(label, 1, n, my_obj_file) != n) {
|
||||
free(label);
|
||||
return -1;
|
||||
}
|
||||
label[n] = '\0'; // Null-terminate the string
|
||||
|
||||
row_of_memory *node = search_address(*memory, address);
|
||||
if (node != NULL) {
|
||||
node->label = label;
|
||||
} else {
|
||||
/* Create a new node with only label and address */
|
||||
add_to_list(memory, address, 0);
|
||||
node = search_address(*memory, address);
|
||||
node->label = label;
|
||||
}
|
||||
} else {
|
||||
/* Unknown header, skip n words */
|
||||
fseek(my_obj_file, n * 2, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -7,88 +7,127 @@
|
||||
/************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "lc4_memory.h"
|
||||
|
||||
|
||||
/*
|
||||
* adds a new node to a linked list pointed to by head
|
||||
*/
|
||||
int add_to_list (row_of_memory** head,
|
||||
short unsigned int address,
|
||||
short unsigned int contents)
|
||||
{
|
||||
int add_to_list(row_of_memory **head,
|
||||
short unsigned int address,
|
||||
short unsigned int contents) {
|
||||
/* Check if the node already exists */
|
||||
row_of_memory *existing_node = search_address(*head, address);
|
||||
if (existing_node != NULL) {
|
||||
existing_node->contents = contents;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check to see if there is already an entry for this address and update the contents. no additional steps required in this case */
|
||||
|
||||
/* allocate memory for a single node */
|
||||
/* Allocate memory for a new node */
|
||||
row_of_memory *new_node = (row_of_memory *)malloc(sizeof(row_of_memory));
|
||||
if (new_node == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* populate fields in newly allocated node w/ address&contents, NULL for label and assembly */
|
||||
/* do not malloc() storage for label and assembly here - do it in parse_file() and reverse_assemble() */
|
||||
/* Initialize the new node */
|
||||
new_node->address = address;
|
||||
new_node->contents = contents;
|
||||
new_node->label = NULL;
|
||||
new_node->assembly = NULL;
|
||||
new_node->next = NULL;
|
||||
|
||||
/* if *head is NULL, node created is the new head of the list! */
|
||||
/* Insert the new node into the linked list in ascending order */
|
||||
if (*head == NULL || (*head)->address > address) {
|
||||
new_node->next = *head;
|
||||
*head = new_node;
|
||||
} else {
|
||||
row_of_memory *current = *head;
|
||||
while (current->next != NULL && current->next->address < address) {
|
||||
current = current->next;
|
||||
}
|
||||
new_node->next = current->next;
|
||||
current->next = new_node;
|
||||
}
|
||||
|
||||
/* otherwise, insert node into the list in address ascending order */
|
||||
|
||||
/* return 0 for success, -1 if malloc fails */
|
||||
|
||||
return 0 ;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* search linked list by address field, returns node if found
|
||||
*/
|
||||
row_of_memory* search_address (row_of_memory* head,
|
||||
short unsigned int address )
|
||||
{
|
||||
/* traverse linked list, searching each node for "address" */
|
||||
|
||||
/* return pointer to node in the list if item is found */
|
||||
|
||||
/* return NULL if list is empty or if "address" isn't found */
|
||||
|
||||
return NULL ;
|
||||
row_of_memory *search_address(row_of_memory *head,
|
||||
short unsigned int address) {
|
||||
row_of_memory *current = head;
|
||||
while (current != NULL) {
|
||||
if (current->address == address) {
|
||||
return current;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* search linked list by opcode field, returns node if found
|
||||
*/
|
||||
row_of_memory* search_opcode (row_of_memory* head,
|
||||
short unsigned int opcode )
|
||||
{
|
||||
/* opcode parameter is in the least significant 4 bits of the short int and ranges from 0-15 */
|
||||
/* see assignment instructions for a detailed description */
|
||||
|
||||
/* traverse linked list until node is found with matching opcode in the most significant 4 bits
|
||||
AND "assembly" field of node is NULL */
|
||||
|
||||
/* return pointer to node in the list if item is found */
|
||||
|
||||
/* return NULL if list is empty or if no matching nodes */
|
||||
|
||||
return NULL ;
|
||||
row_of_memory *search_opcode(row_of_memory *head,
|
||||
short unsigned int opcode) {
|
||||
row_of_memory *current = head;
|
||||
while (current != NULL) {
|
||||
unsigned short instr = current->contents;
|
||||
unsigned short instr_opcode = (instr >> 12) & 0xF;
|
||||
if (instr_opcode == opcode && current->assembly == NULL) {
|
||||
return current;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void print_list(row_of_memory *head) {
|
||||
/* make sure head isn't NULL */
|
||||
if (head == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
void print_list (row_of_memory* head )
|
||||
{
|
||||
/* make sure head isn't NULL */
|
||||
/* print out a header */
|
||||
printf("%-20s %-20s %-20s %s\n", "<label>", "<address>", "<contents>", "<assembly>");
|
||||
|
||||
/* print out a header */
|
||||
|
||||
/* traverse linked list, print contents of each node */
|
||||
/* traverse linked list, print contents of each node */
|
||||
row_of_memory *current = head;
|
||||
while (current != NULL) {
|
||||
char address_str[20];
|
||||
char contents_str[20];
|
||||
sprintf(address_str, "%04X", current->address);
|
||||
sprintf(contents_str, "%04X", current->contents);
|
||||
printf("%-20s %-20s %-20s %s\n",
|
||||
current->label ? current->label : "",
|
||||
address_str,
|
||||
contents_str,
|
||||
current->assembly ? current->assembly : "");
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete entire linked list
|
||||
*/
|
||||
int delete_list (row_of_memory** head )
|
||||
{
|
||||
/* delete entire list node by node */
|
||||
/* set the list head pointer to NULL upon deletion */
|
||||
|
||||
return 0 ;
|
||||
}
|
||||
int delete_list(row_of_memory **head) {
|
||||
row_of_memory *current = *head;
|
||||
while (current != NULL) {
|
||||
row_of_memory *next_node = current->next;
|
||||
if (current->label != NULL) {
|
||||
free(current->label);
|
||||
}
|
||||
if (current->assembly != NULL) {
|
||||
free(current->assembly);
|
||||
}
|
||||
free(current);
|
||||
current = next_node;
|
||||
}
|
||||
*head = NULL;
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user