⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tm.cpp

📁 snl语言是一个简单的具有嵌套过程定义的过程式语言
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  }
  return temp;
} /* getWord */


/************************************************************/
/* 函数名 skipCh											*/
/* 功  能 字符空过函数										*/
/* 说  明 如果当前位置上字符为函数指定的字符,则空过该字符,	*/
/*		  函数返回TRUE;否则函数返回FALSE					*/
/************************************************************/
int skipCh ( char c  )

{ int temp = FALSE;

  /* 当前位置上字符为函数指定字符c */
  if ( nonBlank() && (ch == c) )

  { getCh();		/* 空过当前字符c,取下一字符 */

    temp = TRUE;	/* 空过指定字符c,函数返回TRUE */
  }
  return temp;
} /* skipCh */


/************************************/
/* 函数名 atEOL						*/
/* 功  能 行结束判断函数			*/
/* 说  明 当前行是否结束的判断函数	*/
/************************************/	
int atEOL(void)

{ return ( ! nonBlank ());	/* 如果当前行中没有非空字符,则函数返回TRUE */
} /* atEOL */


/****************************************************/
/* 函数名 error										*/
/* 功  能 错误处理函数								*/
/* 说  明 函数输出错误行号,指令地址标号和错误信息	*/
/****************************************************/
int error( char * msg, int lineNo, int instNo)

{ 
  /* 输出错误出现位置行号lineNo */
  printf("Line %d",lineNo);

  /* 输出错误指令地址标号instNo */
  if (instNo >= 0) printf(" (Instruction %d)",instNo);

  /* 输出错误信息msg */
  printf("   %s\n",msg);

  return FALSE;
} /* error */


/********************************************************/
/* 函数名 readInstructions								*/
/* 功  能 指令文件读入函数								*/
/* 说  明 将指令文件中的指令逐条读入到指令存储区iMem	*/
/********************************************************/
int readInstructions (void)

{ 
  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 ;
    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 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 :
      printf("HALT: %1d,%1d,%1d\n",r,s,t);
      return srHALT ;
    /**********************************************/
	  
    case opIN :
      do
      { 
		/* 屏幕显示用户提示信息,提示用户为指令输入数值 */
		printf("Enter value for IN instruction: ") ;

		/* 刷新标准输入stdin流和标准输出stdout流 */
        fflush (stdin);
        fflush (stdout);

		/* 从标准输入流stdin取得用户输入的数值,送入缓冲器in_Line */
        gets(in_Line);

		/* 取得用户输入数值的实际长度lineLen */
        lineLen = strlen(in_Line) ;

        inCol = 0;

		/* 如从缓冲器in_Line中成功取得数字,则ok为TRUE */
        ok = getNum();

		/* 用户输入的不是数字,报非法IN指令输入错误 */
        if ( ! ok ) printf ("Illegal value\n");

		/* 将输入的数值num送入IN指令操作数r指定的寄存器reg[r] */
        else reg[r] = num;
      }

	  /* 如果用户输入不合法,重复要求用户输入,直到输入合法数值 */
      while (! ok);
      break;
    /**********************************************/

	/* 屏幕显示OUT指令执行的结果信息 */
    case opOUT :  
      printf ("OUT instruction prints: %d\n", reg[r] ) ;
      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;
    /**********************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -