gpt4 book ai didi

c - 模拟虚拟机,增加pc vs jumps有问题

转载 作者:太空宇宙 更新时间:2023-11-04 04:28:00 28 4
gpt4 key购买 nike

我正在用 C 语言编写一个虚拟机,所有各种函数都可以正常工作,但是我在将它们组合在一起时遇到了问题。具体来说,我遇到了一个问题,我需要一种方法来增加程序计数器,而不会干扰改变 pc 指向的指令,如 JMP、JPC、CAL 和 RET。当我尝试采取措施取消 pc++,如 PCvalueAfterJmp - 1 或 if 语句以不在这些情况下递增时,它突然进入无限循环,似乎在重复执行指令。

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

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
}

最佳答案

你的这部分指令 decode 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 指令。

堆栈[*sp + 3] = *pc - 1;

*pc-1 部分可能会在返回时将您带回到调用指令

我预计您会想要压入下一条指令的地址。

在推送所有这些之后,您可能还想将堆栈指针更新 3,并检查您的 BP 逻辑

关于c - 模拟虚拟机,增加pc vs jumps有问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39582580/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com