The goal of this lab is to practice implementing a virtual machine to interpret a pseudo-assembly language.
The new model of our virtual machine is out--- its main new feature is language-level support for fuction calls. Here are the concepts behind it:
When a function is called, the caller must
In the new model, there exactly 32 registers. The last three have a special purpose:
These can be manipulated like the other registers, but some of the new instructions read or modify them without them being stated. Here are the new instructions, with their numeric codes:
There is one other change. Now the second value in the file does not refer to the number of registers (since that's fixed in the new model) but rather it gives the initial value of the stack pointer-- where the stack frame for the "main" function ends. The frame pointer begins at zero---although the program could modify it to be something else, if there is a desire to differentiated between global addresses and the beginning of the call stack.
Make a new directory for this lab and copy the file from the appropriate course directory.
cp /cslab/class/cs245/labfifteenpt5/* .
You will find the source code for the version of the virtual
machine from class on friday, a (compiled) disassembler for the
new version, and a program written for the new version
(unknown
).
Disassemble the program unknown
.
Can you tell what it does?
Take a couple mintues to try to decipher it (you may want
to make a hard copy); if you don't make an progress, then
move on.
Once you run the program, it might be easier to
make sense of it.
Your main activity will be to update the virtual machine program to run programs in the expanded language. You will need to
Then test your program on the given program.
If you still don't know what it does, try changing the first
load to be something other than 5-- say, 4 or 6 or 7.
(This will mean changing the fourth line of the
file unknown
.)
Try writing an assembly program of your own. A fairly simply one would be something to compute the greatest common divisor. Remember gcd(a, 0) = a, and gcd(a, b) = gcd(b, a % b) if b is not 0.
You'll probably want to write the program in phases.
When I wrote unknown
, I started by using
"labels" instead of instruction positions for
jumps.
LOAD 5 r1 LOAD 0 r2 LOAD 1 r3 LOAD L1 r4 LOAD L2 r6 PSH 4 r5 WRLO 0 r1 JAL r4 POP r2 RELO 0 r5 PRN r5 HLT L1: RELO 0 r5 IF r5 r6 WRLO 0 r3 RET L2: SUB r5 r3 r7 WRLO 1 r5 WRLO 2 r29 PSH 4 r8 WRLO -1 r8 WRLO 0 r7 JAL r4 RELO 0 r7 RELO -1 r8 POP r8 RELO 2 r29 RELO 1 r5 MUL r5 r7 r8 WRLO 0 r8 RET
Then I counted off positions to determine what the labels where, and also replaced all the instructions and registers with plain numbers. Furthermore, I counted the number of instruction words.
84 1 5 1 1 0 2 1 1 3 1 31 4 1 41 6 14 4 5 17 0 1 12 4 15 2 16 0 5 8 5 9 L1: 16 0 5 7 5 6 17 0 3 13 L2: 4 5 3 7 17 1 5 17 2 29 14 4 8 17 -1 8 17 0 7 12 4 16 0 7 16 -1 8 15 8 16 2 29 16 1 5 5 5 7 8 17 0 8 13
Finally, I made every number appear on a line by itself (and I got rid of the labels).
84 0 1 5 1 1 0 2 1 1 3 1 31 4 1 41 6 14 4 5 17 0 1 12 4 15 2 16 0 5 8 5 9 16 0 5 7 5 6 17 0 3 13 4 5 3 7 17 1 5 17 2 29 14 4 8 17 -1 8 17 0 7 12 4 16 0 7 16 -1 8 15 8 16 2 29 16 1 5 5 5 7 8 17 0 8 13
Cat all your files in a typescript which also shows you running the programs. Turn in a hard copy.