Machine Problem 2, due at the end of Feb 19
Part of
the homework for CS:2630, Spring 2024
|
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
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.
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?
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.
When I try to link my program, I get this error message:
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.