0

I am nearing the ends of a simple vm i am creating in C and have hit a roadblock in my understanding of the store/load instructions as well as how the values are actually "Stored" in memory. In practice when doing a load and store instruction with the below commands they do seem to work properly and i can load/store values into my registers but when i do an interrupt 1 command to print out memory the only value it seems to print out is the first value i stored onto the "memory". Am i storing incorrectly or just printing out incorrectly or is it something more? Full code posted below for completeness along with highlights of the trouble areas.

MAIN.C

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

#define MAXMEM 1024
#define NUM_REGS 16
int regs[ NUM_REGS];
uint8_t memory[MAXMEM];
uint8_t fetchresult[5];

bool Call = false;
int pc = 0;
int opcode = 0;
int reg1 = 0;
int reg2 = 0;
int reg3 = 0;
//int reg15 = 0;
int imm = 0;
int br1 = 0;
int br2 = 0;
int stackinst = 0;
int br_op = 0;
uint8_t callnxt = 0;
int sp = -1;
int stored = 0;

void showRegs();
void printStack();

size_t loads (char *filename)
{

    FILE *file = fopen(filename, "rb");
    if(!file) {
    perror("Failed to read file");
    exit( EXIT_FAILURE);
    }
    fseek(file, 0, SEEK_END);
    int filesize = ftell(file);
    //printf("filesize is %d\n", filesize);
    sp = filesize;
    rewind(file);
    return fread(memory, sizeof(memory), filesize, file);

}

void fetch(){
    //printf("%02x\n", memory[pc]);
    fetchresult[0] = memory[pc];
    fetchresult[1] = memory[pc+1];
    fetchresult[2] = memory[pc+2];
    fetchresult[3] = memory[pc+3];
    fetchresult[4] = memory[pc+4];
    pc+=2;
    }
int running = 1; // shows vm is running until flag is 0

void decode () {
    opcode = (fetchresult[0]) >> 4;
    //printf("opcode is %d\n", opcode);
    reg1 = (fetchresult[0])&0xf;
    //printf("reg1 is %d\n", reg1);
    reg2 = (fetchresult[1]) >> 4;
    //printf("reg2 is %d\n", reg2);
    reg3 = (fetchresult[1])&0xf;
    //printf("reg3 is %d\n", reg3);
    imm = (fetchresult[1] & 0xFF);
    //printf("immediate value is %d\n", imm);
    br1 = (fetchresult[2] << 8 | fetchresult[3]);
    //printf("br1 value is %d\n", br1);
    br2 = (fetchresult[1] << 16 | br1);
    //printf("br2 value is %d\n", br2);
    stackinst = (fetchresult[1] >> 6);
    //printf("stackinst value is %d\n", stackinst);
    br_op = (fetchresult[0] &0xf);
    //printf("br_op value is %d\n", br_op);
    callnxt = (fetchresult[4]);
    //printf("Callnxt is %02x\n", callnxt);
    }

void eval() {
    switch (opcode)
        {
        case 0:
            printf("halt\n");
            running = 0;
            break;
        case 11:
            printf("Move r%d with value of %d\n", reg1, imm);
            regs[reg1] = imm;
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 1:
            printf("add r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] + regs[reg2];
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 2: 
            printf("and r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] & regs[reg2];
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 3:
            printf("divide r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] / regs[reg2];
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 4:
            printf("multiply r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] * regs[reg2];
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 5:
            printf("subtract r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] - regs[reg2];
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 6:
            printf("or r%d r%d r%d\n", reg1, reg2, reg3);
            regs[reg3] = regs[reg1] | regs[reg2];
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 7:
            switch(br_op)
                {
                case 0: // branchifless
                    if(regs[reg2] < regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 1: //branch if less or equal
                    if(regs[reg2] <= regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 2: // branch if equal
                    if(regs[reg2] == regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 3: // branch if not equal
                    if(regs[reg2] != regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 4: // branch if greater then
                    if(regs[reg2] > regs[reg3]){
                        pc += 2*br1;
                    }
                    break;
                case 5: // branch if greater than or equal
                    if(regs[reg2] >= regs[reg3]){
                        pc += 2*br2;
                    }
                    break;
                case 6: // call & return
                    printf("Call %d\n", br2);
                    regs[15] = pc + 2;
                    printf("Reg 15 is %02x\n", regs[15]);
                    Call = true;
                    pc += 2*br2;
                    break;
                case 7: // jump X
                    printf("Jump %d\n", br1);
                    pc += 2*br2;
                }
            break;
        case 8: // load TO DO 
            sp;
            int loaded = sp + (regs[reg3] + (imm * 2));
            regs[reg1] = memory[loaded];
            printf("Loaded value is %d\n", regs[reg1]);
            sp = sp--;
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 9: // store TO DO 
            sp = sp++;
            stored = sp + (regs[reg3] + (imm * 2));
            sp = stored;
            memory[stored] = regs[reg1];
            printf("Stored value is %d\n", memory[stored]);
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 10: // pop/push/return TO DO 
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;
        case 12: // interrupt TO DO 
            switch(br_op){
                case 0:
                    showRegs();
                    exit(0);
                    break;
                case 1:
                    printStack();
                    exit(0);
                    break;
                }
            break;
            }
        }

void showRegs() {
    int i;
    for (i=0; i< NUM_REGS; i++){
        printf("register %d is %d", i, regs[i] );
        printf("\n");
    }
}

void printStack() {
    //printf("Values in memory? %d\n", memory[sp]);
    for(int i = 0; i < sp; i++) {
        printf("0x%02x ", memory[i]);
        if((i + 1) %4 == 0) {
            printf("\n");
            }
        }
        if(sp != 0) {
            printf("\n");
            }
        }

void run(){
    while(running){
        //showRegs();
        fetch();
        decode();
        eval();
        }
    showRegs();
    }

int main(int argc, char **argv) {

    if(argc <= 1){
        printf("No File Found\n");
        return -1;
        }
    char *filename = argv[1];
    loads(filename);
    //sp++;
    //printf("SP points to %d in memory\n", memory[sp]);

    run();
}

Load and Store Function + Stack Print

case 8: // load TO DO 
            sp;
            int loaded = sp + (regs[reg3] + (imm * 2));
            regs[reg1] = memory[loaded];
            printf("Loaded value is %d\n", regs[reg1]);
            sp = sp--;
            if(Call == true){
                pc = regs[15];
                Call = false;
            }
            break;

case 9: // store TO DO 
                sp = sp++;
                stored = sp + (regs[reg3] + (imm * 2));
                sp = stored;
                memory[stored] = regs[reg1];
                printf("Stored value is %d\n", memory[stored]);
                if(Call == true){
                    pc = regs[15];
                    Call = false;
                }

void printStack() {
        //printf("Values in memory? %d\n", memory[sp]);
        for(int i = 0; i < sp; i++) {
            printf("0x%02x ", memory[i]);
            if((i + 1) %4 == 0) {
                printf("\n");
                }
            }
            if(sp != 0) {
                printf("\n");
                }
            }

Current Input

b604 b702 9622 9743 c100
(Move 4 to R6, Move 2 to R7, Store R6 R2 2, Store R7 R4 3, Interrupt 1)
Description of Store - "stores r6’s value into the memory pointed to by r2 plus 4 bytes"

Current Output Of Memory, bolding stars about the "Stored 4" But there is no 2??

0xb6 0x04 0xb7 0x02 
0x96 0x22 0x97 0x43 
0xc1 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 **0x04** 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00 
0x00 0x00 0x00 0x00
Bret Hasel
  • 303
  • 1
  • 11
  • You use a lot of [global variables](https://stackoverflow.com/questions/484635/are-global-variables-bad) and your indentation is off sometimes. Your code has almost zero comments. It is very hard to follow what is going on and it's hard to understand the code. I suggest using a struct to group elements, passing the context to each function, remove global variables, [keep consistent and clean indentation](https://www.kernel.org/doc/html/v4.10/process/coding-style.html). It will be really way easier to solve problems if your code is readable and clean. – KamilCuk Mar 29 '20 at 16:04
  • `fread(memory, sizeof(memory), filesize` is strange. just `fread(memory, 1, filesize`. The [`sp = sp++;` and `sp = sp--;`](https://stackoverflow.com/questions/949433/why-are-these-constructs-using-pre-and-post-increment-undefined-behavior) are undefined behavior. – KamilCuk Mar 29 '20 at 16:04

0 Answers0