8.19 |
(Computer Simulator) It may at first seem outrageous,
but in this problem you are going to build your own computer. No, you will
not be soldering components together. Rather, you will use the powerful technique
of software-based simulation to create a software model
of the Simpletron. You will not be disappointed. Your Simpletron simulator
will turn the computer you are using into a Simpletron, and you actually
will be able to run, test and debug the SML programs you wrote in Exercise
8.18. |
|
When you run your Simpletron simulator, it should begin by printing |
|
*** Welcome to Simpletron! ***
*** Please enter your program one instruction ***
*** (or data word) at a time. I will type the ***
*** location number and a question mark (?). ***
*** You then type the word for that location. ***
*** Type the sentinel -99999 to stop entering ***
*** your program. ***
|
|
Your program should simulate the Simpletron’s memory with a single-subscripted, 100-element array memory . Now assume that the simulator is running, and let us examine the dialog as we enter the program of Example 2 of Exercise 8.18: |
|
00 ? +1009
01 ? +1010
02 ? +2009
03 ? +3110
04 ? +4107
05 ? +1109
06 ? +4300
07 ? +1110
08 ? +4300
09 ? +0000
10 ? +0000
11 ? -99999
*** Program loading completed ***
*** Program execution begins ***
|
|
Note that the numbers to the right of each ? in the preceding dialog represent the SML program instructions input by the user. |
|
The SML program has now been placed (or loaded) into array memory . Now the Simpletron executes your SML program. Execution begins with the instruction in location 00 and, like C++, continues sequentially, unless directed to some other part of the program by a transfer of control. |
|
Use variable accumulator to represent the accumulator register. Use variable counter to keep track of the location in memory that contains the instruction being performed. Use variable operationCode to indicate the operation currently being performed (i.e., the left two digits of the instruction word). Use variable operand to indicate the memory location on which the current instruction operates. Thus, operand
is the rightmost two digits of the instruction currently being performed.
Do not execute instructions directly from memory. Rather, transfer the next
instruction to be performed from memory to a variable called instructionRegister . Then “pick off” the left two digits and place them in operationCode , and “pick off” the right two digits and place them in operand . When Simpletron begins execution, the special registers are all initialized to zero. |
|
Now let us “walk through” the execution of the first SML instruction, +1009 in memory location 00 . This is called an instruction execution cycle. |
|
The counter tells us the location of the next instruction to be performed. We fetch the contents of that location from memory by using the C++ statement |
|
instructionRegister = memory[ counter ];
|
|
The operation code and operand are extracted from the instruction register by the statements |
|
operationCode = instructionRegister / 100;
operand = instructionRegister % 100;
|
|
Now, the Simpletron must determine that the operation code is actually a read (versus a write, a load, etc.). A switch differentiates among the 12 operations of SML. |
|
In the switch statement, the behavior of various SML instructions is simulated as shown in Fig. 8.42 (we leave the others to the reader). |
|
|
|
The halt instruction also causes the Simpletron to print the
name and contents of each register, as well as the complete contents of memory.
Such a printout is often called a computer dump (and, no, a computer
dump is not a place where old computers go). To help you program your dump
function, a sample dump format is shown in Fig. 8.43. Note that a dump after
executing a Simpletron program would show the actual values of instructions
and data values at the moment execution terminated. To format numbers with
their sign as shown in the dump, use stream manipulator showpos . To disable the display of the sign, use stream manipulator noshowpos .
For numbers that have fewer than four digits, you can format numbers with
leading zeros between the sign and the value by using the following statement
before outputting the value: |
|
cout << setfill( '0' ) << internal;
|
|
|
|
Parameterized stream manipulator setfill (from header <iomanip >)
specifies the fill character that will appear between the sign and the value
when a number is displayed with a field width of five characters but does
not have four digits. (One position in the field width is reserved for the
sign.) Stream manipulator internal indicates that the fill characters should appear between the sign and the numeric value. |
|
Let us proceed with the execution of our program’s first instruction—+1009 in location 00 . As we have indicated, the switch statement simulates this by performing the C++ statement |
|
cin >> memory[ operand ];
|
|
A question mark (? ) should be displayed on the screen before the cin statement executes to prompt the user for input. The Simpletron waits for the user to type a value and press the Enter key. The value is then read into location 09 . |
|
At this point, simulation of the first instruction is complete. All that
remains is to prepare the Simpletron to execute the next instruction. The
instruction just performed was not a transfer of control, so we need merely
increment the instruction counter register as follows: |
|
++counter;
|
|
This completes the simulated execution of the first instruction. The
entire process (i.e., the instruction execution cycle) begins anew with the
fetch of the next instruction to execute. |
|
Now let us consider how to simulate the branching instructions (i.e.,
the transfers of control). All we need to do is adjust the value in the instruction
counter appropriately. Therefore, the unconditional branch instruction (40 ) is simulated in the switch as |
|
counter = operand;
|
|
The conditional “branch if accumulator is zero” instruction is simulated as |
|
if ( accumulator == 0 )
counter = operand;
|
|
At this point, you should implement your Simpletron simulator and run
each of the SML programs you wrote in Exercise 8.18. You may embellish SML
with additional features and provide for these in your simulator. |
|
Your simulator should check for various types of errors. During the program
loading phase, for example, each number the user types into the Simpletron’s
memory must be in the range -9999 to +9999 . Your simulator should use a while
loop to test that each number entered is in this range and, if not, keep
prompting the user to reenter the number until the user enters a correct
number. |
|
During the execution phase, your simulator should check for various serious
errors, such as attempts to divide by zero, attempts to execute invalid operation
codes, accumulator overflows (i.e., arithmetic operations resulting in values
larger than +9999 or smaller than -9999 ) and the like. Such serious errors are called fatal errors. When a fatal error is detected, your simulator should print an error message such as |
|
*** Attempt to divide by zero ***
*** Simpletron execution abnormally terminated ***
|
|
and should print a full computer dump in the format we have discussed
previously. This will help the user locate the error in the program. |