一 简单介绍
Simpletron是一个简单的机器,它具有CPU,控制器,内存等体现,简单描述了计算机的基础与原理。Simpletron 只能运用于它能理解的唯一语言,即Simpletron 机器语言(简称SML)编写的程序。Simpletron 包含一个累加器(AC,一个" 特殊寄存器"),存放Simpletron 用于计算和处理的各种信息。
Simpletron 中的所有信息(包括指令和数据)全是按照"字"来处理的。字是带符号的4 位十进制数(例如8086为16位机器,其只能处理16位(两个字节,16个二进制位,4个十六进制数)数据指令),例如+3364,-1293,+0007,-0001,等等,假设SML指令的符号总是正号,但数据的符号可正可负。
Simpletron 带有100 个字的内存,并且这些字通过它们的位置编号00,01,…,99 被引用。内存中的每个位置可以是一条指令,或程序使用的一个数据值,或是未用到的内存。
在运行一个SML程序之前, 我们必须先把程序放置到内存。每个SML 程序的第一条指令(或语句)总是放在位置00处,之后的指令依顺序逐一存放,并且从00这个位置开始执行,执行亦是顺序执行,除非遇到转移命令。
对于每一个SML 指令,其前两位数字是操作码,指定要进行的操作。后两位数字是操作数(也称为地址码),是要操作的内存位置(可以是数据的地址,或操作码是转移命令时,操作数也可以是指令的地址)。已经十分形似现代机器的的指令,但现代机器有更多的寻址方式。操作码代表的操作
输入/输出操作#define READ 10 // 将数据读入到内存某个位置read
#define WRITE 11 // 将数据从内存写出屏幕write
载入和存储#define LOAD 20// 从内存加载到累加器load
#define STORE 21// 将累加器内容存储到指定内存store
算术运算
#define ADD 30// 累加器中的值加上指定内存的值addition
#define SUBTRACT 31// 累加器中的值减去指定内存的值subtract
#define DIVIDE 32// 累加器中值除以指定内存的值division
#define MULTIPLY 33// 累加器中的值乘以指定位置的值multiplication
控制转移
#define BRANCH 40// 转移到特定内存位置
#define BRANCHNEG 41// 如果累加器为负,转移到内存指定位置
#define BRANCHZERO 42// 如果累加器为零,转移到内存指定位置
#define HALT 43// 停止程序,完成任务
指令分析(加法)
00 +1008 将变量A读入08,执行这条指令时,将等待输入
01 +1009 将变量B读入09
02 +2008 将A加载到累加器
03 +3009 将累加器的值(A)加以B
04 +2110 将结果C存储到10(这一步很重要,如果不将结果保存则无法获得)
05 +1110 将C写到屏幕(输出设备)
06 +4300 停止程序
07 +0000 内存为空(未曾使用过)
08 +0000 A的内存
09 +0000 B的内存
10 +0000 C的内存
下面是内存与累加器的定义和初始化:
//SimpleTron的内存区
#define MEMORY_COUNTER 100
int memory[MEMORY_COUNTER];
//累加器的定义和初始化
int accumulator = +0000;
显然,有了内存,就有了存储指令的地方,但我们如何获取指令,并用对指令进行分析处理,以明确指令的操作和要使到数据值,这时我们需要一个指令寄存器(IR)进行指令存储(从内存取指令后,将指令放到指令寄存器,以便指令译码器对操作码的分析(ID))。
//指令寄存器的定义和初始化--用来从内存逐条加载保存指令
int instructionRegister = +0000;
并且对指令进行必要的统计
int structionCounter = 00;
下一步要将操作码和操作数分开来(在CPU控制下,操作码送往译码器,进行指令分析,操作数送往地址寄存器(AR,存放地址,通过地址总线与内存相连),或程序计数器(针对转移命令))
int operationCode = 00;
//操作数定义和初始化
int operand = 00;
以上是对主要寄存器的定义与初始化
程序之前进行必要的提示,我们将输出
* * * Welcome to Simpletron * * *
* * * Please enter your program one istruction * * *
* * * (or data word) at a time .I will type the * * *
* * * Location number and a question mark(?). * * *
* * * You then tupe the word for that location. * * *
* * * Type the sentinel -99999 to stop entering * * *
* * * You program. * * *
倒数第二句是以-99999结束输入,并打印内存等情况,这是为了为了更明确指令和数据的存储位置,将每个内存的情况打印出来,并对累加器及指令数目等情况明确(方便错误时的调试)。这部分可以放到程序设计的最后部分,值得说明的之前的-4300是停止程序指令,在内存的位置应该在-99999之前,并且,-99999只是必要的程序控制,并不是程序指令,所以指令计数时要忽略它。
下面是函数定义
指令的输入void enterInstruction(void);//指令的输入
当遇到-99999要提示变量数据的输入* * * Program loading completed * * *
* * * Program execution begins * * *
void loadRegister(void)
{
instructionRegister = memory[instructionCounter]; //load instruction to register
}
指令解释
void translateInstruction(void);//指令解释
获得操作码方法
operationCode = instructionRegister / 100;
获得操作数方法
operand = instructionRegister % 100;
并对操作码与操作数判断,if(operand < 0 OR operand >99),调用异常处理函数。
void carryInstruction(void); // 执行指令
这是一个大的switch语句
switch(operationCode)
case READ:
scanf("%d",&memory[operand]);
if(memory[operand]<-9999 || memory[operand]>9999)
{
exception(EXCEPTION_INPUT_DATA);
break;
}
instructionCounter++;
break;
case WRITE:
printf("%d\n",memory[operand]);
instructionCounter++;
break;
// …
注意到每次执行操作成功后都要对指令计数器加1
。
void computerDump(void);//对内存等情况打印
要进行适当的格式控制
void exception(ERROR error);//异常处理,程序应该有处理部分异常的能力,例如指令输入的格式控制
代码
//simpletron.c
//
#include
#define MEMORY_COUNTER 100 //counter of memory
#define READ 10
#define WRITE 11
#define LOAD 20
#define STORE 21
#define ADD 30
#define SUBTRACT 31
#define DEVIDE 32
#define MULTIPLY 33
#define BRANCH 40
#define BRANCHNEG 41
#define BRANCHZERO 42
#define HALT 43
/
int accumulator = +0000; //define accumulator and initialize to zero
int instructionCounter = 00; //define instruction counter and initialize to zero
int instructionRegister = +0000; //define register to load instruction and initialize
int operationCode = 00; //define operationCode and initialize to zero
int operand = 00; //define operand and initialize to zero
int memory[MEMORY_COUNTER]; //memory
//instrution of error
typedef enum{EXCEPTION_INPUT_DATA,
EXCEPTION_INSRUCTION,
EXCEPTION_ERROR_DIVIDED,
EXCEPTION_OUT_ACCUMULATOR,
EXCEPTION_ERROR_OPERAND
}ERROR;
//before
void enterInstruction(void);
void loadRegister(void);
void translateInstruction(void);
void carryInstruction(void);
void computerDump(void);
void exception(ERROR error);
//function of instruction
void enterInstruction(void)
{
printf("* * * Welcome to Simpletron * * *\n");
printf("* * * Please enter your program one istruction * * *\n");
printf("* * * (or data word) at a time .I will type the * * *\n");
printf("* * * Location number and a question mark(?). * * *\n");
printf("* * * You then tupe the word for that location. * * *\n");
printf("* * * Type the sentinel -99999 to stop entering * * *\n");
printf("* * * You program. * * *\n");
int temporary_i = 0;
while(1)
{
printf("%02d?",temporary_i); //output information to get instruction
scanf("%d",&memory[temporary_i]); //get instruction
if(memory[temporary_i] == -99999) //end of -99999
{
printf("* * * Program loading completed * * *\n");
printf("* * * Program execution begins * * *\n");
break;
}
temporary_i++; //add one
}
}
//function of load instruction to register
void loadRegister(void)
{
instructionRegister = memory[instructionCounter]; //load instruction to register
}
//function of translate instruction to oprationcode and oprand
void translateInstruction(void)
{
operationCode = instructionRegister / 100; //control accumulator get instruction code
operand = instructionRegister % 100; //control accumulator get operand
if(operand < 0||operand >99)
exception(EXCEPTION_ERROR_OPERAND);
}
//function of carry out struction
void carryInstruction(void)
{
switch(operationCode)
{
case READ: //read data from std intput
scanf("%d",&memory[operand]);
if(memory[operand]<-9999 || memory[operand]>9999)
{
exception(EXCEPTION_INPUT_DATA);
break;
}
instructionCounter++;
break;
case WRITE: //write data to std ouput
printf("%d\n",memory[operand]);
instructionCounter++;
break;
case LOAD: //add data to accumulator from memory
accumulator = memory[operand];
instructionCounter++;
break;
case STORE: //transfer data of accumulator to memory
memory[operand] = accumulator;
instructionCounter++;
break;
case ADD: //data of accumulator add to memory data
accumulator += memory[operand];
if(memory[operand]<-9999 || memory[operand]>9999)
{
exception(EXCEPTION_OUT_ACCUMULATOR);
break;
}
instructionCounter++;
break;
case SUBTRACT: //data of accumulator subtract memory data
accumulator -= memory[operand];
if(memory[operand]<-9999 || memory[operand]>9999)
{
exception(EXCEPTION_OUT_ACCUMULATOR);
break;
}
instructionCounter++;
break;
case MULTIPLY: //data of accumulator multiply memory data
accumulator *= memory[operand];
if(memory[operand]<-9999 || memory[operand]>9999)
{
exception(EXCEPTION_OUT_ACCUMULATOR);
break;
}
instructionCounter++;
break;
case DEVIDE: //data of accumulator divide memory data
accumulator /= memory[operand];
if(memory[operand] == 0)
{
exception(EXCEPTION_ERROR_DIVIDED);
break;
}
instructionCounter++;
break;
case BRANCH:
instructionCounter = operand;
break;
case BRANCHNEG: //if accumulator less than zero, //if accumulator equal to zero, transfer memory
if(accumulator < 0)
instructionCounter = operand;
else
instructionCounter++;
break;
case BRANCHZERO: //if accumulator equal to zero, transfer memory
if(accumulator == 0)
instructionCounter = operand;
else
instructionCounter++;
break;
case HALT: //if operation code equal to 43, break program
printf("* * * Simpletron execution terminated * * *\n");
break;
default: //carry out other instruction code
exception(EXCEPTION_INSRUCTION);
break;
}
}
//function of computer dump
void computerDump(void)
{
//
int temporary_i, temporary_j, temporary_k, temporary_l = 00, temporary_m = 00, temporary_n = 0;
printf("\n");
///
print the data of simpletron
printf("accumulator %d\n",accumulator);
printf("instructionCounter %d\n",instructionCounter);
printf("instructionRegister %d\n",instructionRegister);
printf("operationCode %d\n",operand);
printf("operand %d\n",operand);
printf("memory:\n"); //print memory data
printf("%2c",' ');
//control
for(temporary_i = 0; temporary_i < MEMORY_COUNTER / 10; temporary_i++)
{
printf("%8d",temporary_l);
temporary_l++;
}
printf("\n\n");
for(temporary_j = 0; temporary_j < MEMORY_COUNTER / 10; temporary_j++)
{
printf("%2d",temporary_m);
temporary_m += 10;
for(temporary_k = 0; temporary_k < MEMORY_COUNTER / 10; temporary_k++)
{
if(memory[temporary_n] == 0)
printf("%3c%c%c%c%c%c",' ','+','0','0','0','0');
else
printf("%8d",memory[temporary_n]);
temporary_n++;
}
printf("\n");
}
}
///
//carry exception of program
void exception(ERROR error)
{
switch(error)
{
case EXCEPTION_INPUT_DATA:
operationCode = HALT;
printf("* * * the input data lsee than-9999 or more than 9999 * * *\n");
break;
case EXCEPTION_ERROR_DIVIDED:
operationCode = HALT;
printf("* * * the divide equal to zero * * *\n");
break;
case EXCEPTION_INSRUCTION:
operationCode = HALT;
printf("* * * the instruction error * * *\n");
break;
case EXCEPTION_OUT_ACCUMULATOR:
operationCode = HALT;
printf("* * * the accumulator is... * * *\n");
break;
case EXCEPTION_ERROR_OPERAND:
operationCode = HALT;
break;
default:
break;
}
//TODO
}
///
//interface of program
void main(void)
{
while(1) //inorder to oher time to get instruction
{
enterInstruction(); //
while(1)
{
loadRegister(); //
translateInstruction(); //
carryInstruction();
if(operationCode == HALT) //
{
computerDump(); //
break;
}
}
int i;
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n");
printf("* * * enter 1 to again. * * *\n");
printf("* * * enter 0 to exit. * * *\n");
scanf("%d",&i);
if(i==0)
break;
}
//TODO
}