我在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}}
答案 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逻辑