- 论坛徽章:
- 0
|
虚拟机源码分析
- /****************************************************/
- /* File: tm.c */
- /* The TM ("Tiny Machine") computer */
- /* Compiler Construction: Principles and Practice */
- /* Kenneth C. Louden */
- /****************************************************/
- #include <stdio.h>;
- #include <stdlib.h>;
- #include <string.h>;
- #include <ctype.h>;
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
- /******* const *******/
- /* 只读指令存储区的大小 */
- #define IADDR_SIZE 1024 /* increase for large programs */
- /* 数据区的大小 */
- #define DADDR_SIZE 1024 /* increase for large programs */
- /* 寄存器的数目 */
- #define NO_REGS 8
- /* PC寄存器(程序计数器)的下标 */
- #define PC_REG 7
- #define LINESIZE 121
- #define WORDSIZE 20
- /******* type *******/
- /* 虚拟机的指令类型,有三种 */
- typedef enum {
- opclRR, /* reg operands r,s,t */
- opclRM, /* reg r, mem d+s */
- opclRA /* reg r, int d+s */
- } OPCLASS;
- /* 虚拟机的汇编指令对应的OPCODE */
- typedef enum {
- /* RR instructions */
- opHALT, /* RR halt, operands are ignored */
- opIN, /* RR read into reg(r); s and t are ignored */
- opOUT, /* RR write from reg(r), s and t are ignored */
- opADD, /* RR reg(r) = reg(s)+reg(t) */
- opSUB, /* RR reg(r) = reg(s)-reg(t) */
- opMUL, /* RR reg(r) = reg(s)*reg(t) */
- opDIV, /* RR reg(r) = reg(s)/reg(t) */
- opRRLim, /* limit of RR opcodes */
- /* RM instructions */
- opLD, /* RM reg(r) = mem(d+reg(s)) */
- opST, /* RM mem(d+reg(s)) = reg(r) */
- opRMLim, /* Limit of RM opcodes */
- /* RA instructions */
- opLDA, /* RA reg(r) = d+reg(s) */
- opLDC, /* RA reg(r) = d ; reg(s) is ignored */
- opJLT, /* RA if reg(r)<0 then reg(7) = d+reg(s) */
- opJLE, /* RA if reg(r)<=0 then reg(7) = d+reg(s) */
- opJGT, /* RA if reg(r)>;0 then reg(7) = d+reg(s) */
- opJGE, /* RA if reg(r)>;=0 then reg(7) = d+reg(s) */
- opJEQ, /* RA if reg(r)==0 then reg(7) = d+reg(s) */
- opJNE, /* RA if reg(r)!=0 then reg(7) = d+reg(s) */
- opRALim /* Limit of RA opcodes */
- } OPCODE;
- /* 枚举执行结果 */
- typedef enum {
- srOKAY, /* 正确执行 */
- srHALT, /* 停止执行 */
- srIMEM_ERR, /* IMEM错误 */
- srDMEM_ERR, /* DMEM错误 */
- srZERODIVIDE /* 零除错误 */
- } STEPRESULT;
- /* 存储指令的值,iop是OPCODE,剩下三个是r,s,t */
- typedef struct {
- int iop;
- int iarg1;
- int iarg2;
- int iarg3;
- } INSTRUCTION;
- /******** vars ********/
- /* 指向只读指令存储区的指针 */
- int iloc = 0 ;
- /* 指向数据存储区的指针 */
- int dloc = 0 ;
- /* 是否跟踪程序执行情况 */
- int traceflag = FALSE;
- /* 是否需要打印出执行的指令数量 */
- int icountflag = FALSE;
- /* 只读指令存储区 */
- INSTRUCTION iMem [IADDR_SIZE];
- /* 数据存储区 */
- int dMem [DADDR_SIZE];
- /* 寄存器 */
- int reg [NO_REGS];
- /* 指令列表,用于在stdout上打印出程序执行情况之用,与enum OPCODE对应,其中的"????"则与相应的LIM值对应,无意义 */
- char *opCodeTab[] = {
- /* RR opcodes */
- "HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
- /* RM opcodes */
- "LD","ST","????",
- /* RA opcodes */
- "LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
- };
- /* 程序结果列表,用于在stdout上打印出程序执行情况之用,与enum STEPRESULT对应 */
- char * stepResultTab[] =
- {
- "OK",
- "Halted",
- "Instruction Memory Fault",
- "Data Memory Fault",
- "Division by 0"
- };
- /* 存储文件名 */
- char pgmName[20];
- /* 代码文件的FILE指针 */
- FILE *pgm ;
- /* 文件的每一行都存在这个数组里 */
- char in_Line[LINESIZE] ;
- /* 读取到当前文件的行数记录 */
- int lineLen;
- /* in_Line数组中的下标 */
- int inCol;
- /* 存储getNum()函数的结果 */
- int num ;
- /* 存储getWord()函数的结果 */
- char word[WORDSIZE] ;
- /* 存储getCh()函数的结果 */
- char ch ;
- /* 存储docomand()函数的执行结果,用于表示程序是否结束 */
- int done ;
- /*************************************************************************************
- * int opClass( int c ):根据c的值在OPCODE枚举型中查找指令的类型,有RR,RM,RA三种指令
- *************************************************************************************/
- int opClass( int c )
- {
- if ( c <= opRRLim)
- return ( opclRR );
- else if ( c <= opRMLim)
- return ( opclRM );
- else
- return ( opclRA );
- } /* opClass */
- /**************************************************************************************
- *void writeInstruction ( int loc ):向stdout上打印出程序的执行情况
- **************************************************************************************/
- void writeInstruction ( int loc )
- {
- printf( "%5d: ", loc) ;
- if ( (loc >;= 0) && (loc < IADDR_SIZE) )
- {
- printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
- switch ( opClass(iMem[loc].iop) )
- {
- case opclRR:
- printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
- break;
- case opclRM:
- case opclRA:
- printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
- break;
- }
- printf ("\n") ;
- }
- } /* writeInstruction */
- /*************************************************************************************
- * void getCh (void):在in_line数组中读取字符,如果到文件尾,就返回空字符,并且将结果存入ch中
- **************************************************************************************/
- void getCh (void)
- {
- if (++inCol < lineLen)
- ch = in_Line[inCol] ;
- else ch = ' ' ;
- } /* getCh */
- /**************************************************************************************
- * int nonBlank (void): 查找某行文件后面是否都是空格,如果是则设置ch=' '并且返回false,
- * 否则设置ch为第一个非空字符返回true
- ***************************************************************************************/
- int nonBlank (void)
- {
- while ((inCol < lineLen)
- && (in_Line[inCol] == ' ') )
- inCol++ ;
- if (inCol < lineLen)
- {
- ch = in_Line[inCol] ;
- return TRUE ;
- }
- else
- {
- ch = ' ' ;
- return FALSE ;
- }
- } /* nonBlank */
- /***************************************************************************************
- * int getNum (void):判断字符是否是数字,不是就返回false,否则返回true并且num中存储读入的数字
- ****************************************************************************************/
- int getNum (void)
- {
- int sign;
- int term;
- int temp = FALSE;
- num = 0 ;
- do {
- sign = 1;
- while ( nonBlank() && ((ch == '+') || (ch == '-')) )
- {
- temp = FALSE ;
- if (ch == '-')
- sign = - sign ;
- getCh();
- }
- term = 0 ;
- nonBlank();
- while (isdigit(ch))
- {
- temp = TRUE ;
- term = term * 10 + ( ch - '0' ) ;
- getCh();
- }
- num = num + (term * sign) ;
- } while ( (nonBlank()) && ((ch == '+') || (ch == '-')) ) ;
- return temp;
- } /* getNum */
- /****************************************************************************************
- *int getWord (void):判断后面紧接着的是否是符号,就是以字母或者数字开头的符号,是就返回true
- * 并且将该符号存入word数组之中,否则返回false
- ****************************************************************************************/
- int getWord (void)
- {
- int temp = FALSE;
- int length = 0;
- if (nonBlank ())
- {
- while (isalnum(ch))
- {
- if (length < WORDSIZE-1)
- word [length++] = ch ;
- getCh() ;
- }
- word[length] = '\0';
- temp = (length != 0);
- }
- return temp;
- } /* getWord */
- /*****************************************************************************************
- *int skipCh ( char c ):略过指定的字符,如果找不到这个字符那么返回false,否则返回true
- *****************************************************************************************/
- int skipCh ( char c )
- {
- int temp = FALSE;
- if ( nonBlank() && (ch == c) )
- {
- getCh();
- temp = TRUE;
- }
- return temp;
- } /* skipCh */
- /******************************************************************************************
- *int atEOL(void):是否到达行尾,是就返回非零值,否则返回零值
- ******************************************************************************************/
- int atEOL(void)
- {
- return ( ! nonBlank ());
- } /* atEOL */
- /*******************************************************************************************
- * int error( char * msg, int lineNo, int instNo):打印出错信息,其中msg是出错信息,
- * lineNo是行数,instNo是指令数
- *******************************************************************************************/
- int error( char * msg, int lineNo, int instNo)
- {
- printf("Line %d",lineNo);
- if (instNo >;= 0)
- printf(" (Instruction %d)",instNo);
- printf(" %s\n",msg);
- return FALSE;
- } /* error */
- /*******************************************************************************************
- * int readInstructions (void):读取代码文件进行处理
- *******************************************************************************************/
- int readInstructions (void)
- {
- /* op存储指令 */
- OPCODE op;
- /* 存储r,s,t */
- int arg1, arg2, arg3;
- /* loc是指令的位置, regNO是寄存器的位置,lineNO是代码中的行数 */
- int loc, regNo, lineNo;
- /* 清空寄存器 */
- for (regNo = 0 ; regNo < NO_REGS ; regNo++)
- reg[regNo] = 0 ;
- /* 不明白为什么这样做? */
- dMem[0] = DADDR_SIZE - 1 ;
- /* 清空数据区 */
- for (loc = 1 ; loc < DADDR_SIZE ; loc++)
- dMem[loc] = 0 ;
- /* 初始化指令存储区的OPCODE是opHALT */
- for (loc = 0 ; loc < IADDR_SIZE ; loc++)
- {
- iMem[loc].iop = opHALT ;
- iMem[loc].iarg1 = 0 ;
- iMem[loc].iarg2 = 0 ;
- iMem[loc].iarg3 = 0 ;
- }
- /* 初始化行数为0 */
- lineNo = 0 ;
- while (! feof(pgm)) /* 对文件进行逐行的读取操作,然后对每一行代码进行处理 */
- {
- /* 读入一行代码 */
- fgets( in_Line, LINESIZE-2, pgm ) ;
- /* 设置行的列号为0 */
- inCol = 0 ;
- /* 行数加一 */
- lineNo++;
- lineLen = strlen(in_Line)-1 ;
- /* 把行尾置为'\0',方便字符串操作 */
- if (in_Line[lineLen]=='\n')
- in_Line[lineLen] = '\0' ;
- else
- in_Line[++lineLen] = '\0';
- /* 如果指令不是空格或者注释 */
- if ( (nonBlank()) && (in_Line[inCol] != '*') )
- {
- /* 如果不是数字,就显示错误,因为指令都是以数字开始 */
- if (! getNum())
- return error("Bad location", lineNo,-1);
- /* 存储指令的位置 */
- loc = num;
- /* 大于指令存储区的大小 */
- if (loc >; IADDR_SIZE)
- return error("Location too large",lineNo,loc);
- /* 如果后面没有紧接着':',则显示出错 */
- if (! skipCh(':'))
- return error("Missing colon", lineNo,loc);
- /* 如果后面紧接着的不是符号,则显示出错 */
- if (! getWord ())
- return error("Missing opcode", lineNo,loc);
- /* 初始化为HALT指令 */
- op = opHALT ;
- /* 循环查找word指令对应的OPCODE,op就是在opCodeTab中对应的指令的下标 */
- while ((op < opRALim)
- && (strncmp(opCodeTab[op], word, 4) != 0) )
- op++ ;
- /* 没有找到对应的OPCODE,显示出错 */
- if (strncmp(opCodeTab[op], word, 4) != 0)
- return error("Illegal opcode", lineNo,loc);
-
- /* 调用opClass函数对指令进行分类,不同的指令处理不相同 */
- switch ( opClass(op) )
- {
- case opclRR : /* 处理RR指令,具体为什么会如下处理可以查看RR指令的格式 */
- /* 如果后面紧接着的不是数字或者数字是非法的就显示出错 */
- if ( (! getNum ()) || (num < 0) || (num >;= NO_REGS) )
- return error("Bad first register", lineNo,loc);
- arg1 = num;
- /* 如果后面没有紧跟着',',就显示出错 */
- if ( ! skipCh(','))
- return error("Missing comma", lineNo, loc);
- /* 如果后面紧接着的不是数字或者数字是非法的就显示出错 */
- if ( (! getNum ()) || (num < 0) || (num >;= NO_REGS) )
- return error("Bad second register", lineNo, loc);
- arg2 = num;
- /* 如果后面没有紧跟着',',就显示出错 */
- if ( ! skipCh(','))
- return error("Missing comma", lineNo,loc);
- /* 如果后面紧接着的不是数字或者数字对于RR命令是非法的就显示出错 */
- if ( (! getNum ()) || (num < 0) || (num >;= NO_REGS) )
- return error("Bad third register", lineNo,loc);
- arg3 = num;
- break;
- case opclRM : /* 处理RM指令,具体为什么会如下处理可以查看RM指令的格式 */
- case opclRA : /* 处理RA指令,具体为什么会如下处理可以查看RA指令的格式 */
- /* 如果后面紧接着的不是数字或者数字是非法的就显示出错 */
- if ( (! getNum ()) || (num < 0) || (num >;= NO_REGS) )
- return error("Bad first register", lineNo,loc);
- arg1 = num;
- /* 如果后面没有紧跟着','就显示出错 */
- if ( ! skipCh(','))
- return error("Missing comma", lineNo,loc);
- /* 如果后面没有紧跟着数字就显示出错 */
- if (! getNum ())
- return error("Bad displacement", lineNo,loc);
- arg2 = num;
- /* 如果后面没有紧跟着'('或者是','就显示出错 */
- if ( ! skipCh('(') && ! skipCh(',') )
- return error("Missing LParen", lineNo,loc);
- /* 如果紧跟的不是数字或者数字是非法的就显示出错 */
- if ( (! getNum ()) || (num < 0) || (num >;= NO_REGS))
- return error("Bad second register", lineNo,loc);
- arg3 = num;
- break;
- } /* switch ( opClass(op) ) */
- /* OK,读取一行代码结束,把指令存入指令存储区 */
- iMem[loc].iop = op;
- iMem[loc].iarg1 = arg1;
- iMem[loc].iarg2 = arg2;
- iMem[loc].iarg3 = arg3;
- } /* if ( (nonBlank()) && (in_Line[inCol] != '*') ) */
- } /* while (! feof(pgm)) */
- return TRUE;
- } /* readInstructions */
- /********************************************************************************************
- * STEPRESULT stepTM (void):根据指令内存区中的存储的指令逐步执行指令,并且返回执行结果
- ********************************************************************************************/
- STEPRESULT stepTM (void)
- {
- INSTRUCTION currentinstruction ;
- int pc ;
- int r,s,t,m ;
- int ok ;
- /* 从PC寄存器中读取下一条指令地址 */
- pc = reg[PC_REG] ;
- /* 如果小于零或者大于IADDR_SIZE,就是超过指令内存大小,就返回srIMEM_ERR错误 */
- if ( (pc < 0) || (pc >; IADDR_SIZE) )
- return srIMEM_ERR ;
- /* PC加一 */
- reg[PC_REG] = pc + 1 ;
- /* 从内存中根据PC地址值读取当前要执行的指令 */
- currentinstruction = iMem[ pc ] ;
-
- /* 调用opClass函数确定opcode的类型 */
- switch (opClass(currentinstruction.iop) )
- {
- case opclRR : /* 对于RR指令而言,opcode格式是opcode r, s, t */
- r = currentinstruction.iarg1 ;
- s = currentinstruction.iarg2 ;
- t = currentinstruction.iarg3 ;
- break;
-
- case opclRM : /* 对于RM指令而言,opcode格式是opcode r, d(s),而m = d + reg(s) */
- r = currentinstruction.iarg1 ;
- s = currentinstruction.iarg3 ;
- /* 对应RM指令中的m = d + reg[s],相当于变址寻址,这个地址用于访问数据区 */
- m = currentinstruction.iarg2 + reg[s] ;
- /* 如果地址是非法的(对于数据存储区而言),就返回一个srDMEM_ERR错误 */
- if ( (m < 0) || (m >; DADDR_SIZE))
- return srDMEM_ERR ;
- break;
- case opclRA : /* 对于RA指令而言,opcode格式是opcode r, d(s),而m = d + reg(s),m值最后存入相应的寄存器 */
- r = currentinstruction.iarg1 ;
- s = currentinstruction.iarg3 ;
- m = currentinstruction.iarg2 + reg[s] ;
- break;
- } /* case */
- /* 根据iop中存储的OPCODE来执行指令,每个case右边是指令的执行情况 */
- switch ( currentinstruction.iop)
- {
- case opHALT : /* RR halt, operands are ignored */
- printf("HALT: %1d,%1d,%1d\n",r,s,t);
- return srHALT ;
- /* break; */
- case opIN : /* RR read into reg(r); s and t are ignored */
- do{
- printf("Enter value for IN instruction: ") ;
- fflush (stdin);
- fflush (stdout);
- gets(in_Line);
- lineLen = strlen(in_Line) ;
- inCol = 0;
- ok = getNum();
- if ( ! ok )
- printf ("Illegal value\n");
- else
- reg[r] = num;
- } while (! ok);
- break;
- case opOUT : /* RR write from reg(r), s and t are ignored */
- printf ("OUT instruction prints: %d\n", reg[r] ) ;
- break;
- case opADD : /* RR reg(r) = reg(s)+reg(t) */
- reg[r] = reg[s] + reg[t] ;
- break;
- case opSUB : /* RR reg(r) = reg(s)-reg(t) */
- reg[r] = reg[s] - reg[t] ;
- break;
- case opMUL : /* RR reg(r) = reg(s)*reg(t) */
- reg[r] = reg[s] * reg[t] ;
- break;
- case opDIV : /* RR reg(r) = reg(s)/reg(t) */
- if ( reg[t] != 0 )
- reg[r] = reg[s] / reg[t];
- else
- return srZERODIVIDE ;
- break;
- /*************** RM instructions ********************/
- case opLD : /* RM reg(r) = mem(d+reg(s)) */
- reg[r] = dMem[m] ;
- break;
- case opST : /* RM mem(d+reg(s)) = reg(r) */
- dMem[m] = reg[r] ;
- break;
- /*************** RA instructions ********************/
- case opLDA : /* RA reg(r) = d+reg(s) */
- reg[r] = m ;
- break;
- case opLDC : /* RA reg(r) = d ; reg(s) is ignored */
- reg[r] = currentinstruction.iarg2 ;
- break;
- case opJLT : /* RA if reg(r)<0 then reg(7) = d+reg(s) */
- if ( reg[r] < 0 )
- reg[PC_REG] = m ;
- break;
- case opJLE : /* RA if reg(r)<=0 then reg(7) = d+reg(s) */
- if ( reg[r] <= 0 )
- reg[PC_REG] = m ;
- break;
- case opJGT : /* RA if reg(r)>;0 then reg(7) = d+reg(s) */
- if ( reg[r] >; 0 )
- reg[PC_REG] = m ;
- break;
- case opJGE : /* RA if reg(r)>;=0 then reg(7) = d+reg(s) */
- if ( reg[r] >;= 0 )
- reg[PC_REG] = m ;
- break;
- case opJEQ : /* RA if reg(r)==0 then reg(7) = d+reg(s) */
- if ( reg[r] == 0 )
- reg[PC_REG] = m ;
- break;
- case opJNE : /* RA if reg(r)!=0 then reg(7) = d+reg(s) */
- if ( reg[r] != 0 )
- reg[PC_REG] = m ;
- break;
- /* end of legal instructions */
- } /* case */
-
- /* 如果程序能够正常执行到这里,就返回执行正确的信息 */
- return srOKAY ;
- } /* stepTM */
- /********************************************************************************************
- *int doCommand (void):执行指令
- * *******************************************************************************************/
- int doCommand (void)
- {
- char cmd;
- int stepcnt=0, i;
- int printcnt;
- int stepResult;
- int regNo, loc;
- do { /* 读入执行虚拟机的命令行参数 */
- printf ("Enter command: ");
- fflush (stdin);
- fflush (stdout);
- gets(in_Line);
- lineLen = strlen(in_Line);
- inCol = 0;
- } while (! getWord ());
- cmd = word[0] ;
- switch ( cmd )
- {
- case 't' : /* 是否跟踪调试 */
- traceflag = ! traceflag ;
- printf("Tracing now ");
- if ( traceflag )
- printf("on.\n");
- else
- printf("off.\n");
- break;
- case 'h' : /* 打印出命令及相应功能列表 */
- printf("Commands are:\n");
- printf(" s(tep <n>; "\
- "Execute n (default 1) TM instructions\n");
- printf(" g(o "\
- "Execute TM instructions until HALT\n");
- printf(" r(egs "\
- "Print the contents of the registers\n");
- printf(" i(Mem <b <n>;>; "\
- "Print n iMem locations starting at b\n");
- printf(" d(Mem <b <n>;>; "\
- "Print n dMem locations starting at b\n");
- printf(" t(race "\
- "Toggle instruction trace\n");
- printf(" p(rint "\
- "Toggle print of total instructions executed"\
- " ('go' only)\n");
- printf(" c(lear "\
- "Reset simulator for new execution of program\n");
- printf(" h(elp "\
- "Cause this list of commands to be printed\n");
- printf(" q(uit "\
- "Terminate the simulation\n");
- break;
- case 'p' : /* 是否打印出执行的指令的步数 */
- icountflag = ! icountflag ;
- printf("Printing instruction count now ");
- if ( icountflag )
- printf("on.\n");
- else
- printf("off.\n");
- break;
- case 's' : /* 指定执行的步数 */
- if ( atEOL ())
- stepcnt = 1;
- else if ( getNum ())
- stepcnt = abs(num);
- else
- printf("Step count?\n");
- break;
- case 'g' : /* 执行指令一直到HALT */
- stepcnt = 1 ;
- break;
- case 'r' : /* 打印出寄存器中的内容 */
- for (i = 0; i < NO_REGS; i++)
- {
- printf("%1d: %4d ", i,reg[i]);
- if ( (i % 4) == 3 )
- printf ("\n");
- }
- break;
- case 'i' : /* 打印出只读指令存储区的内容(指令),也可以自己指定存储区的位置 */
- printcnt = 1 ;
- /* printcnt用于计数,计算总共要打印出多少行的内容,而iloc是指向这一段内存的指针 */
- if ( getNum ())
- {
- iloc = num ;
- if ( getNum ())
- printcnt = num ;
- }
- if ( ! atEOL ())
- printf ("Instruction locations?\n");
- else
- {
- while ((iloc >;= 0) && (iloc < IADDR_SIZE)
- && (printcnt >; 0) )
- {
- writeInstruction(iloc);
- iloc++ ;
- printcnt-- ;
- }
- }
- break;
- case 'd' : /* 打印出数据存储区的内容(指令),也可以自己指定存储区的位置 */
- printcnt = 1 ;
- /* printcnt用于计数,计算总共要打印出多少行的内容,而dloc是指向这一段内存的指针 */
- if ( getNum ())
- {
- dloc = num ;
- if ( getNum ())
- printcnt = num ;
- }
- if ( ! atEOL ())
- printf("Data locations?\n");
- else
- {
- while ((dloc >;= 0) && (dloc < DADDR_SIZE)
- && (printcnt >; 0))
- {
- printf("%5d: %5d\n",dloc,dMem[dloc]);
- dloc++;
- printcnt--;
- }
- }
- break;
- case 'c' : /* 清空虚拟机所有状态 */
- iloc = 0;
- dloc = 0;
- stepcnt = 0;
- for (regNo = 0; regNo < NO_REGS ; regNo++)
- reg[regNo] = 0 ;
- dMem[0] = DADDR_SIZE - 1 ;
- for (loc = 1 ; loc < DADDR_SIZE ; loc++)
- dMem[loc] = 0 ;
- break;
- case 'q' : /* 退出 */
- return FALSE;
- default : /* 未知命令 */
- printf("Command %c unknown.\n", cmd);
- break;
- } /* case */
- stepResult = srOKAY;
- if ( stepcnt >; 0 )
- {
- if ( cmd == 'g' )
- {
- stepcnt = 0;
- /* 当命令行参数是g的时候,就一直执行程序 */
- while (stepResult == srOKAY)
- {
- iloc = reg[PC_REG] ;
- /* 如果设置了跟踪标志,那么在stdout上打印出执行的指令 */
- if ( traceflag )
- writeInstruction( iloc ) ;
- stepResult = stepTM ();
- stepcnt++;
- }
- /* 打印出执行的指令数量 */
- if ( icountflag )
- printf("Number of instructions executed = %d\n",stepcnt);
- }
- else /* 否则根据stepResult中指定的步长执行指令 */
- {
- while ((stepcnt >; 0) && (stepResult == srOKAY))
- {
- iloc = reg[PC_REG] ;
- if ( traceflag )
- writeInstruction( iloc ) ;
- stepResult = stepTM ();
- stepcnt-- ;
- }
- }
- printf( "%s\n",stepResultTab[stepResult] );
- }
- return TRUE;
- } /* doCommand */
- /********************************************************************************************
- *int main( int argc, char * argv[] ):主函数
- ********************************************************************************************/
- int main( int argc, char * argv[] )
- {
- if (argc != 2)
- { printf("usage: %s <filename>;\n",argv[0]);
- exit(1);
- }
- strcpy(pgmName,argv[1]) ;
- if (strchr (pgmName, '.') == NULL)
- strcat(pgmName,".tm");
- pgm = fopen(pgmName,"r");
- if (pgm == NULL)
- { printf("file '%s' not found\n",pgmName);
- exit(1);
- }
- /* read the program */
- if ( ! readInstructions ())
- exit(1) ;
- /* switch input file to terminal */
- /* reset( input ); */
- /* read-eval-print */
- printf("TM simulation (enter h for help)...\n");
- do
- done = ! doCommand ();
- while (! done );
- printf("Simulation done.\n");
- return 0;
- }
复制代码 |
|