0

Im attempting to put together a basic C Virtual machine that will read a binary file from an assembler program and use that file to execute commands based on the binary data in that file. Im at the point where i need to decode values into its hex format and then use these to determine opcode and execution operations. This is the part im confused on how to work around this? I have the registers and instructions defined but im wondering how i am to use the Fetch function to read the "instruction bytes" from memory and then decode to populate OP1 and/or OP2 in order to determine what command is to be done, what has me confused is with a command like pop push and return for within this example they all have the same starting opcode of 7 and differ only in the latter 2 bytes of push being 40 pop being 80 and return being 00. How can i pass all the 4-8 bytes of a command into fetch and be able to determine the command to be executed?

MAIN.C

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

unsigned char memory[1028];

typedef enum{
    halt,
    add,
    and,
    divide,
    mult,
    sub,
    or,
    popushret,
    interrupt,
    addimmediate,
    branchifequal,
    branchifless,
    jump,
    call,
    load,
    store
} Instructions;

typedef enum{
    R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16,
    PC,
    OP1, OP2,
    Result,
    CIP,
} Registers;

void decode( ) { // Read only from the array of bytes from fetch. Populate the OP1 and OP2 registers if appropriate. Fetch any additional memory needed to complete the instruction.

}

void fetch(int memory){ // Read instruction bytes from memory. 
    printf("%02x\n", memory);

}
int loads(char *filename){
     FILE *file = fopen(filename, "rb");
     ssize_t read;
     if(file == NULL){
         exit(-1);
     }

     while(fread(&memory, sizeof(unsigned char), 1, file) == 1){
        fetch(*memory);
     }
    fclose(file);
    exit(0);
}

int main(int argc, char** argv){
    if (argc <= 1){
        printf("No file found\n");
        return -1;
    }

    char *filename = argv[1];

    loads(filename);
}

INPUT.txt

74
40
77
40
11
23

OUTPUT.TXT

Desired output from the above is to push 4 to stack, push 7 to stack, pop 7 into R2 and 4 into R1 and the and add both into R3 and store in result
Seki
  • 11,135
  • 7
  • 46
  • 70
Bret Hasel
  • 303
  • 1
  • 11
  • 1
    If your input must be one 32-bit word per line and the instructions require more than one word, clearly you're going to need a more intelligent `loads` function. It will have to read an opcode and then read more bytes depending on what that opcode is. Why not just put the opcode and all it's operands on each line of input instead? – Carey Gregory Nov 23 '19 at 02:09
  • @CareyGregory That latter solution would be much easier to solve this problem but then what would i do to separate each command? Could you perhaps show me and example of the latter? – Bret Hasel Nov 23 '19 at 02:35
  • 1
    Can you write down your opcode more clearly? I can't see a connection between your input.txt and output.txt. 74 40 is push 4 to stack right? 7 for the pushpopret opcode, 40 for specify push and the 4 after 7 for the value? – rifkin Nov 23 '19 at 02:51
  • @rifkin Youre exactly correct, 7 is opcode for pushporet, 40 for push, and the 4 after the 7 is the value – Bret Hasel Nov 23 '19 at 03:54
  • And the rest? 11 23 relates to? Are the two pop instructions missing? – rifkin Nov 23 '19 at 04:01
  • @rifkin 11 23 refers to the add of the two values, the two `push` will put the two values onto the memory stack and then the add will pull the two values out and place them into the registers 1 and 2 and then add them into register 3. `11 23` is equal to 1 = add 1 = R1 2 = R2 3 = R3 – Bret Hasel Nov 23 '19 at 04:04
  • Read the whole file into memory. Then you can traverse with a index or pointer forward and backward in memory. So you can read forward and see if it was necessary. When not decrement. – rifkin Nov 23 '19 at 04:14
  • Could i perhaps ask you for an example of that? Im having issues reading the whole file into memory as im only able to get the first two bytes for some reason – Bret Hasel Nov 23 '19 at 04:15
  • fread(memory, 1, 1028, file); and ommit the while loop – rifkin Nov 23 '19 at 04:20
  • hmm yeah when i go to print out in the "fetch" its only grabbing the 74 part using that @rifkin – Bret Hasel Nov 23 '19 at 04:21
  • You have to rewrite some things here. fetch in this form only grabs the first byte. fetch has to keep track of an memory index. maybe a static one. every time fetch is called increment index ---- printf("%02x", memory[index]); – rifkin Nov 23 '19 at 04:26
  • ahhhh okay that makes sense with how to check a set of 4 bytes but now basically all i need to do is just check the first byte and then use the increment index to operate the rest of the command? – Bret Hasel Nov 23 '19 at 04:34
  • yeah. much work. but i am out of better ideas now. – rifkin Nov 23 '19 at 04:38
  • You `compiled` input (INPUT.txt) looks like a text file. You will have hard time reading it with fread. Consider scanf/fgets instead. – dash-o Nov 23 '19 at 05:57
  • @dash-o That was just how i showed the file on the question, the actual file is binary data that if i copied and pasted here would not be human readable – Bret Hasel Nov 23 '19 at 18:39

0 Answers0