一 简单介绍
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 <stdio.h> #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 }