Lab 6: Hmmm: Assembly!
~30 points, in files named hw6pr1a.hmmm, hw6pr1b.hmmm, and hw6pr1c.py
There are two problems and three files for this Hmmm lab. All are in the Hmmmwork6 starter folder ... Submission: As a result, you'll submit your hw6pr1a.hmmm, hw6pr1b.hmmm, and hw6pr1c.py files to GradescopeStarter Files!
Start by downloading the starter files, Hmmmwork6.zip from this link. For reference, Here is the HMMM documentation: all of the instructions in the Hmmm language. You will want to unzip the files and choose File ... Open ... in order to open the example1.hmmm file. Here's a screenshot: To try it, start ipython and then run hmmm example1.hmmm .- You'll need to be in the Hmmmwork6 directory.
- Keep the files together! Use cd to move into that directory, Hmmmwork6
- Important note: Remember to include
hmmm
in yourrun
command.- If you type run example1.hmmm -- without the hmmm after the run -- you'll get an error message showing Python's confusion!
Hmmm - Assembly Language!
This lab is all about programming in assembly language on a small computer model called Hmmm, the "Harvey Mudd Miniature Machine". There are three parts:- First we give you a bit of background. This short preamble will help you avoid a lot of potential pitfalls.
- Next, you're asked to write a Hmmm program that counts down to zero, starting from the cube of a positive input.
- The final part asks you to write a pseudorandom-number generator in Hmmm…
Introduction to assembly language
Although the Hmmm model is not a physical computer, its design is fundamentally very similar to that of modern real computers. Why not use a "real" computer? It's not worth learning the details of a real processor's instruction set: all of them are weighed down with lots of stuff that's not essential. (DNA shouldn't feel so bad!) Those many details are machine-specific: they don't apply to other computers. The instructions in Hmmm are a subset common to all processors. Hmmm has about 20 instructions. Modern computers typically have between twice and twenty times as many instructions. Engineering 85 (E85), a wonderful course taken by all engineering and many computer science students, will have you program in a real assembly language similar to Hmmm but with a larger (and more complicated) set of instructions.Why program in assembly language?
XKCD's reason
When a computer is first built, all it can do is execute machine-language instructions written in binary. Programming in this binary machine language is a pain! Therefore, the first thing that the designers of a computer (such as Hmmm) typically do is write an "assembler." With the assembler, programmers can now write programs with instructions such as
add
, jump
, and the others in Hmmm. The assembler converts
these instructions into their corresponding binary equivalents,
aka the "machine language" that the computer's circuits execute.
Once an assembler exists, the next step is to use assembly language to write more powerful
languages such as Python.
Don't worry—we won't ask you to implement Python in Hmmm! But
writing a few short assembly-language programs will give you a sense
of how one would start building such tools in the processor's native
language.
There's another reason for understanding assembly language.
Whenever you run a program in Python (or Java or C or…), that
program is ultimately
compiled (translated) into assembly or machine language so that the
computer can run
it. Learning to program in assembly language will allow you to
understand what's really going on inside the machine when your
program is run.
What's the difference between registers and memory?
Hmmm has 16 registers namedr0
through r15
, and 256 memory locations ("RAM").
A real processor might have have (about) the same
number of registers as Hmmm—maybe a couple of times
bigger—but would have "lots and lots" of RAM
memory—typically on the order of millions or billions of memory
locations that it could access.
Registers are where the computer actually does
its computation. Registers are the limited amount of data the
computer can keep in its "head."
RAM memory is where all of the other
data—and the program itself—are located. Think of RAM as a
"notebook" where the computer keeps lots of information that it can't
otherwise remember.
Keep in mind that the
actual program is located in memory and that the computer fetches one
instruction at a time from that RAM memory into its "brain"
(registers) so that it can
actually execute that instruction. This process of fetching instructions
from memory to execute on the processor is known as the Von Neumann
architecture. All modern computers use the Von Neumann architecture.
A closer look at Hmmm instructions
Each instruction typically tells the computer to do something with its registers (add numbers, etc). When that instruction is done, the computer fetches the next instruction from memory. By convention, the program resides in memory beginning at memory location 0. As in most computers, most Hmmm instructions "operate" on registers. If you look over your class notes, you'll see there are instructions such asadd
that take
three registers as arguments, e.g.,
add r3 r1 r2The values in the right two registers,
r1
and r2
,
are added together and the result is stored in the left-side register r3
.
This instruction is Python's r3 = r1 + r2.
Similarly, the sub
(subtract), mul
(multiply), and many other
instructions operate entirely on registers.
There are
exceptions! The most important are jumpn
, addn
, and setn
. Note that each
of these instructions ends in the letter n. This means that each takes
a raw number
as an argument. For instance, the number supplied to the jumpn
instruction
indicates the line
to which the program will jump next. Jumpn's relatives jltzn,
jgtzn, jnezn, and jeqzn all accept a register
and a raw number. For example,
jltzn r2 42 will jump to line 42 only if the value in register r2 is less than zero.
Feeding raw numbers into the instructions addn and loadn works in a very
similar manner. Simply put, the command addn r5 42
adds the number 42
to the pre-existing
contents of register r5
and then stores the result back in register r5
.
Note that
the instruction addn rX -1 is an easy way to subtract 1 from a register!
The instruction
setn r3 42
simply puts the number 42
into register
r3—this is also useful….
Let's get started with Hmmm!
Downloading and running Hmmm
To get started running Hmmm, you will need to download the following zipped folder:- Hmmmwork6.zip, the folder with all of the files needed—including hw6pr1a.hmmm and hw6pr1b.hmmm and hw6pr1c.py
Hmmmwork6
folder with several files
in it.
Try it with example1.hmmm
- Try Hmmm out by cd'ing into the Hmmmwork6 folder (for this term) that you downloaded and unzipped.
- Then, run the usual command at the command-line: ipython
- Then, type run hmmm hw6pr1a.hmmm to run Hmmm itself. Hmmm will assemble and run hw6pr1a.hmmm.
example1.hmmm
looks like:
# Example1 is an example program that # (1) asks the user for two inputs # (2) computes the product of the inputs # (3) prints out the result (with write) # (4) stops 00 read r1 # get number from user to r1 01 read r2 # ditto, for r2 02 mul r3 r1 r2 # r3 = r1 * r2 03 write r3 # print what's in r3 04 halt # stop
After you type run hmmm hw6pr1a.hmmm, you should see something like this:
---------------------- | ASSEMBLY SUCCESSFUL | ---------------------- 0 : 0000 0001 0000 0001 00 read r1 # get number from user 1 : 0000 0001 0000 0010 01 write r1 # print the value of r1 2 : 0101 0001 0000 0001 02 addn r1 1 # add 1 to r1 3 : 1011 0000 0000 0001 03 jumpn 01 # jump to line 01 4 : 0000 0000 0000 0000 04 halt # never halts! [use ctrYou will then see:
Enter number:Things have worked and the program is running!
- Enter 14 or another number (only integers...)
- Enter 3 or another number
You're ready for the first lab problem. Onward!
The first (lab) problem: hw6pr1a.hmmm, Cubic Countdown
Here is whathw6pr1a.hmmm
looks like:
# hw6pr1a is an example program that # 1) asks the user for an input # 2) counts up from that input # 3) keeps going and going... 00 read r1 # get number from user to r1 01 write r1 # print the value of r1 02 addn r1 1 # add 1 to r1 03 jumpn 01 # jump to line 01 04 halt # never halts! [use ctrl-c]
After you type run hmmm hw6pr1a.hmmm, you should see something like this:
---------------------- | ASSEMBLY SUCCESSFUL | ---------------------- 0 : 0000 0001 0000 0001 00 read r1 # get number from user 1 : 0000 0001 0000 0010 01 write r1 # print the value of r1 2 : 0101 0001 0000 0001 02 addn r1 1 # add 1 to r1 3 : 1011 0000 0000 0001 03 jumpn 01 # jump to line 01 4 : 0000 0000 0000 0000 04 halt # never halts! [use ctrYou will then see:
Enter number:Things have worked and the program is running.
It is asking you to enter a number (this is the effect of the read r1 instruction at the start of the program):
- Type in 32000 and hit return.
- You should see the simulator counting upward from 32000 or whatever number you typed in.
- When it gets to the maximum value, 32767, it will stop (because it overflows!)
- If you want to stop it early, hit control-c.
From here, for the first problem, hw6pr1a.hmmm, your task is to change the code in the file so that it does the following:
- First, it should ask the user for an input. Hmmm only allows integers between -32768 and 32767. For this problem, you may assume that the input will be positive and less than 30.
- Next, your Hmmm program should compute the cube of that input. It should print the result. You'll need multiple multiplications to compute the cube! This will require multiple instructions. In general, it takes a lot more Hmmm instructions to do something than, say, Python lines of code!
- Next, your hw6pr1a.hmmm should count downward from that resulting value (the cube of the input) one integer at a time. It should print each one until it gets to 0.
- When this countdown is at zero, the program should stop. The last value printed should be either 0 or 1. Either is completely OK as the final value.
For reference, here are all of the Hmmm instructions (open in a new tab for a larger view...)
Commenting is a must!
For this same reason—that keeping track of what is going on each step of the way is quite difficult for human readers—all of your Hmmm code should have a comment on every line except for null-operations, nops, which are convenient to use as spacers so that you have room to grow your program without renumbering lines in the future. A note about comments: comments are much more useful if they say why something is done, rather than simply translating the Hmmm instructions into English. For example, rather than:read r1 # Read a number into r1it's more helpful to write:
read r1 # Get number to be cubedSimilarly, instead of:
mul r2 r1 r1 # r2 = r1*r1try:
mul r2 r1 r1 # Find the square of r1