• Tiny语言执行环境TM机源码


    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 (" ") ; } } /* 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] = ''; 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 ",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]==' ') in_Line[lineLen] = '' ; else in_Line[++lineLen] = ''; 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 ",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 "); else reg[r] = num; } while (! ok); break; case opOUT : printf ("OUT instruction prints: %d ", 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. "); else printf("off. "); break; case 'h' : /***********************************/ printf("Commands are: "); printf(" s(tep <n> " "Execute n (default 1) TM instructions "); printf(" g(o " "Execute TM instructions until HALT "); printf(" r(egs " "Print the contents of the registers "); printf(" i(Mem <b <n>> " "Print n iMem locations starting at b "); printf(" d(Mem <b <n>> " "Print n dMem locations starting at b "); printf(" t(race " "Toggle instruction trace "); printf(" p(rint " "Toggle print of total instructions executed" " ('go' only) "); printf(" c(lear " "Reset simulator for new execution of program "); printf(" h(elp " "Cause this list of commands to be printed "); printf(" q(uit " "Terminate the simulation "); break; case 'p' : /***********************************/ icountflag = ! icountflag ; printf("Printing instruction count now "); if ( icountflag ) printf("on. "); else printf("off. "); break; case 's' : /***********************************/ if ( atEOL ()) stepcnt = 1; else if ( getNum ()) stepcnt = abs(num); else printf("Step count? "); 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 (" "); } break; case 'i' : /***********************************/ printcnt = 1 ; if ( getNum ()) { iloc = num ; if ( getNum ()) printcnt = num ; } if ( ! atEOL ()) printf ("Instruction locations? "); 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? "); else { while ((dloc >= 0) && (dloc < DADDR_SIZE) && (printcnt > 0)) { printf("%5d: %5d ",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. ", 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 ",stepcnt); } else { while ((stepcnt > 0) && (stepResult == srOKAY)) { iloc = reg[PC_REG] ; if ( traceflag ) writeInstruction( iloc ) ; stepResult = stepTM (); stepcnt-- ; } } printf( "%s ",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> ",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 ",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)... "); do done = ! doCommand (); while (! done ); printf("Simulation done. "); return 0; }


  • 相关阅读:
    Spring Boot项目配置RabbitMQ集群
    rabbitMQ第二篇:java简单的实现RabbitMQ
    SpringBoot启动和停止脚步
    SpringBoot实战之SpringBoot自动配置原理
    maven profile 多环境
    Mybatis根据配置文件获取session(多数据源)
    Mybatis的mapper注册
    MyBatis SqlSessionFactory的几种常见创建方式
    Result映射成对象和List
    JAVA反射的使用之ResultSet的自动转换
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5165443.html
Copyright © 2020-2023  润新知