📄 tm.cpp
字号:
// tm.cpp: implementation of the Ctm class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "face.h"
#include "tm.h"
#include "indialog.h"
#include "inNum.h"
#include "result.h"
#include "comhelp.h"
#include "stdio.h"
#include "MainFrm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
Ctm::Ctm()
{
iloc = 0 ; /* 指令存储计数指针,初始为0 */
dloc = 0 ; /* 数据存储计数指针,初始为0 */
traceflag = FALSE; /* 指令执行追踪标志,初始为FALSE */
icountflag = FALSE; /* 指令执行计数标志,初始为FALSE */
}
Ctm::~Ctm()
{
}
/****************************************************/
/* 函数名 opClass */
/* 功 能 指令寻址模式分类函数 */
/* 说 明 该函数对给定的指令操作码枚举值c进行分类 */
/* 返回指令所属寻址模式 */
/****************************************************/
int Ctm::opClass( int c )
{
/* 如果枚举值c小于opRRLim,则指令为寄存器寻址模式指令类型 */
if ( c <= opRRLim) return ( opclRR );
/* 如果枚举值c小于opRMLim,则指令为寄存器-内存寻址模式指令类型 */
else if ( c <= opRMLim) return ( opclRM );
/* 为寄存器-立即数寻址模式指令类型 */
else return ( opclRA );
}
/********************************************************/
/* 函数名 writeInstruction */
/* 功 能 指令输出函数 */
/* 说 明 该函数将指令存储区中指令以指定格式输出到屏幕 */
/********************************************************/
void Ctm::writeInstruction ( int loc )
{
/* loc为所要输出的指令在指令存储区中地址,输出到屏幕 */
//fprintf(listing, "%5d: ", loc) ;
str1.Format( "%5d: ", loc) ;
str2+=str1;
/* 输出指令地址loc在0-1023有效的指令存储区地址范围之内 */
if ( (loc >= 0) && (loc < IADDR_SIZE) )
{
/* 输出地址为loc上的指令操作码值iMem[loc].iop和第一操作数iMem[loc].iarg1 */
//fprintf(listing,"%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
str1.Format("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
str2+=str1;
/* 根据指令的寻址模式分类处理 */
switch ( opClass(iMem[loc].iop) )
{
/* 输出指令为寄存器寻址模式指令,以给定形式输出操作数2,操作数3 */
case opclRR:
//fprintf(listing,"%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
str1.Format( "%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
str2+= str1;
break;
/* 输出指令为寄存器-立即数寻址模式指令,和寄存器-内存寻址模式指令 *
* 以给定形式输出操作数2,操作数3 */
case opclRM:
case opclRA:
//fprintf(listing,"%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
str1.Format("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
str2+=str1;
break;
}
/* 向屏幕输出换行符 */
//fprintf(listing,"\r\n") ;
str2+="\r\n";
}
} /* writeInstruction */
/****************************************************/
/* 函数名 getCh */
/* 功 能 字符获取函数 */
/* 说 明 如果当前行中字符未读完,则函数返回当前字符 */
/* 否则,函数返回空格字符 */
/****************************************************/
void Ctm::getCh ()
{
/* 在当前代码行in_Line中,当前字符列数inCol未超过代码行实际长度lineLen *
* 取得当前行中当前位置的字符,送入ch */
if (++inCol < lineLen)
ch = in_Line[inCol] ;
/* 如果inCol超出当前代码行长度范围,则ch赋为空格 */
else ch = ' ' ;
} /* getCh */
/********************************************************/
/* 函数名 nonBlank */
/* 功 能 非空字符获取函数 */
/* 说 明 如果成功从当前行中取得非空字符,函数返回TRUE */
/* 否则,函数返回FALSE */
/********************************************************/
int Ctm::nonBlank ()
{
/* 在当前代码行in_Line中,当前字符位置inCol中为空格字符 *
* 在当前代码行in_Line中,当前字符位置inCol下移,略过空格 */
while ((inCol < lineLen)
&& (in_Line[inCol] == ' ') )
inCol++ ;
/* 在当前代码行in_Line中,遇到非空字符 */
if (inCol < lineLen)
{
/* 取当前字符位置inCol中的字符送入ch, *
* 函数返回TRUE(已定义为1),ch中得到非空字符 */
ch = in_Line[inCol] ;
return TRUE ; }
/* 当前代码行已经读完,将当前字符ch 赋为空格, *
* 函数返回FALSE(已定义为0),ch中为空格字符 */
else
{ ch = ' ' ;
return FALSE ; }
} /* nonBlank */
/****************************************************************/
/* 函数名 getNum */
/* 功 能 数值获取函数 */
/* 说 明 将代码行中连续出现的有加减运算的数term合并计数, */
/* 所的数值送入为num.如果成功得到数值,则函数返回TRUE; */
/* 否则,函数返回FALSE */
/****************************************************************/
int Ctm::getNum ()
{ int sign; /* 符号因子 */
int term; /* 用于记录当前录入的局部数值 */
int temp = FALSE; /* 记录函数返回值,初始为假 */
num = 0 ; /* 用于记录所有加减运算后的最终数值结果 */
do
{ sign = 1; /* 符号因子初始为1 */
/* 调用函数nonBlank()略过当前位置的空格后, *
* 所得到的当前非空字符ch为+或-.(+/-的连续出现处理) */
while ( nonBlank() && ((ch == '+') || (ch == '-')) )
{ temp = FALSE ;
/* 当前字符ch为"-"时,符号因子sign设为-1 */
if (ch == '-') sign = - sign ;
/* 取当前代码行中下一字符到当前字符ch中 */
getCh();
}
term = 0 ; /* 当前录入的局部数值初始为0 */
nonBlank(); /* 略过当前位置上的空格 */
/* 当前字符ch为数字,局部数值的循环处理 */
while (isdigit(ch))
{ temp = TRUE ; /* 函数返回值设为TRUE,成功得到数字 */
/* 将字符序列转化为数值形式,进行进位累加 */
term = term * 10 + ( ch - '0' ) ;
getCh(); /* 取当前代码行中下一字符到当前字符ch中 */
}
/* 将局部数值带符号累加,得到最终数值num */
num = num + (term * sign) ;
} while ( (nonBlank()) && ((ch == '+') || (ch == '-')) ) ;
return temp;
} /* getNum */
/****************************************************/
/* 函数名 getWord */
/* 功 能 单词获取函数 */
/* 说 明 函数从当前代码行中获取单词.如果得到字符, */
/* 则函数返回TRUE;否则,函数返回FALSE */
/****************************************************/
int Ctm::getWord ()
{
int temp = FALSE; /* 函数返回值初始为FALSE */
int length = 0; /* 单词长度初始为0 */
/* 在当前代码行中成功获取非空字符ch */
if (nonBlank ())
{
/* 当前非空字符ch为字母或数字 */
while (isalnum(ch))
{
/* 当前单词word未超过规定字长WORDSIZE-1(为单词结束字符留一空位) *
* 将当前字符ch读入到单词末尾 */
if (length < WORDSIZE-1) word [length++] = ch ;
getCh() ; /* 取当前代码行中下一字符 */
}
/* 给当前单词word加入结束字符 */
word[length] = '\0';
/* 设置函数返回值,当读入字word非空的时候为TRUE */
temp = (length != 0);
}
return temp;
} /* getWord */
/************************************************************/
/* 函数名 skipCh */
/* 功 能 字符空过函数 */
/* 说 明 如果当前位置上字符为函数指定的字符,则空过该字符, */
/* 函数返回TRUE;否则函数返回FALSE */
/************************************************************/
int Ctm::skipCh ( char c )
{ int temp = FALSE;
/* 当前位置上字符为函数指定字符c */
if ( nonBlank() && (ch == c) )
{ getCh(); /* 空过当前字符c,取下一字符 */
temp = TRUE; /* 空过指定字符c,函数返回TRUE */
}
return temp;
} /* skipCh */
/************************************/
/* 函数名 atEOL */
/* 功 能 行结束判断函数 */
/* 说 明 当前行是否结束的判断函数 */
/************************************/
int Ctm::atEOL()
{ return ( ! nonBlank ()); /* 如果当前行中没有非空字符,则函数返回TRUE */
} /* atEOL */
/****************************************************/
/* 函数名 error */
/* 功 能 错误处理函数 */
/* 说 明 函数输出错误行号,指令地址标号和错误信息 */
/****************************************************/
int Ctm::error( char * msg, int lineNo, int instNo)
{
AfxGetApp()->m_pMainWnd->MessageBox(msg);
/* 输出错误出现位置行号lineNo */
//fprintf(listing,"Line %d",lineNo);
str1.Format("Line %d",lineNo);
str2+=str1;
/* 输出错误指令地址标号instNo */
if (instNo >= 0)
//fprintf(listing," (Instruction %d)",instNo);
str1.Format(" (Instruction %d)",instNo);
str2+= str1;
/* 输出错误信息msg */
// fprintf(listing," %s\r\n",msg);
str1.Format(" %s\r\n",msg);
str2+=str1;
return FALSE;
} /* error */
/********************************************************/
/* 函数名 readInstructions */
/* 功 能 指令文件读入函数 */
/* 说 明 将指令文件中的指令逐条读入到指令存储区iMem */
/********************************************************/
int Ctm::readInstructions ()
{
OPCODE op; /* 当前指令操作码 */
int arg1, arg2, arg3; /* 当前指令操作数 */
int loc, regNo, lineNo;
/* 将8个寄存器内容初始化为0 */
for (regNo = 0 ; regNo < NO_REGS ; regNo++)
reg[regNo] = 0 ;
/* dMem为数据存储区,0地址单元dMem[0]的值赋为数据存储区高端地址1023 *
* 此数值将在目标程序运行时由程序的先驱指令读入到mp寄存器中 */
dMem[0] = DADDR_SIZE - 1 ;
/* 将数据存储数区内除0地址单元外的各单元初始化为0 */
for (loc = 1 ; loc < DADDR_SIZE ; loc++)
dMem[loc] = 0 ;
/* 将指令存储区中各单元初始化为指令;HALT 0,0,0 */
for (loc = 0 ; loc < IADDR_SIZE ; loc++)
{ iMem[loc].iop = opHALT ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -