zoukankan      html  css  js  c++  java
  • 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;
    }
    

  • 相关阅读:
    七牛云上传博客
    .net 导入Excel
    liunx ln -s 软连接
    dos2unix 命令
    x-csrf-token
    设置git 不提交 修改权限的文件
    nginx 启动、重启、关闭
    命令行导入mysql数据
    mongo 相关命令
    laravel 安装完成后安装 vendor 目录
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3810169.html
Copyright © 2011-2022 走看看