📄 tm.cpp
字号:
iMem[loc].iarg1 = 0 ;
iMem[loc].iarg2 = 0 ;
iMem[loc].iarg3 = 0 ;
}
lineNo = 0 ; /* lineNo用于记录当前代码指令行号 */
/* 不是指定文件pgm的文件结尾 */
while (! feof(pgm))
{
/* 从指定文件pgm中读入119个字符到当前代码行in_Line */
fgets( in_Line, LINESIZE-2, pgm ) ;
inCol = 0 ; /* 当前代码行in_Line中当前字符位置inCol初始为0 */
lineNo++; /* 当前代码行行号加1 */
/* 当前代码行in_Line行结尾字符位置赋给lineLen */
lineLen = strlen(in_Line)-1 ;
/* 如果源行结束字符是'\n',则更换行结束字符为'\0' */
if (in_Line[lineLen]=='\n') in_Line[lineLen] = '\0' ;
/* 源行没有行结束字符,加上结束字符'\0' */
else in_Line[++lineLen] = '\0';
/* 当前字符不是"*",即不是注释语句,应该是指令语句 */
if ( (nonBlank()) && (in_Line[inCol] != '*') )
{
/* 当前字符不是数字,报地址错,并给出行号lineNo */
if (! getNum())
return error("Bad location", lineNo,-1);
/* 将所得数值赋给当前代码地址标号loc */
loc = num;
/* 代码地址标号loc超出指令存储区地址IADDR_SIZE,报错 */
if (loc > IADDR_SIZE)
return error("Location too large",lineNo,loc);
/* 代码地址标号loc后面缺少冒号,报缺少冒号错 */
if (! skipCh(':'))
return error("Missing colon", lineNo,loc);
/* 当前位置不是单词,报缺少指令操作码错 */
if (! getWord ())
return error("Missing opcode", lineNo,loc);
/* 初始查表指针op,op指向操作码表表首,值为opHALT */
op = opHALT ;
/* 查操作码表opCodeTab,只比较当前字word中的前四个字符 *
* 因为所有定义的操作码中,最长操作码HALT长度只为四 */
while ((op < opRALim)
&& (strncmp(opCodeTab[op], word, 4) != 0) )
op = (enum opcode)(op+1);
/* 当前单词word中指定的操作码不在操作码表opCodeTab中,报非法操作码错误 */
if (strncmp(opCodeTab[op], word, 4) != 0)
return error("Illegal opcode", lineNo,loc);
/* 对查表得到的操作码值op的寻址模式,进行分类处理 */
switch ( opClass(op) )
{ case opclRR : /* 寄存器寻址模式操作码 */
/* 第一寄存器操作数错,非0-7之间数字, *
* 输出错误信息,行号lineNo,代码地址标号loc */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad first register", lineNo,loc);
/* 将第一操作数arg1赋值为当前数值num */
arg1 = num;
/* 第一操作数后漏掉","分隔符,报错 */
if ( ! skipCh(','))
return error("Missing comma", lineNo, loc);
/* 第二寄存器操作数错,非0-7之间数字, *
* 输出错误信息,行号lineNo,代码地址标号loc */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad second register", lineNo, loc);
/* 将第二个操作数arg2赋值为当前数值num */
arg2 = num;
/* 第二操作数后漏掉","分隔符,报错 */
if ( ! skipCh(','))
return error("Missing comma", lineNo,loc);
/* 第三寄存器操作数错,非0-7之间数字,报错 */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad third register", lineNo,loc);
/* 将第三操作数arg3赋值为当前数值num */
arg3 = num;
break;
/* 寄存器-内存寻址模式 *
* 寄存器-立即数寻址模式 */
case opclRM :
case opclRA :
/* 第一寄存器操作数错,非0-7之间数字,报错 */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad first register", lineNo,loc);
/* 将第一操作数arg1赋值为当前数值num */
arg1 = num;
/* 第一操作数后面漏掉","分隔符,报错 */
if ( ! skipCh(','))
return error("Missing comma", lineNo,loc);
/* 第二偏移地址操作数错误,非数字偏移地址,报错 */
if (! getNum ())
return error("Bad displacement", lineNo,loc);
/* 将第二偏移地址操作数arg2赋值为当前地址num */
arg2 = num;
/* 第二偏移地址操作数后漏掉"(",或者是","分隔符,报错 */
if ( ! skipCh('(') && ! skipCh(',') )
return error("Missing LParen", lineNo,loc);
/* 第二寄存器操作数错,非0-7之间数字,报错 */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS))
return error("Bad second register", lineNo,loc);
/* 将第三操作数arg3赋值为当前数值num */
arg3 = num;
break;
}
/* 按代码地址标号loc将指令存储到指令存储区iMem */
iMem[loc].iop = op;
iMem[loc].iarg1 = arg1;
iMem[loc].iarg2 = arg2;
iMem[loc].iarg3 = arg3;
}
}
return TRUE;
} /* readInstructions */
/************************************************/
/* 函数名 stepTM */
/* 功 能 TM机单步执行函数 */
/* 说 明 函数为一条指令解释执行,完成指令动作. */
/************************************************/
STEPRESULT Ctm::stepTM (void)
{
/* currentinstruction 用于存储当前将执行的指令 */
INSTRUCTION currentinstruction ;
int pc ; /* 程序计数器 */
int r,s,t,m ; /* 指令操作数 */
int ok ;
/* pc设置为第7个寄存器reg[7]的值,为程序计数器 */
pc = reg[PC_REG] ;
if ( (pc < 0) || (pc > IADDR_SIZE) )
/* pc的值不是指令存储区的有效地址,报指令存储错,函数返回srIMEM_ERR */
return srIMEM_ERR ;
/* pc的值为有效指令地址,将程序计数器reg[PC_REG]的值加1 */
reg[PC_REG] = pc + 1 ;
/* 从指令存储区iMem之中取出当前指令 */
currentinstruction = iMem[ pc ] ;
/* 对取出的指令的寻址模式分类处理,初始化各个指令操作数变量 */
switch (opClass(currentinstruction.iop) )
{ case opclRR : /* 寄存器寻址模式 */
r = currentinstruction.iarg1 ;
s = currentinstruction.iarg2 ;
t = currentinstruction.iarg3 ;
break;
case opclRM : /* 寄存器-内存寻址模式 */
r = currentinstruction.iarg1 ;
s = currentinstruction.iarg3 ;
m = currentinstruction.iarg2 + reg[s] ;
/* 操作数m非数据存储区有效地址,报数据存储错,函数返回srDMEM_ERR */
if ( (m < 0) || (m > DADDR_SIZE))
return srDMEM_ERR ;
break;
case opclRA : /* 寄存器-立即数寻址模式 */
r = currentinstruction.iarg1 ;
s = currentinstruction.iarg3 ;
m = currentinstruction.iarg2 + reg[s] ;
break;
} /* case */
/* 对将执行指令的操作码值进行分类处理,输出指令信息, *
* 完成指令动作,返回相应结果状态 */
switch ( currentinstruction.iop)
{
/******************** RR指令 ******************/
/* 格式化屏幕显示HALT(停止)指令,返回状态srHALT(停止) */
case opHALT :
//fprintf(listing,"HALT: %1d,%1d,%1d\r\n",r,s,t);
str1.Format("HALT: %1d,%1d,%1d\r\n",r,s,t);
str2+=str1;
return srHALT ;
/**********************************************/
case opIN :
do
{
//显示输入数据对话框,得到用户输入的数值:
CinNum myinputNum;
myinputNum.DoModal();
in_Line[0]= '\0';
strcpy(in_Line , myinputNum.m_inputNum);
/* 取得用户输入数值的实际长度lineLen */
lineLen = strlen(in_Line) ;
inCol = 0;
/* 如从缓冲器in_Line中成功取得数字,则ok为TRUE */
ok = getNum();
/* 用户输入的不是数字,报非法IN指令输入错误 */
if ( ! ok )
//fprintf(listing, "Illegal value\r\n");
str2+= "Illegal value\r\n";
/* 将输入的数值num送入IN指令操作数r指定的寄存器reg[r] */
else reg[r] = num;
}
/* 如果用户输入不合法,重复要求用户输入,直到输入合法数值 */
while (! ok);
break;
/**********************************************/
/* 屏幕显示OUT指令执行的结果信息 */
case opOUT :
//fprintf(listing,"OUT instruction prints: %d\r\n", reg[r] ) ;
str1.Format("OUT instruction prints: %d\r\n", reg[r] ) ;
str2+= str1;
break;
/**********************************************/
/* 完成ADD指令操作 */
case opADD : reg[r] = reg[s] + reg[t] ; break;
/**********************************************/
/* 完成SUB指令操作 */
case opSUB : reg[r] = reg[s] - reg[t] ; break;
/**********************************************/
/* 完成MUL指令操作 */
case opMUL : reg[r] = reg[s] * reg[t] ; break;
/**********************************************/
case opDIV :
/* 对于除法指令,若除数为0,则报除零错误, *
* 并返回srZERODIVIDE;否则,完成除法操作 */
if ( reg[t] != 0 ) reg[r] = reg[s] / reg[t];
else return srZERODIVIDE ;
break;
/***************** RM 指令 ********************/
/* 将数据存储区dMem中的数据载入到寄存器reg[r] */
case opLD : reg[r] = dMem[m] ; break;
/**********************************************/
/* 将寄存器reg[r]中的数据写入到数据存储区dMem */
case opST : dMem[m] = reg[r] ; break;
/***************** RA 指令 ********************/
/* 将寄存器reg[r]赋值为操作数m的值 */
case opLDA : reg[r] = m ; break;
/**********************************************/
/* 将寄存器reg[r]赋值为当前指令的第二操作数的值 */
case opLDC : reg[r] = currentinstruction.iarg2 ; break;
/**********************************************/
/* 如果寄存器reg[r]的值小于0,则将程序计数器reg[PC_REG]的值 *
* 赋值为立即数m,产生小于条件跳转 */
case opJLT : if ( reg[r] < 0 ) reg[PC_REG] = m ; break;
/**********************************************/
/* 如果寄存器reg[r]的值小于等于0,则将程序计数器reg[PC_REG]的值 *
* 赋值为立即数m,产生小于等于条件跳转 */
case opJLE : if ( reg[r] <= 0 ) reg[PC_REG] = m ; break;
/**********************************************/
/* 如果寄存器reg[r]的值大于0,则将程序计数器reg[PC_REG]的值 *
* 赋值为立即数m,产生大于条件跳转 */
case opJGT : if ( reg[r] > 0 ) reg[PC_REG] = m ; break;
/**********************************************/
/* 如果寄存器reg[r]的值大于等于0,则将程序计数器reg[PC_REG]的值 *
* 赋值为立即数m,产生大于等于跳转 */
case opJGE : if ( reg[r] >= 0 ) reg[PC_REG] = m ; break;
/**********************************************/
/* 如果寄存器reg[r]的值等于0,则将程序计数器reg[PC_REG]的值 *
* 赋值为立即数m,产生等于条件跳转 */
case opJEQ : if ( reg[r] == 0 ) reg[PC_REG] = m ; break;
/**********************************************/
/* 如果寄存器reg[r]的值不等于0,则将程序计数器reg[PC_REG]的值 *
* 赋值为立即数m,产生不等于条件跳转 */
case opJNE : if ( reg[r] != 0 ) reg[PC_REG] = m ; break;
}
/* case */
/* 所有正常结束指令,返回正常结果状态 */
return srOKAY ;
} /* stepTM */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -