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

📄 tm.cpp

📁 snl语言是一个简单的具有嵌套过程定义的过程式语言
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***** 该代码文件所包含头文件 *****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* 宏定义常量TRUE为1 */
#ifndef TRUE
#define TRUE 1
#endif
/* 宏定义常量FALSE为0 */
#ifndef FALSE
#define FALSE 0
#endif


/***************** 常量 *******************/

/* 为大型程序扩展,指令存储区大小,定义为1024 */
#define   IADDR_SIZE  1024 
/* 为大型程序扩展,数据存储区大小,定义为1024 */
#define   DADDR_SIZE  1024 
/* 寄存器数量,定义为8 */
#define   NO_REGS 8
/* PC寄存器,定义为7 */
#define   PC_REG  7
/* 目标代码行大小,定义为121 */
#define   LINESIZE  121
/* 字大小,定义为20 */
#define   WORDSIZE  20


/**************** 类型 *******************/

/* 指令寻址模式类型 */
typedef enum 
{
   opclRR,		/* 寄存器寻址模式类型,操作数使用寄存器r,s,t */
   opclRM,		/* 寄存器-内存寻址模式类型,操作数使用寄存器r,内存地址d+s */
   opclRA		/* 寄存器-立即数寻址模式类型,操作数使用寄存器r,立即数值d+s */
} OPCLASS;

/* 操作指令标识码类型 */
typedef enum opcode{

   /************* 寄存器寻址模式指令标识码 ***************/

   opHALT,	/* 停止指令:结束程序执行,忽略操作数 */
   
   opIN,	/* 输入指令:将外部变量读入寄存器,使用第r个寄存器,忽略s,t参数 */

   opOUT,	/* 输出指令:将寄存器的值输出,使用第r个寄存器,忽略s,t参数 */

   opADD,   /* 加法指令:寄存器r的值赋为寄存器s的值与寄存器t的值的和 */

   opSUB,   /* 减法指令:寄存器r的值赋为寄存器s的值与寄存器t的值的差 */

   opMUL,   /* 乘法指令:寄存器r的值赋为寄存器s的值与寄存器t的值的积 */

   opDIV,   /* 除法指令:寄存器r的值赋为寄存器s的值与寄存器t的值的商 */

   /* 寄存器寻址模式指令限制标志,							*
    * 操作标识码枚举值小于opRRLim的指令均为寄存器寻址模式指令	*/
   opRRLim,  

   /************** 寄存器-内存寻址模式指令标识码 ****************/

   opLD,	/* 载入指令:寄存器r的值赋为地址为d+reg(s)的内存单元的值 */

   opST,    /* 设置指令:将地址为d+reg(s)的内存单元值赋为寄存器r的值 */

   /* 寄存器-内存寻址模式指令限制标志										*
    * 操作标识码枚举值小于opRMLim且大于opRRLim的均为寄存器-内存寻址模式指令 */
   opRMLim, 

  
   /************* 寄存器-立即数寻址模式指令标识码 ****************/

   opLDA,	/* 载入指令:将寄存器r的值赋为立即数d与寄存器s的值的和 */

   opLDC,   /* 载入指令:将寄存器r的值赋为立即数d,参数s被忽略 */

   opJLT,   /* 如果寄存器r的值小于0,将第7个寄存器的值赋为d+reg(s)	*
			 * 第7个寄存器为pc程序计数寄存器						*/

   opJLE,   /* 如果寄存器r的值小于等于0,将pc寄存器的值赋为d+reg(s) */

   opJGT,   /* 如果寄存器r的值大于0,将pc寄存器的值赋为d+reg(s) */

   opJGE,   /* 如果寄存器r的值大于等于0,将pc寄存器的值赋为d+reg(s) */

   opJEQ,   /* 如果寄存器r的值等于0,将pc寄存器的值赋为d+reg(s) */

   opJNE,   /* 如果寄存器r的值不等于0,将pc寄存器的值赋为d+reg(s) */

   /* 寄存器-立即数寻址模式指令限制标志
    * 操作标识码枚举值小于opRALim且大于opRMLim的均为寄存器-立即数寻址模式指令 */
   opRALim    

   } OPCODE;						

/************ 指令单步执行结果类型 ************/
typedef enum {
   srOKAY,			/* 正常 */

   srHALT,			/* 停止 */

   srIMEM_ERR,		/* 指令存储错 */

   srDMEM_ERR,		/* 数据存储错 */

   srZERODIVIDE		/* 除数为零错 */

   } STEPRESULT;

/* 指令结构类型:操作码,操作数1,操作数2,操作数3 */
typedef struct {
      int iop  ;
      int iarg1  ;
      int iarg2  ;
      int iarg3  ;
   } INSTRUCTION;


/******** 变量 ********/

int iloc = 0 ;			/* 指令存储计数指针,初始为0 */

int dloc = 0 ;			/* 数据存储计数指针,初始为0 */

int traceflag = FALSE;	/* 指令执行追踪标志,初始为FALSE */

int icountflag = FALSE;	/* 指令执行计数标志,初始为FALSE */

/* iMem用于指令存储,为1024长的指令结构数组 */
INSTRUCTION iMem [IADDR_SIZE];				

/* dMem用于数据存储,为1024长的整数类型数组 */
int dMem [DADDR_SIZE];						

/* reg用于寄存器存储,为8长的整数类型数组 */
int reg [NO_REGS];							


/* 指令操作码表,对应寻址模式分为三类 */
char * opCodeTab[]

        = {"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
          /* 寄存器寻址模式指令类型 */

           "LD","ST","????", 
		  /* 寄存器-内存寻址模式指令类型 */

           "LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
          /* 寄存器-立即数寻址模式指令类型 */
          };

/** 单步执行结果状态表 **/
char * stepResultTab[]

        = {"OK","Halted","Instruction Memory Fault",
           "Data Memory Fault","Division by 0"
          };

char pgmName[20];			/* 用于存储程序文件名 */

FILE *pgm  ;				/* 程序文件指针 */

char in_Line[LINESIZE] ;	/* 用于存储一行代码,为121长的字符数组 */

int lineLen ;				/* in_Line中行结尾字符位置 */

int inCol  ;				/* 用于指出在in_Line中的当前字符位置 */

int num  ;					/* 用于存储当前所得数值 */

char word[WORDSIZE] ;		/* 用于存储当前的字,为20长的字符数组 */

char ch  ;					/* 当前代码行中当前位置上的字符 */

int done  ;



/****************************************************/
/* 函数名 opClass									*/
/* 功  能 指令寻址模式分类函数						*/
/* 说  明 该函数对给定的指令操作码枚举值c进行分类	*/
/*        返回指令所属寻址模式						*/
/****************************************************/
int opClass( int c )

{ 
  /* 如果枚举值c小于opRRLim,则指令为寄存器寻址模式指令类型 */
  if      ( c <= opRRLim) return ( opclRR );

  /* 如果枚举值c小于opRMLim,则指令为寄存器-内存寻址模式指令类型 */
  else if ( c <= opRMLim) return ( opclRM );

  /* 为寄存器-立即数寻址模式指令类型 */
  else                    return ( opclRA );

} 

/********************************************************/
/* 函数名 writeInstruction								*/
/* 功  能 指令输出函数									*/
/* 说  明 该函数将指令存储区中指令以指定格式输出到屏幕	*/
/********************************************************/
void writeInstruction ( int loc )

{  
  /* loc为所要输出的指令在指令存储区中地址,输出到屏幕 */
  printf( "%5d: ", loc) ;

  /* 输出指令地址loc在0-1023有效的指令存储区地址范围之内 */
  if ( (loc >= 0) && (loc < IADDR_SIZE) )

  { 
    /* 输出地址为loc上的指令操作码值iMem[loc].iop和第一操作数iMem[loc].iarg1 */
	printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);

	/* 根据指令的寻址模式分类处理 */
    switch ( opClass(iMem[loc].iop) )

    { 
      /* 输出指令为寄存器寻址模式指令,以给定形式输出操作数2,操作数3 */
	  case opclRR: printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
                   break;		

      /* 输出指令为寄存器-立即数寻址模式指令,和寄存器-内存寻址模式指令	*
	   * 以给定形式输出操作数2,操作数3									*/
      case opclRM: 
      case opclRA: printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
                   break;	
    }
   	/* 向屏幕输出换行符 */
	printf ("\n") ;
  }
} /* writeInstruction */

/****************************************************/
/* 函数名 getCh										*/
/* 功  能 字符获取函数								*/
/* 说  明 如果当前行中字符未读完,则函数返回当前字符	*/
/*		  否则,函数返回空格字符						*/
/****************************************************/
void getCh (void)

{ 
  /* 在当前代码行in_Line中,当前字符列数inCol未超过代码行实际长度lineLen *
   * 取得当前行中当前位置的字符,送入ch									*/
  if (++inCol < lineLen)
  ch = in_Line[inCol] ;

  /* 如果inCol超出当前代码行长度范围,则ch赋为空格 */
  else ch = ' ' ;

} /* getCh */



/********************************************************/
/* 函数名 nonBlank										*/
/* 功  能 非空字符获取函数								*/
/* 说  明 如果成功从当前行中取得非空字符,函数返回TRUE	*/
/*		  否则,函数返回FALSE							*/
/********************************************************/
int nonBlank (void)

{ 
  /* 在当前代码行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 getNum (void)

{ 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 getWord (void)

{ 
	
  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);

⌨️ 快捷键说明

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