Included are assignments on key points from class and text regarding foundational concepts necessary for understanding standard computer operation.
machine
architecture described in the text is simple enough to be implemented in software by a
one page C++ program! The software merely simulates the operation of
the hypothetical computer CPU which produces the same results as if the
hypothetical CPU existed. Simulating the hypothetical hardware in software is
a truly powerful idea since programs can be written for the hypothetical
machine but executed by simulation software on a real computer. See the Hypothetical
Machine in C++ at the end of this document for the simulator software. Software for new hardware
is often implemented in this way while the hardware is still under development.How does the simulator or interpreter work? In fact, much like the hardware it simulates, both implement a Fetch/Execute cycle. Suppose we had written the following program instructions:
Z = Y + 921
The corresponding program would be as in Figure 1.
|
Figure 1 |
Address Instruction Mnemonic Comments 000 01005 LDA Y A = Y 001 20004 ADD 921 A = A + 921 002 02006 STA Z Z = A 003 30007 Jmp 007 GO TO Address 7 004 00921 921 00921 Constant 921 005 04800 Y 04800 Variable Y 006 00807 Z 00807 Variable Z 007 99000 HLT Halt Execution |
NOTE: The MNEMONIC column entries correspond to the INSTRUCTION column, so mnemonic Jmp 007 is stored as 30007 (JMP is code 30) at memory ADDRESS 003. Variable Y address is 005 so that mnemonic LDA Y instruction code is 01005 (LDA is code 01 and Y is at address 005). The constant 921 must also be stored in memory, at address 004.
To run this program, the simulator executes the fetch/execute cycle for the hypothetical machine. The execution starts by fetching the LDA Y instruction and executing. The simulator program simply implements the hypothetical machine fetch/execute cycle as below:
ALGORITHM:
Simply stated, a hardware CPU runs a program by repeatedly FETCH'ING one instruction from memory and EXECUTE'ING that instruction in an endless cycle. This is called the FETCH/EXECUTE cycle. To simulate the hardware CPU, the software simulator must implement this cycle as below.
1. Fetch instruction at PC by: MAR = PC MDR = Memory[ MAR ] IR = MDR 2. PC = PC + 1 PC = next instruction address 3. Decode instruction: OP = IR operation field Addr = IR address field 4. Execute operation OP. 5. Go to 1.
DATA:
Notice that the CPU architecture (internal memory: PC, IR, A, B, MDR, MAR) and external memory are simulated using variables to hold each register's data. We accurately represent the hypothetical CPU internal memory by:
PC 3 digits, holds address in range 000 to 999 of next instruction. IR 5 digits, holds instruction (2-digit operation and 3-digit operand). A, B 5 digits, holds numerical value in range -99999 to 99999. MAR 3 digits, holds address in range 000 to 999 of Memory index. MDR 5 digits, holds numerical value accessed to/from Memory[ MAR ]. Memory 5 digits, array indexed from 000 to 999, holds values -99999 to 99999.
A non-interactive simulator is also given below in C++ as an example.
Address Value 000 01005 001 20004 002 02006 003 30007 004 00921 005 04800 006 00807 007 99000 |
Note: Since the multiply instruction generates a 10 digit result and stores the most significant 5 digits in the A register and the least significant 5 digits in the B register, the result is in the B register. To assign variable U the final result, store the value of the B register to variable U. Choose any reasonable addresses for the variables R, S, T and U but note that the constant 6 will also have to be stored at a memory address.
1. Enter program
Enter the below program using Notepad or any other ASCII text editor. Add your name on the first line in the title. When saving the file, use HW1.ASM as the name. You should be able to copy and paste the following into NotePad or other word processor as an ASCII file (be certain that the extension is ASM and not TXT if saving in NotePad).
Title YOUR NAME Home Work 1 - Evaluate U = (R+6-T)*S
DATA Segment ;;Data Segment
R DW 100 ;; R = 100
S DW 8 ;; S = 8
T DW 1 ;; T = 1
U DW ? ;; U is uninitialized
DATA Ends ;; End of segment DATA
ALGORITHM Segment ;; Algorithm Segment
Assume Cs:ALGORITHM, Ds:DATA, Ss:SSeg
HW1 Proc Far ;; Procedure HW1
Mov Bx, Seg Data ;; Initialize DS register
Mov Ds, Bx ;; to address of data segment
Mov Ax, R ;; Ax = R
Add Ax, 6 ;; Ax = R+6
Sub Ax, T ;; Ax = R+6-T
Mov Dx, 1234h ;; Notice value of Dx after Mul below
Mul S ;; Dx:Ax = (R+6-T)*S
Mov U, Ax ;; U = (R+6-T)*S
Mov Ah, 4ch ;; Terminate process returning
Int 21h ;; to parent (Debugger or DOS)
HW1 Endp ;; End of procedure HW1
ALGORITHM Ends ;; End of segment ALGORITHM SSeg Segment STACK ;;Stack segment of 254 bytes
DB 254 dup(?)
SSeg Ends
End HW1 ;; End of file, start execution at HW1 |
2. Assemble
v:\common\user\c335\assembler Do once at command prompt.
ml /Fl hw1.asm Do each time program changed.
3. Execute
Hw1.Lst Microsoft (R) Macro Assembler Version 6.14.8444 08/15/02 15:09:01 YOUR NAME Home Work 1 - Evaluate U = (R+6-T)*S Page 1 - 1 Title YOUR NAME Home Work 1 - Evaluate U = (R+6-T)*S 0000 DATA Segment ;;Data Segment 0000 0064 R DW 100 ;; R = 100 0002 0008 S DW 8 ;; S = 8 0004 0001 T DW 1 ;; T = 1 0006 0000 U DW ? ;; U is uninitialized 0008 DATA Ends ;; End of segment DATA 0000 ALGORITHM Segment ;;Algorithm Segment Assume Cs:ALGORITHM, Ds:DATA, Ss:SSeg 0000 HW1 Proc Far ;; Procedure HW1 0000 BB ---- R Mov Bx, Seg DATA ;; Initialize DS register 0003 8E DB Mov Ds, Bx ;; to address of data segment 0005 A1 0000 R Mov Ax, R ;; Ax = R 0008 83 C0 06 Add Ax, 6 ;; Ax = R+6 000B 2B 06 0004 R Sub Ax, T ;; Ax = R+6-T 000F BA 1234 Mov Dx, 1234h ;; Notice value of Dx after Mul below 0012 F7 26 0002 R Mul S ;; Dx:Ax = (R+6-T)*S 0016 A3 0006 R Mov U, Ax ;; U = (R+6-T)*S 0019 B4 4C Mov Ah, 4ch ;; Terminate process returning 001B CD 21 Int 21h ;; to parent (Debugger or DOS) 001D HW1 Endp ;; End of procedure HW1 001D ALGORITHM Ends ;; End of segment ALGORITHM 0000 SSeg Segment STACK ;;Stack segment of 254 bytes 0000 00FE [ DB 254 dup(?) 00 ] 00FE SSeg Ends End HW1
Use the debugger to execute the Hw1.Exe file by entering:
debug hw1.exe
4. Debugging
The debugger will display a command prompt of a '-'. The four commands needed are:
- u - Unassemble the machine code. Lists the mnemonic that correspond to the machine code. ADD AX, +06 corresponds to 83C006 machine code.
u12C0:0000 BBBF12 MOV BX,12BF 12C0:0003 8EDB MOV DS,BX 12C0:0005 A10000 MOV AX,[0000] 12C0:0008 83C006 ADD AX,+06 12C0:000B 2B060400 SUB AX,[0004] 12C0:000F BA3412 MOV DX,1234 12C0:0012 F7260200 MUL WORD PTR [0002] 12C0:0016 A30600 MOV [0006],AX 12C0:0019 B44C MOV AH,4C 12C0:001B CD21 INT 21 12C0:001D C3 RET 12C0:001E BFB2E8 MOV DI,E8B2- r - Register view. Displays the registers and next instruction to execute.
rAX=0000 BX=0000 CX=002D DX=0000 SP=00FE BP=0000 SI=0000 DI=000 DS=12AF ES=12AF SS=12C2 CS=12C0 IP=0000 NV UP EI PL NZ NA PO NC 12C0:0000 BBBF12 MOV BX,12BF- p - Proceed by executing the next one or more instructions. The registers and next instruction to execute are displayed.
p2 AX=0000 BX=12BF CX=002D DX=0000 SP=00FE BP=0000 SI=0000 DI=0000 DS=12AF ES=12AF SS=12C2 CS=12C0 IP=0003 NV UP EI PL NZ NA PO NC 12C0:0003 8EDB MOV DS,BX AX=0000 BX=12BF CX=002D DX=0000 SP=00FE BP=0000 SI=0000 DI=0000 DS=12BF ES=12AF SS=12C2 CS=12C0 IP=0005 NV UP EI PL NZ NA PO NC 12C0:0005 A10000 MOV AX,[0000] DS:0000=0064- d - Dump memory. The d ds:0 command dumps memory pointed to by the DS register. Memory containing the program data variables has been dumped, variable S has been located and underlined in the following example.
d ds:0S 12BF:0000 64 00 08 00 01 00 00 00-00 00 00 00 00 00 00 00 d............... 12BF:0010 BB BF 12 8E DB A1 00 00-83 C0 06 2B 06 04 00 BA ...........+.... 12BF:0020 34 12 F7 26 02 00 A3 06-00 B4 4C CD 21 C3 BF B2 4..&......L.!... 12BF:0030 E8 B4 2A CD 21 98 51 52-8B F0 D1 E6 03 F0 8B CE ..*.!.QR........ 12BF:0040 A1 12 83 B6 03 57 E8 A9-25 5F 03 F1 B9 03 00 F3 .....W..%_...... 12BF:0050 A4 B0 00 AA 5A 59 C3 8A-D0 32 F6 B8 23 65 CD 21 ....ZY...2..#e.! 12BF:0060 C3 80 3E 27 D3 00 75 72-8B 36 D7 E2 32 D2 AC 0A ..>'..ur.6..2... 12BF:0070 C0 74 26 3C 2A 75 0F F6-C2 02 74 05 80 CA 01 EB .t&<*u....t.....
5. The IP register points to the NEXT instruction to be executed by the CPU at location cs:0005 in the Algorithm. To execute one instruction at a time and witness the effects on registers and memory press:
Execute instructions by pressing p until the instruction at address 0008 is displayed as below:p
12C0:0008 83C006 Add Ax, 6 Address Instruction Mnemonic |
6. Locating variables in the data segment
Variables correspond to a memory location, variable S corresponds to data segment location 0002 and 0003, since it is a word it occupies 2 bytes. The location of variable S in the data segment can be determined by examining the Hw1.Lst listing which contains the following information.
Use the debugger dump command, to examine variable S at location 0002-0003 count across the DATA pane row, starting at 0000 and counting to location 0002. Note that variable S = 0008 but is stored as 08 00 in memory backward as low high byte.:Location Value Variable
0002 0008 S DW 8 ;; S = 8
7. Continue to execute each instruction (by pressing p) until the next instruction to execute is at address 0019.
d ds:0Contents 12BF:0000 17 00 08 0001 00 00 00 Address 0000 0001 0002 0003 0004 0005 0006 0007 Variable S
AX=0348 BX=12BF CX=002D DX=0000 SP=00FE BP=0000 SI=0000 DI=0000 DS=12BF ES=12AF SS=12C2 CS=12C0 IP=0019 NV UP EI PL NZ NA PE NC 12C0:0019 B44C MOV AH,4C |
Alt PrtSc
Paste into WordPad or other word processor to print.
The program's execution effects on data has been completed and results appear in the DATA segment. You will need to locate the memory used by each variable and determine their values. The program has not executed to completion however. Up to this point the program has been executed under the control of the debugger, executing one instruction at a time. To allow the CPU to execute the remaining instructions to completion enter:
g - Go execute program. Starts execution at the next instruction. The following executes through the last instruction Int 21h which terminates the program.
g Program terminated normally |
q - Quit debugger.
q
- values of variables R-U in the data segment dump circled and identified as R-U as in Step 6.
- the FINAL values of variables R-U as the corresponding decimal values (remember that words are stored in reverse byte order in memory, 123416 is stored as 34 12).
The Assembler software used in Assignment 2 and the remainder of course homeworks can be downloaded and installed by the following instructions:
Assembler documentation can be downloaded from this Web site.
01004
20005
02006
30007
00921
04800
00807
99000
// Machine language interpreter for architecture of Runnion p. 19
#include <iomanip.h>
#include <stdlib.h>
typedef long WordSize;
typedef int AddressRange;
typedef int CodeSize;
WordSize Memory[ 1000 ], IR, A, B, MDR; // Machine architecture
AddressRange PC, MAR;
void Interpret() // Interpret program instructions stored in memory
{ WordSize Temp;
CodeSize OP;
AddressRange Addr;
cout << "PC OP Addr A B" << "\n"; A = 0; B = 0;
PC = 0;
while (1) { // Forever
MAR = PC;
MDR = Memory[MAR];
IR = MDR; // Fetch
cout << setw(2) << PC;
PC = PC + 1; // Increment PC
OP = IR / 1000; // Decode
Addr = IR % 1000;
cout << setw(4) << OP << setw(6) << Addr << setw(7) << A
<< setw(7) << B << "\n";
switch (OP) { // Execute OP
case 01 : MAR = Addr; // LDA Addr
MDR = Memory[ MAR ];
A = MDR;
break;
case 02 : MAR = Addr; // STA Addr
MDR = A;
Memory[ MAR ] = MDR;
break;
case 03 : { Temp = A; // XAB
A = B;
B = Temp;
break;
}
case 04 : A = 0; // CLA
break;
case 20 : MAR = Addr; // ADD Addr
MDR = Memory[ MAR ];
A = A + MDR;
break;
case 21 : MAR = Addr; // SUB Addr
MDR = Memory[ MAR ];
A = A - MDR;
break;
case 30 : PC = Addr; // JMP
break;
case 99 : exit(0); // HLT
}
}
}
void Load() // Load instructions into memory from file
{ char Line[80];
PC = 0;
cin >> dec >> IR; cin.getline(Line, 80, '\n');
while (cin) {
Memory[ PC ] = IR;
PC = PC + 1;
cin >> dec >> IR; cin.getline(Line, 80, '\n');
}
}
void main()
{ Load();
Interpret();
}