CS5: Introduction to Computer Science at Harvey Mudd College
CS5 Web > Homework6Gold > Lab6
Submissions: CS submission site

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 Gradescope


Starter 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:

hmmmexample.png

To try it, start ipython and then run hmmm example1.hmmm .


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:

Happy Hmmming!

Here is the HMMM documentation: all of the instructions in the Hmmm language


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 named r0 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 as add that take three registers as arguments, e.g.,

add r3 r1 r2

The 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:

Unzip that file and you'll get a Hmmmwork6 folder with several files in it.


Try it with example1.hmmm

  1. Try Hmmm out by cd'ing into the Hmmmwork6 folder (for this term) that you downloaded and unzipped.
  2. Then, run the usual command at the command-line:    ipython
  3. Then, type run hmmm hw6pr1a.hmmm to run Hmmm itself. Hmmm will assemble and run hw6pr1a.hmmm.

Not working? Ask us! (You may be on Windows where you'll need to unzip the folder before running the files. It lets you navigate to them, even zipped!)

If the example1.hmmm file is moved away from the other files in that folder, it won't work!   Be sure to move the whole folder around, not single files.

Here is what 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 ctr

You will then see:

Enter number:
Things have worked and the program is running!

You'll see the right answer! (Perhaps...)


You're ready for the first lab problem. Onward!


The first (lab) problem: hw6pr1a.hmmm, Cubic Countdown

Here is what hw6pr1a.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 ctr

You 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):


From here, for the first problem, hw6pr1a.hmmm, your task is to change the code in the file so that it does the following:

  1. 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.
  2. 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!
  3. 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.
  4. 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...)

Hmmm instructions



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 r1
it's more helpful to write:
    read r1     # Get number to be cubed

Similarly, instead of:

    mul r2 r1 r1 # r2 = r1*r1
try:
    mul r2 r1 r1 # Find the square of r1

On to the next part: RandoHmmm numbers…

You've implemented the cubic countdown!

Next, continue via this link: RandoHmmm   

to go to the next part of the lab, in which you'll use Hmmm to generate "random" numbers!