Assignment 4, due Feb 14
On every assignment, write your name legibly as it appears on your University ID card! Homework is due on paper at the start of class on the day indicated (usually Friday). Exceptions will be made only by advance arrangement (excepting "acts of God"). Late work must be turned in to the TA's mailbox (ask the CS receptionist in 14 MLH for help). Never push homework under someone's door!
00001000: D4 12 3 LIS R4, #12 00001002: E5 654321 4 LIL R5, #654321 00001006: 32 45 5 ADD R2, R4, R5
A problem: This data fills memory locations 100016 to 100716, a total of 4 halfwords, but the assembler listing shows it as a sequence of 8-bit bytes and one 24-bit triple-byte. Show the data as a sequence of hexadecimal address-value pairs, where each value is a halfword. (0.8 points)
The easy way to solve this problem is to start by converting it to a sequence of bytes:00001000: D4 -- from line 3 00001001: 12 00001002: E5 -- from line 4 00001003: 21 -- low byte of 24-bit value 00001004: 43 -- middle byte of 24-bit value 00001005: 65 -- high byte of 24-bit value 00001006: 32 -- from line 5 00001007: 45
Then, bunch the bytes into pairs.00001000: 12D4 00001002: 21E5 00001004: 6543 00001006: 4532
Note that you need to use the fact that this machine is a lowbyter twice here, once in undoing the 24-bit value into a sequence of bytes, and once in reassembling these bytes into halfwords.
USE "hawk.h" ALIGN 2 ; we begin at an even address B #D3 B #01 B #13 B #C2 B #F4 B #F3
a) Disassemble this code -- that is, convert it from a sequence of B assembly directives to an equivalent sequence of SMAL Hawk machine instructions (things like ORIS R1,7 or LIL R5,7000, although neither of these is part of the answer). Assembling your sequence should load exactly the same result into memory. (0.6 points)
First, pair up the bytes and convert them to binary, since the Hawk manual is all in binary, not Hex.USE "hawk.h" ALIGN 2 ; we begin at an even address B 2#11010011 2#00000001 B 2#00010011 2#11000010 B 2#11110100 2#11110011
Now, look them up in the Hawk manual, appendix B.1:USE "hawk.h" ALIGN 2 ; we begin at an even address LIS R3,1 ADDSI R3,2 MOVE R4,R3
b) If you execute the above sequence of machine instructions, starting with the program counter pointing to the first byte and stopping after the last byte, what registers will have been changed, and to what values? (0.6 points)
R3 = 3 (that is, the constant 1 incremented by 2)
R3 = 3 (that is, a copy of R3)
Hint: You can solve this by reading and hunting through Chapter 4, or you can solve this by using the SMAL assembler to assemble the code and then loading it into the Hawk emulator and letting the emulator disassemble it and run it. You will learn the most if you do both, using one approach to check your work done using the other.
The solutions above were done by hand. Here is the result of assembling the hand-made code from part a):1 USE "hawk.h" 2 ALIGN 2 ; we begin ... +00000000: D3 01 3 LIS R3,1 +00000002: 13 C2 4 ADDSI R3,2 +00000004: F4 F3 5 MOVE R4,R3
In the above, note that the sequence of bytes given in the assembly listing is identical to the sequence of bytes given in the problem statement!
Running the Hawk emulator with the object file obtained from assembling either the original byte sequence or the result of the hand translation exercise in part a, you get the following display showing the disassembled code. This screen capture was made after pressing the "s" key 3 times, making it single-step through three instructions so you can also see the values loaded in registers 3 and 4:HAWK EMULATOR /------------------CPU------------------\ /----MEMORY----\ PC: 00000006 R8: 00000000 *000000: LIS R3,#01 PSW: 00000000 R1: 00000000 R9: 00000000 000002: ADDSI R3,#2 NZVC: 0 0 0 0 R2: 00000000 RA: 00000000 000004: MOVE R4,R3 R3: 00000003 RB: 00000000 ->000006: NOP R4: 00000003 RC: 00000000 000008: NOP R5: 00000000 RD: 00000000 00000A: NOP R6: 00000000 RE: 00000000 00000C: NOP R7: 00000000 RF: 00000000 00000E: NOP
MACRO LI =dst, =const IF (const >= -#80) & (const <= #7F) LIS dst, const ELSEIF (const >= -#800000) & (c < #7FFFFF) LIL dst, const ELSE LIL dst, const >> 8 ORIS dst, const & #FF ENDIF ENDMAC
With this macro, a programmer could write LI R3, (A + B) and let the assembler decide which instruction or instruction sequence to use, depending on the value of the sum.
Note: The IF, ELSEIF, ELSE and ENDIF operations are fairly obvious. They control which part of the body of the macro gets assembled and which parts are skipped, depending on the values of the macro parameters. If that is insufficient, you are welcome to look at Chapter 5 of the SMAL32 manual for additional discussion.
Aside: So why isn't the LI macro in the hawk.h file? Because it, along with many similar macros, would raise the level of the language closer to a high level language, so you would learn less about machine architecture as you learned to program in what would end up being just a very clumsy middle-level programming language.
A problem: Write a similar macro called AI standing for add immediate. This macro would select between doing nothing (if the immediate constant was zero), using ADDSI, using ADDI or loading the constant into a register (user R1) and then using a plain ADD. Note that you may need to subdivide the "loading a constant" alternative depending on the value of the constant. Feel free to crib code for this purpose from the LI macro given above. (1 point)
Clarification: In response to a student question, the user might write AI R3,VALUE, and depending on the value of the second operand, the macro would expand to either ADDSI R3,VALUE or ADDI R3,R3,VALUE or something else.
This was a difficult problem, only a few students got it anywhere near right, and only a few students thought to ask questions about it. Here is a good answer:MACRO AI =dst, =const IF (const = 0) ; no work to do? IF (const >= -#8) & (const <= #8) ADDSI dst, const ELSEIF (const >= -#8000) & (c < #7FFF) ADDI dst, dst, const ELSE IF (const >= -#800000) & (c < #7FFFFF) LIL R1, const ELSE LIL R1, const >> 8 ORIS R1, const & #FF ENDIF ADD DST, DST, R1 ENDIF ENDMAC
Among the issues that complicate the problem: The ADDSI instruction cannot add zero, because it has provisions to handle +8 as well as -8; this requires a special case for adding zero.
The above solution uses nested if statements just to show that they are possible. It is probably easier to understand this solution that just uses another ELSEIF at the end.MACRO AI =dst, =const IF (const = 0) ; no work to do? IF (const >= -#8) & (const <= #8) ADDSI dst, const ELSEIF (const >= -#8000) & (c < #7FFF) ADDI dst, dst, const ELSEIF (const >= -#800000) & (c < #7FFFFF) LIL R1, const ADD DST, DST, R1 ELSE LIL R1, const >> 8 ORIS R1, const & #FF ADD DST, DST, R1 ENDIF ENDMAC