Mic1MMV is a simulator for the Mic-1 microarchitecture. You can use it to assemble and load IJVM assembly programs, and then step through the execution.
Mic1MMV is part of the student resources for the course textbook. I have posted a copy of the student resources here: tanenbaum_sco6.zip
Unzip this file, and navigate to the Mic1MMV/bin
directory. You should see
the files Mic1MMV_hr.jar
and Mic1MMV_lr.jar
. The hr
and lr
stand for
“high resolution” and “low resolution”.
If you are on the command line, run the high resolution version like so:
java -jar Mic1MMV_hr.jar
If you are in a GUI file browser, you should be able to double click on it to run it. If you run the high resolution version and it does not fit vertically on your screen, try the low resolution version.
Refer to Figure 4-11 in the text for the IJVM instruction set, and Figure 4-17 for the microprogram.
Open a new file in an editor, paste in the following text, and save it as
print_chars.jas
:
// this program displays all the visible printable ASCII values 33..126
.constant
one 1
start 33
stop 126
.end-constant
.main
LDC_W start
next: DUP
OUT
DUP
LDC_W stop
ISUB
IFEQ done
LDC_W one
IADD
GOTO next
done: POP
HALT
.end-main
In the simulator, select File -> Assemble / Load JAS File, and select the file you just created. If all goes well you should see this in the window that pops up:
IJVM Assembler...
assembly complete
Press Load to load the program. Before running the program, note a few things.
The constant pool begins with this:
00010000: 00000001
00010004: 00000021
00010008: 0000007e
These are the 3 constants that were defined in the assembly file (1, 33, and
126 in decimal). CPP has the value 0x4000
, and the first address in the
constant pool is 0x10000
. This is because CPP is a 4-byte word address, and
the addresses show in the constant pool section are byte addresses. 0x4000
times 4 is 0x10000
.
The stack addresses are organized the same way: SP and LV are word addresses, but the addresses shown in the Stack Area are byte addresses. The blue text Stack Area is the word pointed to by LV, and the red is the word pointed to by SP. The green values are the ones in between. I am not sure why the stack starts off with extra 0’s, but it does.
Now let’s run the the program. First, set the speed to IJVM, so that you can
step through at the assembly language level. This will make it easier to
understand at first. Now press the blue arrow three times. You should see the
stack has changed, and the top value of the stack is now 0x21
(33). This is
the result of the LDC_W start
instruction, which pushes the constant named
start
onto the stack. Now each time you press the blue arrow it will step
forward by 1 IJVM instruction (which may be numerous microinstructions).
I will walk you through one iteration of the program. After each instruction I
will show the stack from the address 0x20044
and up, with the highest
addressed value on top.
The first instruction is LDC_W start
. This pushes the constant named start
onto the stack, so the stack now looks like this:
0x00000021 (33)
The next instruction is DUP
. This instruction is preceded by the label
next
, which the program will jump to later to accomplish the loop. DUP
duplicates the top of the stack, so now the stack looks like this:
0x00000021 (33)
0x00000021 (33)
The next instruction is OUT
. Technically this instruction is not part of the
IJVM instruction set but it was added to the simulator to make output
easier. OUT
prints the character corresponding to the ASCII code of the top
of the stack, and pops the stack. 0x21
is the exclaimation point, so after
the OUT
instruction has executed you should see !
in the Output Console,
and the stack has become this:
0x00000021 (33)
DUP
duplicates the top of the stack again:
0x00000021 (33)
0x00000021 (33)
LDC_W stop
pushes stop
onto the stack:
0x0000007e (126)
0x00000021 (33)
0x00000021 (33)
ISUB
pops the top two values from the stack, subtracts them, and pushes the
result. 33 - 126 is -93, which in 2’s complement is 0xffffffa3
. Here’s the
stack now:
0xffffffa3 (-93)
0x00000021 (33)
IFEQ done
pops the stack and compares the value with 0. If it is 0, execution
will jump to the label done
, otherwise it continues. Since -93 is not zero,
execution moves on normally and this is the stack:
0x00000021 (33)
LDC_W one
adds 1 to the top of the stack:
0x00000001 (1)
0x00000021 (33)
IADD
adds the top two values and replaces them with the sum:
0x00000022 (34)
GOTO next
jumps execution up to the next
label, and the process starts over
again with 34 on the top of the stack. This process will repeat until the
character 126 (which is ~
). If you set the speed to Prog and press the blue
arrow, the program will continue execution without showing you the steps until
it halts. After running the entire thing you should see this in the Output
Console:
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
If you reset and set the speed to Clock, you can step through the program again at the microprogram level and see the individual cycles of the data path. SubClock speed will show you how the data propagates within each clock cycle.
This assignment came with the empty file every_other_letter.jas
. In this
file, write an IJVM assembly program that is very similar to the above program,
except that it only prints out every other lowercase letter like so:
acegikmoqsuwy
Look up an ASCII table online so you can figure out where to start and stop. You will need to increment the value of the character by 2 each iteration instead of 1.
Push your assembly program to git-keeper.