模拟虚拟机,增加pc与跳转有困难

时间:2016-09-19 21:41:59

标签: c virtual-machine

我在C中编写虚拟机并且我已经完成了所有各种功能,但是我无法将它们组合在一起。特别是我遇到了一个问题,我需要一种方法来增加程序计数器,而不会干扰改变PC指向的指令,如JMP,JPC,CAL和RET。当我试图采取措施来取消PC ++,如PCvalueAfterJmp - 1或int main(int argc, char* argv[]){ int running = 1; int numInstructions = 0; int lineRun; int arcntr = 0; //Memory int stack[MAX_STACK_HEIGHT]; instruction code[MAX_CODE_LENGTH]; int arlist[MAX_STACK_HEIGHT]; //Registers int sp=0; int bp=1; int pc=0; instruction ir; //Initializing ir ir.op = 0; ir.l = 0; ir.m = 0; //Initializing stack stack[1] = 0; stack[2] = 0; stack[3] = 0; //Reading the input file numInstructions = readFile(argc, argv, code); if(numInstructions < 0) //Exit with error if readFile returns invalid return 1; //show input code printFile(code, numInstructions); //setup and labeling printState(-1, ir, pc, bp, sp, stack, arlist); //Execution loop while(running) { lineRun = pc; //Fetch cycle ir = code[pc]; //Execution cycle returns a nonzero to keep program running until end if(!execOp(&sp, &bp, &pc, ir, code, stack, arlist, &arcntr)) running = 0; //if statement didn't work printState(lineRun, ir, pc, bp, sp, stack, arlist); //if (!(ir.op == 5 || ir.op == 7 || ir.op == 8 || (ir.op == 2 && ir.m == 0))) pc++; } return 0; } 语句,以便在这些情况下不增加时,它突然进入无限循环,似乎反复通过指令。

该程序读入输入文件并在屏幕上打印正在处理的指令和堆栈的当前状态

int execOp(int* sp, int* bp, int* pc, instruction ir, instruction code[],
           int stack[], int arlist[], int* arcntr){

  switch((opcode)ir.op){
  case LIT:
    stack[++(*sp)] = ir.m;
    break;

  case OPR:  //Operators
    switch((operator)ir.m){

    case RET:
      if(*bp == 1) //Kill the simulation if we're at the base level
        return 0;
      arlist[--(*arcntr)] = 0;
      *sp = *bp - 1;
      *pc = stack[*sp+3];
      *bp = stack[*sp+2];
      break;

    case NEG:
      stack[*sp] = -stack[*sp];
      break;

    case ADD:
      (*sp)--;
      stack[*sp] = stack[*sp] + stack[*sp+1];
      break;

    case SUB:
      (*sp)--;
      stack[*sp] = stack[*sp] - stack[*sp+1];
      break;

    case MUL:
      (*sp)--;
      stack[*sp] = stack[*sp] * stack[*sp+1];
      break;

    case DIV:
      (*sp)--;
      stack[*sp] = stack[*sp] / stack[*sp+1];
      break;

    case ODD:
      stack[*sp] = stack[*sp] % 2;
      break;

    case MOD:
      (*sp)--;
      stack[*sp] = stack[*sp] % stack[(*sp)+1];
      break;

    case EQL:
      (*sp)--;
      stack[*sp] = stack[*sp] == stack[*sp+1];
      break;

    case NEQ:
      (*sp)--;
      stack[*sp] = stack[*sp] != stack[*sp+1];
      break;

    case LSS:
      (*sp)--;
      stack[*sp] = stack[*sp] < stack[*sp+1];
      break;

    case LEQ:
      (*sp)--;
      stack[*sp] = stack[*sp] <= stack[*sp+1];
      break;

    case GTR:
      (*sp)--;
      stack[*sp] = stack[*sp] > stack[*sp+1];
      break;

    case GEQ:
      (*sp)--;
      stack[*sp] = stack[*sp] >= stack[*sp+1];
      break;
    }
    break;

  case LOD:
    stack[++*sp] = stack[base(ir.l, *bp, stack) + ir.m];
    break;

  case STO:
    stack[base(ir.l, *bp, stack) + ir.m] = stack[(*sp)--];
    break;

  case CAL:
    arlist[(*arcntr)++] = *sp + 1;
    stack[*sp + 1] = base(ir.l, *bp, stack);
    stack[*sp + 2] = *bp;
    stack[*sp + 3] = *pc - 1;
    *bp = *sp + 1;
    *pc = ir.m;
    break;

  case INC:
    *sp = *sp + ir.m;
    break;

  case JMP:
    *pc = ir.m;
    break;

  case JPC:
    if(!stack[(*sp)--])
      *pc = ir.m;
    break;

  case SOI:
    printf("%d\n", stack[(*sp)--]);
    break;

  case SIO:
    scanf("%d", &stack[++(*sp)]);
    break;
  }

  return 1; //A non-zero return value keeps the machine running
}

这是我的执行周期

{{1}}

1 个答案:

答案 0 :(得分:0)

这部分指令解码select语句似乎错了

  case CAL:
    arlist[(*arcntr)++] = *sp + 1;
    stack[*sp + 1] = base(ir.l, *bp, stack);
    stack[*sp + 2] = *bp;
    stack[*sp + 3] = *pc - 1;
    *bp = *sp + 1;
    *pc = ir.m;
    break;

通常,您希望在返回时返回NEXT指令。

<强> stack[*sp + 3] = *pc - 1;

*pc-1部分可能会在返回时将您带回回电话说明

我希望你想要推送下一条指令的地址。

您可能希望在推送所有这些之后将堆栈指针更新3,以及检查您的BP逻辑