/*7.27b.c*/
/*继续语言设计*/
/*
构建一台计算机并称其为“Simpletron”。正如它的名字所表示的那样,
它只是一台简单的计算机,但是我们很快就会看到,它的能力还是很
强的。Simpletron唯一能够理解的语言是Simpletron机器语言
(Simpletrom Machine Language,简称SML),它只能够指向采用
SML编写的程序。
simpletron包含一个累加器(accumulator)---用于存放即将被simpletron
处理的信息的特殊的寄存器。在simpletron中处理的所以信息都是以子(word)
为单位。字是一个 有符号的4为十进制数,如:+3364,-1293,+0007,——0001
等。simpletron带有一个容量为100字的存储器(以下简称内存)。这些字可以
通过他们的地址(00,01---99)来访问。
在运行一个SML程序之前,需要将程序加载到内存中。每个SML程序的第一条指针
(或称语句)总是被存放在地址为00的内存单元中。
每一条采用SML编写的指令都是占据内存中的一个字(所以指令也是一个有符号的
4位十进制数)。我们假设SML指令的符号总是正号,但是数据的符号是可正可负
的。simpletron内存中的一个存储单元要么存储一条指令,要么存储一个数据。
要么是展示空闲(和未定义)的。
SML指令的头两个数字是用来表示操作类型的造作码(operation code)。sml
的各种操作码见图7.32
操作码---------------------含义--------------------------------
输入/输出操作
#define READ 10 从中断将一个字读入到内存指定单元中
#define WRITE 11 将内存指定单元中的一个字写到终端上
装入/存回操作
#define LOAD 20 将内存指定单元中的一个字装入累加器
#define STORE 21 从累加器将一个字村回到内存指定单元中
算术运算操作
#define ADD 31 将内存知道抵挡单元中的一个字与累加器中的字相加(结果存到累加器中)
#define SUBTRACT 31 将累加器中的字减去内存指定单元中的一个字(结果存到累加器中)
#define DIVIDE 32 将累加器中字除以内存指定单元中的一个字(结果存在累加器中)
#define MULTIPLY 33 将累加器中的字乘以内存指定单元中的字(结果留在累加器中)
控制转移操作
#define BRANCH 40 转移到内存指定单元
#define BRANCHNEG 41 如果累加器位负数。则转移到内存指定单元
#define BRANCHZERO 42 如果累加器位零,则转移到内存指定单元
#define HALT 43 停机---即程序完成了它的任务
-------------------------------------------------------
图7.32 Simpletron机器语言(SML)的操作码
SML指令的后两个数字是操作码(operand),它表示欲操作的数据字所在内存存储单元的地址。
举几个SML程序的列子。下面给出的SML程序从键盘上读取两个数,然后计算并打印它们的和。
--------------------------------------------
例程1
单元地址 存储的数据 对应的指令
00 +1007 (read a)
01 +1008 (read b)
02 +2007 (load a)
03 +3008 (add b)
04 +2109 (store c)
05 +1109 (write c)
06 +4300 (halt)
07 +0000 (variable a)
08 +0000 (variable b)
09 +0000 (result c)
-------------------------------------------
指令+1007从键盘上读取第一个数并将它存放在地址位07的内存单元(
事先已经被初始化位0)中,指令+1008从键盘上读取第二个数并将它
存放在地址位08的内存单元(实现已经被初始化位0)中,装入指令
+2007将第一个数送入累加器,加法指令3009将第二个数与累加器
中的数相加,并将记过存回累加器,事实上,所有的sml算术指令都将
它们的运算结果保留在累加器中,保存指令+2009将结果存入到地址为
09的内存单元(事先已经被初始化为0)中,读指令+1109将从09单元
读一个数并将其按照有符号的4为十进制数形式大于出来,停机指令
+4300结束程序的运行。
下面给出的SML程序从就按盘上读取两个数,然后比较它们的大小,最后大于其中
较大的那个数,指令+4107是一个条件转移指令,它的用途类似c语言的if语句。
-----------------------------------------------
例程2
单元地址 存储的数据 对应的指令
00 +1009 (read a)
01 +1010 (read b)
02 +2009 (load a)
03 +3110 (subtract b)
04 +4107 (branch negative to 07)
05 +1109 (write a)
06 +4300 (halt)
07 +1110 (write b)
08 +0000 (halt)
09 +0000 (variable a)
10 +0000 (variable b)
11
-------------------------------------------
现在请编写三个SML程序来分别完成一下任务。
a)用一个标记控制循环来从键盘上读入10个正数,然后计算并打印它们的和
b)用一个计数控制循环来从键盘上读入7个数,这些书有的正数也有负数,然后计算并打印它们的和
c)从键盘上读取若干个数,然后比较它们的大小,最后打印其中最大的那个数。
读入的第一个数用来指明将要比较的数据的个数。
另外一篇文章完成这三个问题,这里搭建好运行的环境
文章后面附上,此次练习的答案
*/
#include<stdio.h>
#define SIZE 100
#define FLAG -9999
/*打印内存*/
void printmemory(int m[], int accumulator, int instructionCounter,
int instructionRegister, int operationCode, int operand);
int errZero(int operand);/*除0错误*/
int errAccumulator(int accumulator);/*累加器溢出错误*/
int erroperandCode(int operationCode);/*操作码错误*/
/*程序从main开始执行*/
int main()
{
/*打印输出*/
printf("欢迎来到Simpletron\n");
/*新建数组memory并初始化*/
int memory[SIZE] = { 0 };
/*寄存器值初始化*/
int accumulator = 0; //累加器
int instructionCounter = 0; /*内存编号--数组下标*/
int instructionRegister = 0; /*'word'*/
int operationCode = 0; /*操作码*/
int operand = 0; /*位置编号*/
/*打印内存*/
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
printf("\n\n");
/*将SML程序加载到内存----数组memory*/
do
{
do
{
printf("%02d ? +", instructionCounter);
scanf("%d", &memory[instructionCounter]);
if (memory[instructionCounter] > 9999 || memory[instructionCounter] < FLAG)
{
printf("输入错误,请重新输入!\n");
}
} while (memory[instructionCounter] > 9999 || memory[instructionCounter] < FLAG);
++instructionCounter;
} while (memory[instructionCounter - 1] != FLAG);
printf("\n*****程序加载完成*****\n");
/*打印内存*/
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
printf("\n***程序开始执行***\n");
/*开始执行程序*/
instructionCounter = 0;
do
{
instructionRegister = memory[instructionCounter];
operationCode = instructionRegister / 100;
if (erroperandCode(operationCode) == 0)
{
operationCode = 43;
printf("\n****操作码错误****\n***程序终止执行!\n");
}
operand = instructionRegister % 100;
/*操作选择*/
switch(operationCode)
{
/*读取*/
case 10:
{
printf("?");
scanf("%d", &memory[operand]);
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
/*打印*/
case 11:
{
printf("%d \n", memory[operand]);
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
/*加载*/
case 20:
{
accumulator = memory[operand];
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
/**/
case 21:
{
memory[operand] = accumulator;
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
/*加法*/
case 30:
{
accumulator += memory[operand];
if (errAccumulator(accumulator) == 0)
{
operationCode = 43;
printf("\n***累加器溢出错误***\n***程序将终止执行!\n");
break;
}
else
{
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
}
/*减法*/
case 31:
{
accumulator -= memory[operand];
if (errAccumulator(accumulator) == 0)
{
operationCode = 43;
printf("\n***累加器溢出错误***\n***程序将终止执行!\n");
break;
}
else
{
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
}
/*除法*/
case 32:
{
accumulator /= memory[operand];
if (errZero(operand) == 0)
{
operationCode = 43;
printf("\n***累加器溢出错误***\n***程序将终止执行!\n");
break;
}
else
{
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
}
/*乘法*/
case 33:
{
accumulator *= memory[operand];
if (errAccumulator(accumulator) == 0)
{
operationCode = 43;
printf("\n***乘数为0***\n***程序将终止执行!\n");
break;
}
else
{
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
}
/*jmp*/
case 40:
{
instructionCounter = operand;
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
//++instructionCounter;
break;
}
/*累加器为负数,跳转*/
case 41:
{
if (accumulator < 0)
{
instructionCounter = operand;
break;
}
else
{
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
}
/*acc==zero jmp */
case 42:
{
if (accumulator == 0)
{
instructionCounter = operand;
break;
}
else
{
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
}
case 43:
{
instructionCounter = operand;
printf("暂停\n");
printmemory(memory, accumulator, instructionCounter,
instructionRegister, operationCode, operand);
++instructionCounter;
break;
}
/*默认*/
default:
break;
};
} while (operationCode != 43);
return;
}
void printmemory(int m[], int accumulator, int instructionCounter,
int instructionRegister, int operationCode, int operand)
{
printf("REGISTERS:\n");
printf("accumulator %+05d\n", accumulator);
printf("instructionCounter %02d\n", instructionCounter);
printf("instructionRegister %+05d\n", instructionRegister);
printf("operationCode %02d\n", operationCode);
printf("operand %02d\n\n", operand);
printf("MEMORY:\n");
printf("\t0 1 2 3 4 5 6 7 8 9\t");
for (int i = 0; i < 100; i++)
{
if (i % 10 == 0)
{
printf("\n");
printf("%2d ", i);
}
printf("%+05d ", m[i]);
}
printf("\n");
}
/*操作码错误*/
int erroperandCode(int operationCode)
{
if (operationCode == 10 || operationCode == 11 ||
operationCode == 20 || operationCode == 21 ||
operationCode == 30 || operationCode == 31 ||
operationCode == 32 || operationCode == 33 ||
operationCode == 40 || operationCode == 41 ||
operationCode == 42 || operationCode == 43)
return 1;
else
return 0;
}
/*除0错误*/
int errZero(int operand)
{
{
printf("\n除零错误\n");
}
return operand;
}
/*累加器溢出错误*/
int errAccumulator(int accumulator)
{
if (accumulator > 9999 || accumulator < -9999)
{
return 0;
}
else
return -1;
}
第一题的答案SML语言用一个标记控制循环来从键盘上读入10个正数,然后计算并打印它们的和_zhyjhacker的博客-CSDN博客