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 ("\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;
}
Tiny语言执行环境TM机源码的更多相关文章
- APP加固技术历程及未来级别方案:虚机源码保护
传统App加固技术,前后经历了四代技术变更,保护级别每一代都有所提升,但其固有的安全缺陷和兼容性问题始终未能得到解决.而下一代加固技术-虚机源码保护,适用代码类型更广泛,App保护级别更高,兼容性更强 ...
- Crackme006 - 全新160个CrackMe学习系列(图文|视频|注册机源码)
知乎:逆向驿站 原文链接 CrackMe006 | 难度适中适合练手 |160个CrackMe深度解析(图文+视频+注册机源码) crackme006,依然是delphi的,而且没壳子,条线比较清晰, ...
- PHP-Yii执行流程分析(源码)
转自:http://www.cnblogs.com/zhanghaoyong/articles/2659846.html 一 目录文件 |-framework 框架核心库 |--base ...
- 23 使用环境 UsageEnvironment——Live555源码阅读
23 使用环境 UsageEnvironment——Live555源码阅读(三)UsageEnvironment 23 使用环境 UsageEnvironment——Live555源码阅读(三)Usa ...
- AOP执行增强-Spring 源码系列(5)
AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...
- 【CC2530入门教程-增强版】基础技能综合实训案例(基础版)-上位机源码
[CC2530入门教程-增强版]基础技能综合实训案例(基础版)-上位机源码 广东职业技术学院 欧浩源 一.需求分析 按照指定参数打开串口,与测控终端建立数据传输通道,并根据应用要求实现程序逻辑,具体 ...
- 生成MyEclipse6.5&7.5&8.5 注册机源码
分类: java技术2010-09-30 21:46 26638人阅读 评论(6) 收藏 举报 myeclipsejavastringimportinputbyte 生成MyEclipse8.5注册码 ...
- Go语言GC实现原理及源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/475 本文使用的 Go 的源码1.15.7 介绍 三色标记法 三色标 ...
- ubuntu配置android开发环境和编译源码遇到的一些问题
---------------------------------------------环境变量设置--------------------------------------------- 1.设 ...
随机推荐
- ASP.NET中 分析器错误:发现不明确的匹配
这是一个不好的代码习惯引起的发布后运行时的问题.错误原因为.net2.0无法正确识别服务器控件和变量的大小写区别,但是这个错误只有在iis中体现,在文件系统的调试中没有发生. 错误信息 引发错误的参考 ...
- 简单实现图片间的切换动画 主要用到ViewPager
简单实现图片间的切换动画 主要用到ViewPagerViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view.ViewPager类需要一个PagerAdapter适 ...
- 一种实现C++反射功能的想法(一)
Java的反射机制很酷, 只需知道类的名字就能够加载调用. 这个功能很实用, 想象一下, 用户只需指定类的名称, 就可以动态绑定类型, 而且只需通过字符串指定, 字符串的使用可以使得用户的修改只需修改 ...
- 设置windows窗口ICON 【windows 编程】【API】【原创】
1. ICON介绍 最近开始接触windows 编程,因此将自己所接触的一些零散的知识进行整理并记录.本文主要介绍了如何更改windows对话框窗口的ICON图标.这里首先介绍一下windows IC ...
- HTML5手机开发——滚动和惯性缓动
1. 滚动 以下是三种实现方式: 1) 利用原生的css属性 overflow: scroll div id= parent style = overflow:scroll; divid='conte ...
- [jQuery编程挑战]003 克隆一个页面元素及其相关事件
挑战: a) 绑定一个点击方法到这个div,点击后此元素会淡出消失 b) 同时克隆一个新的div元素到页面,元素内容是前面div文字内容反向书写(即,sgatbg olleh),同样也具有上面的点击事 ...
- Yii2的相关学习记录,下载Yii2(一)
原先学习过Yii1的相关知识,虽然也是半懂不懂的,但稍微的结构是了解的.现在利用晚上的时间学习下Yii2的使用,打算建一个后台管理系统,这里记录下,以免自己以后忘记. 目前已看一部分Yii2的权威指南 ...
- python函数参数的pack与unpack
python函数参数的pack与unpack 上周在使用django做开发的时候用到了mixin(关于mixin我还要写一个博客专门讨论一下,现在请参见这里),其中又涉及到了一个关于函数参数打包(pa ...
- Java高精度学习第一弹
为了快速解决高精度问题,总算是要来接触java了,算上这学期要开java的课了,好好学习吧! 拿来练手的是hdu的1002,高精度加法. import java.util.*; import java ...
- Eclipse+Pydev +Django搭建开发环境时容易出错的几点
1.注意安装的软件和系统的位数是否匹配. 2.安装Django框架的时候注意是否安装了setuptools工具.在Python中,安装第三方模块,是通过setuptools这个工具完成的.Python ...