现在的位置: 首页 > 综合 > 正文

简单的的SimpleTron(C语言实现,程序内部实现体验)

2013年08月15日 ⁄ 综合 ⁄ 共 9759字 ⁄ 字号 评论关闭

一 简单介绍

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
}		  




抱歉!评论已关闭.