zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Tiny语言执行环境TM机源码

源码执行语言 环境 TM Tiny
2023-09-14 09:07:59 时间

TM机就是TINY语言编译器编译之后的汇编代码的执行环境。TM机的主要功能是将TM的汇编代码读入和执行,它具有一般计算机类似的精简指令级RISC。TM汇编语言和一般的Intel汇编语言差点儿相同,包含寄存器寻址、操作符等,非常easy理解。

一条典型的代码如:LD 0,10(1)。这里面10(1)就是寄存器1中地址为基址。10为偏移地址,寻址结果放入寄存器0。

三目操作符:MUL 0,1,0表示将寄存器1和寄存器2的相乘结果放入寄存器0.接下来開始一部分一部分的分析TM机的源码。

 TM源码例如以下:

/****************************************************/
/* 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
#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;

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,
   srDMEM_ERR,
   srZERODIVIDE
   } STEPRESULT;

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];

char * opCodeTab[]
        = {"HALT","IN","OUT","ADD","SUB","MUL","DIV","??

??

", /* RR opcodes */ "LD","ST","????

", /* RM opcodes */ "LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????

" /* RA opcodes */ }; char * stepResultTab[] = {"OK","Halted","Instruction Memory Fault", "Data Memory Fault","Division by 0" }; char pgmName[20]; FILE *pgm ; char in_Line[LINESIZE] ; int lineLen ; int inCol ; int num ; char word[WORDSIZE] ; char ch ; int done ; /********************************************/ int opClass( int c ) { if ( c <= opRRLim) return ( opclRR ); else if ( c <= opRMLim) return ( opclRM ); else return ( opclRA ); } /* opClass */ /********************************************/ 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) { if (++inCol < lineLen) ch = in_Line[inCol] ; else ch = ' ' ; } /* getCh */ /********************************************/ 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) { 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) { 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 ) { int temp = FALSE; if ( nonBlank() && (ch == c) ) { getCh(); temp = TRUE; } return temp; } /* skipCh */ /********************************************/ int atEOL(void) { return ( ! nonBlank ()); } /* atEOL */ /********************************************/ 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) { OPCODE op; int arg1, arg2, arg3; 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 ; 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 ; while (! feof(pgm)) { fgets( in_Line, LINESIZE-2, pgm ) ; inCol = 0 ; lineNo++; lineLen = strlen(in_Line)-1 ; 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); op = opHALT ; while ((op < opRALim) && (strncmp(opCodeTab[op], word, 4) != 0) ) op++ ; if (strncmp(opCodeTab[op], word, 4) != 0) return error("Illegal opcode", lineNo,loc); switch ( opClass(op) ) { case opclRR : /***********************************/ 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); if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) ) return error("Bad third register", lineNo,loc); arg3 = num; break; case opclRM : case opclRA : /***********************************/ 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; } iMem[loc].iop = op; iMem[loc].iarg1 = arg1; iMem[loc].iarg2 = arg2; iMem[loc].iarg3 = arg3; } } return TRUE; } /* readInstructions */ /********************************************/ STEPRESULT stepTM (void) { INSTRUCTION currentinstruction ; int pc ; int r,s,t,m ; int ok ; pc = reg[PC_REG] ; if ( (pc < 0) || (pc > IADDR_SIZE) ) return srIMEM_ERR ; reg[PC_REG] = pc + 1 ; 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] ; 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 instructions */ case opHALT : /***********************************/ printf("HALT: %1d,%1d,%1d\n",r,s,t); return srHALT ; /* break; */ case opIN : /***********************************/ 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 : printf ("OUT instruction prints: %d\n", reg[r] ) ; break; case opADD : reg[r] = reg[s] + reg[t] ; break; case opSUB : reg[r] = reg[s] - reg[t] ; break; case opMUL : reg[r] = reg[s] * reg[t] ; break; case opDIV : /***********************************/ if ( reg[t] != 0 ) reg[r] = reg[s] / reg[t]; else return srZERODIVIDE ; break; /*************** RM instructions ********************/ case opLD : reg[r] = dMem[m] ; break; case opST : dMem[m] = reg[r] ; break; /*************** RA instructions ********************/ case opLDA : reg[r] = m ; break; case opLDC : reg[r] = currentinstruction.iarg2 ; break; case opJLT : if ( reg[r] < 0 ) reg[PC_REG] = m ; break; case opJLE : if ( reg[r] <= 0 ) reg[PC_REG] = m ; break; case opJGT : if ( reg[r] > 0 ) reg[PC_REG] = m ; break; case opJGE : if ( reg[r] >= 0 ) reg[PC_REG] = m ; break; case opJEQ : if ( reg[r] == 0 ) reg[PC_REG] = m ; break; case opJNE : if ( reg[r] != 0 ) reg[PC_REG] = m ; break; /* end of legal instructions */ } /* case */ return srOKAY ; } /* stepTM */ /********************************************/ 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' : 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 ; 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 ; 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; /* break; */ default : printf("Command %c unknown.\n", cmd); break; } /* case */ stepResult = srOKAY; if ( stepcnt > 0 ) { if ( cmd == 'g' ) { stepcnt = 0; while (stepResult == srOKAY) { iloc = reg[PC_REG] ; if ( traceflag ) writeInstruction( iloc ) ; stepResult = stepTM (); stepcnt++; } if ( icountflag ) printf("Number of instructions executed = %d\n",stepcnt); } else { while ((stepcnt > 0) && (stepResult == srOKAY)) { iloc = reg[PC_REG] ; if ( traceflag ) writeInstruction( iloc ) ; stepResult = stepTM (); stepcnt-- ; } } printf( "%s\n",stepResultTab[stepResult] ); } return TRUE; } /* doCommand */ /********************************************/ /* E X E C U T I O N B E G I N S H E R E */ /********************************************/ 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; }