Machine Problem 2, due at the end of Sept 26

Part of the homework for CS:2630, Fall 2023
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Framework: Your program must begin and end as follows:

	TITLE	"mp2.a by YOUR NAME HERE"
	USE	"hawk.h"
	USE	"stdio.h"

The code continues with the usual skeleton of a Hawk program given in Chapter 5 of the notes.

Top Level Specification: Your program should output the first 15 numbers in the tribonacci sequence. The first three numbers are 0, 0, 1. After that, every number in the sequence is the sum of the previous three.

The numbers should be output across the screen, each number separated from its predecessor by a comma.

Your program must be written in SMAL Hawk assembly language, and it it must be formatted so that it does not trigger warnings when you run

   [HawkID@fastx?? ~]$ ~dwjones/format mp2.a

Brief commentary: The tribonacci sequence is closely related to the Fibonacci sequence. Where the Fibonacci sequence begins with 0, 1 and each successive number is the sum of the previous two, the Tribonacci sequence begins with 0, 0, 1 and each successive number is the sum of the previous three. Wikipedia says that Charles Darwin invented this sequence inadvertently, but it was not named until later.

Also, note that solving this problem in C before solving it in assembly language is an obvious way to make sure you have an algorithm that works before you try to reduce it to assembly language code.

Grading: 5 points. Correct output is worth 2.5 points. The remaining credit will be offered only for those who have correct output.

Code that does not assemble will not earn any credit.

Stylistically clean code is important; that is why half the credit is reserved for style, but only if the code works. Bad indenting will be penalized up to 1 point from the 2.5 style points. Excessive or inadequate white space within and between lines will be penalized, again, up to 1 point. Excessive or inadequate comments will be judged similarly.

Note: Comments should not repeat the assignment. Assume that the reader of your code has read the assignment. Assume that the reader knows how to program. Using C code as commentary on assembly code is quite appropriate, so long as additional comments are added where the C code needs comments.

Submission: To submit your work, it must be in a file named mp2.a in your current directory on the CLAS Linux system, and you must know your section number. In the following, what you type is shown in bold face. Begin at the linux command-line prompt:

   [HawkID@fastx?? ~]$ ~dwjones/submit 0A0X mp2.a

Note: The ~dwjones must be verbatim, do not substitute another name. Also, use your section number (one of 0A01 to 0A05).

The submission script will copy your code and, after the copy is made, it will output a message saying "successful submission." You may resubmit as many times as you want; each time you resubmit, your previous submission of that file will be replaced, so we will only see your final submission. The completed dialogue on your screen will look like this when you are done:

In the event of insurmountable trouble, do not delete or edit files you have submitted until the graded work is returned. The operating system record of the last edit time and date and the backups maintained by the operating system are proof of what you did and when, and they allow us to investigate what happened. until your graded work is returned. This way, the time stamp marking the time of last edit is a trustworthy indicator of whether you did the work on time.


Discussion

Sept. 13, 8:30 AM

There seems to be an inconsistency, some places it says use the link command. Other places it says hawklink. Why?

Originally, the Linux and Unix shell command for creating a link to a file was ln. Then someone decided to make link a standard synonym for ln. So, we had to rename the Hawk linker from link to hawklink.

If you have trouble with this, pleas run the following two shell commands:

bash-5.2$ ~dwjones/2630deinstall
bash-5.2$ ~dwjones/2630install

This will remove the possibly defective definition of link and install the correct definition of hawklink.

Sept. 22, 4:53 PM

After I compile my code with no errors, I run hawk mp2.o and it gives me a "found '^J' where 'P' was expected in object file" error.

You need to do the following commands:

smal mp2.a
hawklink mp2.o
hawk link.o

You can only use

smal mp2.a
hawk mp2.o

in cases where there is no reference to external symbols such as routines in the Hawk monitor.

Sept. 24, 6:30 PM

I keep getting this error when I try to link the output of my program:

[hawkid@fastx02 hawkid]$ hawklink mp2.o
     4  undefined symbol          T RMAIN

What does it mean?

You were told to use this boilerplate at the start of your code:

        TITLE   "Some appropriate title like Hello World or MP2"
        USE     "hawk.h"
        USE     "stdio.h"
ARSIZE  =       4
        INT     MAIN
        S       MAIN
MAIN:                        ; entry point
        STORES  R1,R2
        ADDI    R2,R2,ARSIZE

;  --- begin aplication code ---

Until you understand what's going on, don't start getting creative with the boilerplate. It was all explained in class, but here's a repeat:

In this case, the error is that you didn't include the line saying INT MAIN. The purpose of this line is to tell the linker where your main program is. The linker couldn't find it, so it complained.

Some students have spent time puzzling over the S MAIN line. This line tells the SMAL assembler to tell the Hawk linker to tell the Hawk computer to stop when PC=MAIN, that is, stop after the operating system has transferred control to your program, but before any of your instructions run. This gives you a chance to do some debugging by, for example, running your code one instruction at a time (with the s command) or, when inside a loop, to run just one loop iteration at a time (with the i command).

Sept. 25, 10:21 AM

I am having trouble getting the Fibonacci sequence example in the notes to run. It always results in a bus trap.

That example in Chapter 6 is a recursive subroutine. It was written to explore recursion, not to illustrate a simple algorithm appropriate for MP2. To use it effectively, you'd have to do major surgery to make it compute Tribonacci numbers and in addition, you'd have to write a main program to call it 15 times and output the result after each call, with commas added where needed.

This assignment is far simpler than what you seem to have set out to do. It can be solved with a simple iterative main program, just one loop, and no need to use main memory for local variables (because you've got a slew of registers available).

When I solved the problem, my solution began something like this:

trib = 0;
trib1 = 0;
trib2 = 1;
do {
    temp = trib + trib1 + trib2;
    trib = trib1;
    trib1 = trib2;
    trib2 = temp;
} while (true);

That basic idea doesn't include loop termination, it doesn't include output of any values, and it certainly doesn't include "pretty" things like commas. First, you need to decide where to put your variables, and I suggest there are so few you can use registers and never worry about using RAM.

Sept. 26, 11:00 AM

So with that sum I'm a bit confused on how to take the ADD function's output and move it to r3.

The add machine instruction has two source and one destination fields. If you want to add two numbers and put the result in R3, you might write this kind of code:

	LIS	R4,1
	LIS	R5,2
	ADD	R3,R4,R5

This initializes R4 and R5 to hold the values 1 and 2, and then puts the sum in R5, which ends up holding 3.

But you need to think about what registers you want to use. If you are just doing computation, without calling any subroutines, use any register, but if you call subroutines, we have the convention that subroutines are free to use R1 and R3 to R7, but they must return leaving R2 and R8 to 15 unchanged. Of course, R2 is our stack pointer, so you can't use it for your variables.

So, if you want to call PUTCHAR to put commas between successive numbers, an PUTDEC to output the successive numbers, you will need to use R8 and up for variables that survive these calls, and only put temporary values in lower registers.

So, the code you write is more likely to resemble this:

	LIS	R8,1
	LIS	R9,2
	ADD	R10,R8,R9
	MOVE	R3,R10

Sept. 26, 11:47 AM

I have a working loop for the tribonacci sequence, however, when I try to use PUTCHAR or PUTS, it puts out weird characters such as the = sign.

PUTCHAR only outputs a single character from R3. If you give it a value that is not a character, expect nonsense.

PUTS outputs a null-terminated character string when given, in R3, the memory address of the first character in that string. Expect nonsense or even a bus trap (hardware exception) if the contents of R3 is not the memory address of a string when you call it.

For an introductory list of the Hawk monitor routines available for input and output, see Chapter 6 of the course notes:
-- http://homepage.cs.uiowa.edu/~dwjones/assem/notes/05prog.shtml

The official manual for these routines is in the stdio.h header file. The source for this file is indexed from the course home page (near the bottom):
-- http://homepage.cs.uiowa.edu/~dwjones/assem/

Sept. 26, 2:16 PM

I keep getting relocation errors in my code. What is going on?

You didn't tell me the specific line of code that triggered the error message, nor the nature of that line, but this is a common error for those new to the Hawk instruction set.

The SMAL assembler has useful kind of data typing for numbers: Absolute numbers like 5 or 1024 are quite distinct from external symbols like PUTCHAR or R5. So if you use something like

	LIS	R3,R6
The assembler will complain that R6 is illegal. If this was line 8 of your source file, you'll see this in your listing file:
                                 8          LIS     R3,R6
+00000006: D3 +06                8      ERROR register not allowed

The macro for assembling the LIS instruction managed to anticipate this error and give a nice error message. The following example shows an uglier error message from the STORE macro:

                                 8          LIS     R3,R6
+0000000A: F3                    8          STORE   R3,2,4
+0000000B: 22  0004              8      B (61472 & #FF) ! (2-qREGISTERq)
misuse of relocation                                        =

The macro successfuly put out the first byte of the instruction, F316 but it had trouble with the second byte because the absolute constant 2 where it expected a register. In the assembly code from the macro expansion, you can see the sub-expression 2-qREGISTERq. The 2 there is the value that should have been a register, and the qREGISTERq being subtracted is there force the type of that value to be a register. The SMAL assembler underlined the minus sign because the two operands of that subtraction have incompatable types.

Sept. 26, 7:23 PM

Additionally, according to the assignment's requirements, I still need to remove the last comma, right? I have not thought of any good way to figure this comma out and do not know if it will deduct a lot of points.

Right, but it's a small issue compared to what you've already done, and the penalty is small.

This is an intro to CS problem, not a computer organization problem. Recall, that in C, Java, Python or even assembly language, there are many ways to make a loop. It's easy to remember pre-test and post-test forms of loops:

while (cond) {
    thing
    more thing
}

do {
    thing
    more thing
} while (cond)

It's easy to forget that you can also write loops with a break in the middle:

repeat {
    thing
    if (cond) break;
    more thing
}

These choices let you solve the final-comma problem fairly easily.