Ellison Larry
Ellison Larry

Reputation: 11

Segemention fault (core dumped)

I'm writing some code for school that mimics a simple CPU. I know what segmentation faults are but I can't find what's wrong with my code.

There is nothing wrong with the header or main, I'm including it for referrence

Here is my header:

#define NUM_BYTES (16 * 1024) 
#define BYTES_PER_WORD 2
#define WORDS_PER_INSTRUCTION 2
#define NUM_WORDS (NUM_BYTES / BYTES_PER_WORD)
#define NUM_INSTRUCTIONS (NUM_WORDS / WORDS_PER_INSTRUCTION)
#define R0 0
#define R1 1
#define R2 2
#define R3 3
#define R4 4
#define R5 5

typedef unsigned short Machine_word;

typedef enum { PLUS, MINUS, TIMES, DIV, NEG, AND, OR, NOT, LI, LW, SW,
               MOVE, CMP, READ, WRITE, HALT } Opcode;

typedef enum { LT, LE, GT, GE, EQ, NE } Comparison;

typedef struct {
  Opcode opcode;
  Comparison comparison;
  unsigned short reg1;
  unsigned short reg2;
  unsigned short reg3;
  unsigned short addr_or_imm;
} Instruction;

void print_instruction(Instruction instr);
int disassemble(const Machine_word memory[], int starting_addr, int num_instrs,
                Instruction instrs[], int *const valid_instrs);
int valid_instruction(Machine_word instr_word1, Machine_word instr_word2);
int assemble(unsigned short opcode, unsigned short comparison,
             unsigned short reg1, unsigned short reg2, unsigned short reg3,
             unsigned short addr_or_imm, Machine_word *const word1,
             Machine_word *const word2);

My main:

#include<stdio.h>
#include "header.h"

#define PROGRAM_SIZE 10


int main() {
  Machine_word words[NUM_WORDS]= {0x10a5,      0,  /* 2 words of 1st instr. */
                                  0x80c0, 0x03ff,  /* 2 words of 2nd instr. */
                                  0xa040, 0x00d8,  /* etc. */
                                  0x5008,      0,
                                  0x7080,      0,
                                  0xc528, 0x21f8,
                                  0x9080, 0x2718,
                                  0xb058,      0,
                                  0xe100,      0,
                                  0xf000,      0};
  /* double braces because it's an array of structures */
  Instruction instrs[NUM_INSTRUCTIONS]= {{0}};
  int i, num_valid_instrs= 0;

  disassemble(words, 0, PROGRAM_SIZE, instrs, &num_valid_instrs);

  for (i= 0; i < num_valid_instrs; i++) {
    print_instruction(instrs[i]);
    printf("\n");
  }

My functions: (the first function has no issue!)

#include<stdio.h>
#include "machine.h"


void print_instruction(Instruction instr) {

  if (instr.opcode == HALT) {
    printf("halt");
  } else if (instr.opcode == PLUS) {
    printf("plus\tR%hu\tR%hu\tR%hu", instr.reg1, instr.reg2, instr.reg3);
  } else if (instr.opcode == MINUS) {
    printf("minus\tR%hu\tR%hu\tR%hu", instr.reg1, instr.reg2, instr.reg3);
  } else if (instr.opcode == TIMES) {
    printf("times\tR%hu\tR%hu\tR%hu", instr.reg1, instr.reg2, instr.reg3);
  } else if (instr.opcode == DIV) {
    printf("div\tR%hu\tR%hu\tR%hu", instr.reg1, instr.reg2, instr.reg3);
  } else if (instr.opcode == NEG) {
    printf("neg\tR%hu\tR%hu", instr.reg1, instr.reg2);
  } else if (instr.opcode == AND) {
    printf("and\tR%hu\tR%hu\tR%hu", instr.reg1, instr.reg2, instr.reg3);
  } else if (instr.opcode == OR) {
    printf("or\tR%hu\tR%hu\tR%hu", instr.reg1, instr.reg2, instr.reg3);
  } else if (instr.opcode == NOT) {
    printf("not\tR%hu\tR%hu", instr.reg1, instr.reg2);
  } else if(instr.opcode == LI) {
    printf("li\tR%hu\t%05hu", instr.reg1, instr.addr_or_imm);
  }else if (instr.opcode == LW) {
    printf("lw\tR%hu\t%05hu", instr.reg1, instr.addr_or_imm);
  } else if (instr.opcode == SW) {
    printf("sw\tR%hu\t%05hu", instr.reg1, instr.addr_or_imm);
  } else if (instr.opcode == MOVE) {
    printf("move\tR%hu\tR%hu", instr.reg1, instr.reg2);
  } else if (instr.opcode == CMP) {
    printf("cmp %d\tR%hu\tR%hu\t%05hu", (int)instr.comparison, instr.reg1, instr.reg2, instr.addr_or_imm);
  } else if (instr.opcode == READ) {
    printf("read\tR%hu", instr.reg1);
  } else if (instr.opcode == WRITE) {
    printf("write\tR%hu", instr.reg1);
  }
}


int disassemble(const Machine_word memory[], int starting_addr, int num_instrs, Instruction instrs[], int *const valid_instrs) {
  int i, count= 0, index= 0;

  if(starting_addr % 4 != 0)
    return 0;
  if(starting_addr < 0 || starting_addr > 16384)
    return 0;
  if(starting_addr + num_instrs*4 > 16384)
    return 0;
  if(memory == NULL || instrs == NULL)
    return 0;

  for(i = starting_addr/2; i < i + num_instrs*2; i += 2){
    /*read instructions*/
    Machine_word opcode = memory[i];
    Machine_word comparison = memory[i];
    Machine_word reg1 = memory[i];
    Machine_word reg2 = memory[i];
    Machine_word reg3 = memory[i];
    Machine_word mem_addr = memory[i + 1];

    opcode = (opcode & 0xf000) >> 12;
    comparison = (comparison & 0x0e00) >> 9;
    reg1 = (reg1 & 0x01c0) >> 6;
    reg2 = (reg2 & 0x0038) >> 3;
    reg3 = (reg3 & 0x0007);

    if(opcode == 0) {
      instrs[index].opcode = PLUS;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
      instrs[index].reg3 = reg3;
    } else if(opcode == 1) {
      instrs[index].opcode = MINUS;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
      instrs[index].reg3 = reg3;
    } else if(opcode == 2) {
      instrs[index].opcode = TIMES;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
      instrs[index].reg3 = reg3;
    } else if(opcode == 3) {
      instrs[index].opcode = DIV;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
      instrs[index].reg3 = reg3;
    } else if(opcode == 4) {
      instrs[index].opcode = NEG;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
    } else if(opcode == 5) {
      instrs[index].opcode = AND;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
      instrs[index].reg3 = reg3;
    } else if(opcode == 6) {
      instrs[index].opcode = OR;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
      instrs[index].reg3 = reg3;
    } else if(opcode == 7) {
      instrs[index].opcode = NOT;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
    } else if(opcode == 8){
      instrs[index].opcode = LI;
      instrs[index].reg1 = reg1;
      instrs[index].addr_or_imm = mem_addr;
    } else if(opcode == 9) {
      instrs[index].opcode = LW;
      instrs[index].reg1 = reg1;
      instrs[index].addr_or_imm = mem_addr;
    } else if(opcode == 10) {
      instrs[index].opcode = SW;
      instrs[index].reg1 = reg1;
      instrs[index].addr_or_imm = mem_addr;
    } else if(opcode == 11) {
      instrs[index].opcode = MOVE;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
    } else if(opcode == 12) {
      instrs[index].opcode = CMP;
      instrs[index].comparison = (Comparison)comparison;
      instrs[index].reg1 = reg1;
      instrs[index].reg2 = reg2;
    } else if(opcode == 13) {
      instrs[index].opcode = READ;
      instrs[index].reg1 = reg1;
    } else if(opcode == 14) {
      instrs[index].opcode = WRITE;
      instrs[index].reg1 = reg1;
    } else if(opcode == 15) {
      instrs[index].opcode = HALT;
    }

    index++;
    count++;

  }

  *valid_instrs = count;
  return 1;
}

Only the second function, which does bit manipulations, has issues

apologies for it being so long.

Upvotes: 1

Views: 155

Answers (1)

Peter K.
Peter K.

Reputation: 134

As told in comments above, the error is in i < i + num_instrs*2 condition. Note, the value of 'i' is not frizzed in i + num_instrs*2 - it is incremented on each step - i. e. condition will looks like 0 < 0 +10*2, 2 < 2 +10*2, 4 < 4 +10*2. So you need to use initial value starting_addr/2 in condition:

Please change

for(i = starting_addr/2; i < i + num_instrs*2; i += 2){

to

for(i = starting_addr/2; i < starting_addr/2 + num_instrs*2; i += 2){

Upvotes: 2

Related Questions