(Exercise 8.18 Machine-Language Programming + Exercise 8.19 Computer Simulator)
Here comes the interesting part! I have created a virtual computer named Simpletron with C++! It is a simple machine that only has 100 memory locations, each can store a four digit signed decimal integers(-9999 to +9999). When running a program, the machine load the program to the start of its memory (location 00) and run the instruction stored in it one by one.
Although it is simple, we can still run program on it! Programs in Simpletron are witten in SML, which stands for Simpletron Machine Language. Each instruction written in SML occupies one memory location of Simpletron, thus, it is a signed four digit integer. The first two digits of each instruction are the operation code that specifies the operation to be performed(shown below). The last two digits are the operand, which are the address of the memory location. (Remember? There are 100 locations, which can be indexed 0 to 99)
Ok, now we have a brief knowledge of SML. We can try writing programs in SML now! (it is miserable, trust me XD)
The books provide some simple programs that can be written in SML. I have written down my programs below. Take a look at them if you are interested. You may also try to write a more complicated program yourself! You will miss C++ once you trying to program in SML though. LOL
Add sum until a negative number is entered
Location Number Instruction
00 +1011 Read N
01 +2011 Load N
02 +4110 Branch negative to 10
03 +2112 Store S
04 +1011 Read N
05 +2011 Load N
06 +4109 Branch negative to 09
07 +3012 Add S
08 +4003 Branch to 03
09 +1112 Write S
10 +4300 Halt
11 +0000 Variable N
12 +0000 Variable S
Add sum of seven numbers
Location Number Instruction
00 +1011 Read N
01 +2012 Load S
02 +3011 Add N
03 +2112 Store S
04 +2013 Load I
05 +3114 Subtract One
06 +2113 Store I
07 +4209 Branch Zero to 09
08 +4000 Branch to 00
09 +1112 Write S
10 +4300 Halt
11 +0000 Variable N
12 +0000 Variable S
13 +0007 Variable I
14 +0001 One
Find the largest number in N numbers
Location Number Instruction
00 +1018 Read N
01 +2018 Load N
02 +4217 Branch Zero to 17
03 +1019 Read Largest
04 +2018 Load N
05 +3121 Subtract One
06 +4216 Branch zero to 16
07 +2118 Store N
08 +2019 Load Largest
09 +1020 Read X
10 +3120 Subtract X
11 +4113 Branch negative to 13
12 +4004 Branch to 04
13 +2020 Load X
14 +2119 Store Largest
15 +4004 Branch to 04
16 +1119 Write Largest
17 +4300 Halt
18 +0000 Variable N
19 +0000 Variable Largest
20 +0000 Variable X
21 +0001 One
Okay, we have the program now. Wait! How do we run those programs? We don't have the Simpletron machine in reality! Don't be nervous, guys. I am going to show you how I write a Simpletron simulator with C++. Here is how it looks(the testing program is the same with the first one above):
The Simpletron machine has some register units to store neccessary information to run programs. We use an accumulator register to store the result of calculation, an instruction register to store the current instruction and a counter register to indicate the current location of execution. For example, when we need to add the integer at location 10 and the integer at location 11 together, we first load the first integer to the accumulator.(instruction:+2010) Then we add the second integer to the accumulator.(instruction:+3011) The result is now in the accumulator and we may store it at location 12 for later use.(instruction:+2112) Note that after each instruction, the value in the counter register is increased by 1, which tells the computer to run the instruction at the next memory location.
I created a SimpletronSimulator class to represent the virtual computer. And I used a lot of static const int to represent the operation code in the table above so that I can recognize different operation with a switch easily. Okay, enough talk. The details are all in the sourcecode. I promise that is is a very easy and clear implementation!
// Exercise 8.19 Computer Simulator
#include <iostream>
#include <iomanip>
using namespace std;
// to simulate a type of computer called Simpletron
class SimpletronSimulator
{
public:
SimpletronSimulator();
void printConsoleMessage();
void printErrorMessage();
void inputSMLProgram();
void executeSMLProgram();
void printRegisterAndMemoryDump();
private:
// memory
static const int memorySize = 100;
int memory[memorySize];
bool setMemory( int index ); // false when -99999 sentinel is entered
bool validInput( int input );
// registers
int accumulator;
int instructionCounter;
int instructionRegister;
int operationCode;
int operand;
// operation code
static const int READ = 10;
static const int WRITE = 11;
static const int LOAD = 20;
static const int STORE = 21;
static const int ADD = 30;
static const int SUBTRACT = 31;
static const int DIVIDE = 32;
static const int MULTIPLY = 33;
static const int BRANCH = 40;
static const int BRANCHNEG = 41;
static const int BRANCHZERO = 42;
static const int HALT = 43;
};
int main()
{
SimpletronSimulator simulator;
simulator.printConsoleMessage();
return 0;
}
SimpletronSimulator::SimpletronSimulator()
{
accumulator = 0;
instructionCounter = 0;
for( int i=0; i<100; i++ )
{
memory[i] = 0;
}
}
void SimpletronSimulator::printConsoleMessage()
{
cout << "*** Welcome to Simpletron! ***" << endl;
cout << "*** Please enter your program one instruction ***" << endl;
cout << "*** (or data word) at a time. I will type the ***" << endl;
cout << "*** location number and a question mark (?). ***" << endl;
cout << "*** You then type the word for that location. ***" << endl;
cout << "*** Type the sentinel -99999 to stop entering ***" << endl;
cout << "*** your program. ***" << endl << endl;
inputSMLProgram();
cout << endl;
cout << "*** Program loading completed ***" << endl;
cout << "*** Program execution begins ***" << endl;
executeSMLProgram();
cout << "*** Program execution completed ***" << endl;
cout << endl;
printRegisterAndMemoryDump();
}
void SimpletronSimulator::inputSMLProgram()
{
bool inputContinue = true;
for( int counter=0; inputContinue; counter++ )
inputContinue = setMemory(counter); // setMemory return false when -99999 is entered
}
void SimpletronSimulator::executeSMLProgram()
{
int temp; // for tempory use
do
{
// load necessary data into registers
instructionRegister = memory[instructionCounter];
operationCode = instructionRegister / 100; // first two digits as code
operand = instructionRegister % 100; // last two digits as location
switch( operationCode )
{
case READ:
cout << "? ";
cin >> temp;
memory[operand] = temp;
instructionCounter++;
break;
case WRITE:
cout << showpos << memory[operand] << endl;
instructionCounter++;
break;
case LOAD:
accumulator = memory[operand];
instructionCounter++;
break;
case STORE:
memory[operand] = accumulator;
instructionCounter++;
break;
case ADD:
accumulator += memory[operand];
instructionCounter++;
break;
case SUBTRACT:
accumulator -= memory[operand];
instructionCounter++;
break;
case DIVIDE:
accumulator /= memory[operand];
instructionCounter++;
break;
case MULTIPLY:
accumulator *= memory[operand];
instructionCounter++;
break;
case BRANCH:
instructionCounter = operand;
break;
case BRANCHNEG:
if( accumulator < 0 )
{
instructionCounter = operand;
}
else
{
instructionCounter++;
}
break;
case BRANCHZERO:
if( accumulator == 0 )
{
instructionCounter = operand;
}
else
{
instructionCounter++;
}
break;
case HALT:
break;
default:
break;
}
}
while( operationCode != HALT );
}
void SimpletronSimulator::printRegisterAndMemoryDump()
{
cout << setfill('0') << internal; // fill 0 between '+' and number
cout << "REGISTERS:" << endl;
cout << "accumulator\t\t\t"
<< showpos << setw(5) << accumulator << endl;
cout << "instructionCounter\t\t "
<< noshowpos << setw(2) << instructionCounter << endl;
cout << "instructionRegister\t\t"
<< showpos << setw(5) << instructionRegister << endl;
cout << "operationCode\t\t\t "
<< noshowpos << setw(2) << operationCode << endl;
cout << "operand\t\t\t\t " << setw(2) << operand << endl;
cout << endl << "MEMORY:" << endl;
cout << setfill(' ') << setw(2) <<' ';
for( int i=0; i<=9; i++ ) // column number
cout << ' ' << setw(5) << i;
cout << endl;
for( int i=0; i<=90; i+=10 ) // loop from 0 to 99
{
cout << noshowpos << setfill(' ') << setw(2) << i; // row number
cout << setfill('0') << showpos; // formating
for( int j=0; j<=9; j++ )
{
cout << ' ' << setw(5) << memory[i+j];
}
cout << endl;
}
}
bool SimpletronSimulator::setMemory( int index )
{
int input;
cout << setfill('0');
do // prompt again if not valid
{
cout << setw(2) << index << " ? ";
cin >> input;
}
while( !validInput(input) );
if( input == -99999 )
{
return false;
}
else
{
memory[index] = input;
return true;
}
}
bool SimpletronSimulator::validInput( int input )
{
// valid when input is a 4-digit number or -99999 sentinel
return ( ( input>=-9999 && input<=9999 ) || input==-99999 );
}
If you find any bugs or have any doubts, please feel free to contact me!