add basic function, program can give a result

This commit is contained in:
feng-arch 2024-11-13 10:19:53 +08:00
parent da2e75e912
commit 8968433f33
4 changed files with 312 additions and 102 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}