Machine Problem 2, due at the end of Feb 19

Part of the homework for CS:2630, Spring 2024
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"

	EXT	MP2DATA
	INT	MAIN
	S	MAIN

MAIN:	STORES	R1,R2
	ADDSI	R2,4

... your code here ...

	ADDSI	R2,-4
	LOADS	PC,R2

	END

Obviously, where it says YOUR NAME HERE put your name, and where it says ... your code here ... put SMAL Hawk code to solve the problem.

Specification: The declaration, EXT MP2DATA defines the symbol MP2DATA as the address of the first word in an array of words, where each of the words in this array holds the address of a character string. The last word in the array is a null pointer.

Your program should walk sequentially through the array, outputing each string. All control characters for formatting the strings are included in the strings, so your program should not produce any additional output.

To run your program, you will have to link it with the object file that defines MP2DATA. Assuming that your source code is in a file named mp2.a, assembling this file will produce a file called mp2.o. To link this with the data, use this shell command:

hawklink mp2.o ~dwjones/mp2data.o

Once you do this, the object file link.o will contain both your code and the data structure that your code is responsible for interpreting.

Understanding the data structure: At an early stage in your debugging, it might be worthwhile to declare your own MP2DATA instead of using the larger data that your code must ultimately be able to process. In that case, replace:

	EXT	MP2DATA
with something like this::
	USE	"ascii.h"
	ALIGN	4
MP2DATA:W	STRING1,STRING2,STRING3,NULL
STRING2:ASCII	" worl",NUL
STRING1:ASCII	"Hello",NUL
STRING3:ASCII	"d!",LF,NUL

Given this input data, your program should produce the output "Hello world!" verbatim, with just one newline at the end. Notice that the order that the strings are stored in memory is not important. What matters is the order of the pointers in MP2DATA.

We strongly recommend that you debug your algorithm in a high level language like C before trying to reduce it to assembly code. To do that, you will need to build an equivalent data structure. Here is the C declaration for this:

char * mp2data[] = {
        "Hello",
        " worl",
        "d!\n",
        NULL
};

C does not offer a way to control the order of storage of the strings, but what this declaration builds is sequence of 4 pointers, with mp2data being the address of the first pointer. The last pointer is NULL, while each of the first 3 points to a null-terminated string.

The following C declaration will declare a variable that is initialized to point to the pointer at address mp2data.

char ** a = mp2data;

Given this declaration, *a is a pointer to a character string, and if *a != NULL **a is the first character in this string. When *a == NULL, using **a is illegal.

Writing strings: In C, you can output the string s with:

        fputs( s, stdout );

The equivalent Hawk monitor routine is PUTSTR. Using puts( s ) in C or PUTS on the Hawk adds a an extra newline after the string.

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. Awkward 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, so commenting ADDSI R3,1 with increment R3 would be stupid. Comments should help the reader when the code is hard to follow.

Comments that give a high-level language equivalent for one or a small block of machine level statements are appropriate. If that style of commentary is used, please use sensible indenting and spacing rules for the "code" in the comments and use sensible variable names. So it might make very good sense to comment ADDSI R3,1 with counter++ because this explains that R3 is a counter and consistent use of high-level language code in the comments allows you to read the algorithm in the comment part of the assembly code. Of course, the high-level language code itself may still need comments. Don't omit those!

Note: As a general rule, the first lines of every file should identify that file. The TITLE in the code framework above does this. Please avoid using lines longer than 80 characters -- this is a common rule in the style guidelines of many employers. As a consequence, it is almost always a bad idea to maximize your editing window, since the default width of the window is 80 characters. Better to use the remainder of your screen realestate to open other windows for reference.

You can use the following tool flag many common file format problems such as overly long lines or invisible characters:

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

This format checker does not know anything about C or SMAL, it is looking for things that cause trouble with files imported from Windows systems, over-length lines, and non-printable characters.

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.

Historically, students unable to successfully complete MP2 for this course have a low chance of success in the course. If this assignment proves daunting, seek help early.


Discussion

Friday, February 9, 2024 2:00 PM

I'm getting this error message that I don't understand:

[hawkid@fastx04 hawkid]$ smal mp2.a
dwjones@limonite:~$ smal t.a
    16  error message                   ERROR illegal PC-relative address
    16  misuse of relocation          H qREGISTERq+8 - (.+2)

   2 errors
[hawkid@fastx04 hawkid]$

How do I interpret this?

When you get assembly errors, you should look at the listing file. If you just assembled t.a, your listing is in file t.l. Look at that. The listing file shows your whole source file, with the output of the assembler added in the left margin and error message under the lines that caused them. In this case, it will show you this:

                                15  LOOP:
                                16          LOADCC  R3,R8
+00000000: F3  40               16        ERROR illegal PC-relative address
error message                       
+00000002: 0004                 16      H qREGISTERq+8 - (.+2)
misuse of relocation                                   =

I have only included lines 15 and 16 of the file. Line 16 had the error. The problem was caused by the LOADCC command on line 16. If you look up this command in the Hawk manual, you will find that it is a memory reference instruction. If you read that section of the manual you will find this:

The LOAD instruction for loading a value from memory into a register is the prototypical memory reference instruction. All of these instructions share the same assembly language formats:

	LOAD	dst,x,disp
	LOAD	dst,label

The three argument form is used for indexed addressing, where x is one of R1 through R15. The second form is used for PC relative addressing

So, the complaint was that, in LOADCC R3,R8, you used R8 where the assembler wanted you to use a PC-relative address.

Perhaps LOADCC was the wrong instruction?

Saturday, February 17, 2024 6:25 PM

Right now, I am debugging using the input data given in the assignment file. My program outputs Hello world! but also, outputs Trap errors. After stepping through the program, it seems to be getting stuck in the loop and not exiting correctly. Do you have any tips on how I can fix this?

Just for fun, I fixed my solution to MP2 so that it would use the hello-world test data and then I broke my code to make it bus trap, producing this output:

HAWK EMULATOR
   /------------------CPU------------------\   /----MEMORY----\
   PC:  00000000                R8: 00001010   FFFFFC: --
   PSW: 00007F00  R1: 00001034  R9: 00000000   FFFFFE: --
   NZVC: 0 0 0 0  R2: 00010074  RA: 00000000 ->000000: LIL     R2,#010070
                  R3: 726F7720  RB: 00000000   000004: JSR     R1,#00032C
                  R4: 001000E8  RC: 00000000   000008: LIL     R1,#001020
                  R5: FF000154  RD: 00000000   00000C: JSRS    R1,R1
                  R6: 00001034  RE: 00000000   00000E: BR      #000000
                  R7: 726F7720  RF: 00000000   000010: CPUSET  R2,#3

 **HALTED**  r(run) s(step) q(quit) ?(help)

Hello world!
q"Dh
Bus Trap.          Trap PC = #0000051E
                   Trap MA = #726F7720 invalid addr

Normally, after a bus trap, I would say "look at the Trap PC" and find the corresponding place in your code. The trap program counter is the address of the instruction that tried to do something that didn't work. In this case, a bus trap — that is, the code tried to use an invalid memory address.

Here, Trap PC is 51E16. The hawk linker is relocating your code to address 100016, so this trap address is in the Hawk monitor. That means that you called some Hawk monitor routine passing it an illegal parameter. The obvious question is, what happened?

Looking at the above, you can learn more: When there is a bus trap, Trap MA gives the memory address that the instruction tried to use that didn't work. Here, the memory address is 726F772016, definitely not in RAM, which runs from 1000016 to 1FFFF16. The Hex value 726F772016 is a bit suspicious, and when I looked at my assembly listing, I found this line:

+00000010: 20  77  6F  72        9  STRING2:ASCII   " worl",NUL

Pack those bytes into a word, and you have 726F772016. From this, we can conclude that my broken program tried to use the first 4 bytes of the ASCII test data as a memory address.

Go back to the display of the Hawk CPU state at the time of the trap. R3 was 726F772016, exactly the memory address that caused the problem, and R1 was 103416. That's in ROM after address 100016, so it's probably the return address from a call to the Hawk monitor from my (deliberately broken) code. So, back to the assembly listing. Subtract 100016 from 103416 and ask, what's there in my code?

+0000002E: E1 +000000           27          LIL     R1,PUTSTR
+00000032: F1  B1               28          JSRS    R1,R1
+00000034: .... more code ....

What seems to have happened is this: My program somehow contiued to walk through the sequence of memory addresses after the null pointer that was supposed to mark the end of that sequence. I'll bet that the "q"Dh" after the "Hello world!" was what the code output when it tried to use a null pointer as a pointer to a string.

So where's the loop in my code? It turns out that my loop was just fine, and it correctly detected the null and tried to return from my main program. What I did to break my program was forget to decrement the stack pointer (that's R2) before my return. The result of that was that my code used a nonsense value as a return address. It used a value from the stack just above its own return address, which turned out to be a return address that had previously been passed to PUTCHAR.

Monday, February 19, 2024 12:29 PM

When I try to link my program, I get this error message:

ERROR: 5 undefined symbol T RMP2DATA

What am I doing wrong?

This linker error is because your code contained EXT MP2DATA but the linker was not told about an object file that defined MP2DATA. The R prefix on names defined by external definitions is an artifact of how external symbols are represented in the object code.

If you reread the assignment, you'll find instructions for how to use the hawklink command with an extra argument telling it where to look for the definition of MP2DATA.