-
This solution preserves the original C code verbatim as comments.
TITLE HW3 Problem 1 program
USE "/group/class/22c018/hawk.macs"
USE "/group/class/22c018/hawk.system"
S main
main:
LOAD R2,PSTACK
CALL DSPINI
LIS R8,50 ; int t = 50
loop:
CMPI R8,1 ; while (t > 1) {
BLE endloop
LIS R9,1
AND R9,R8 ; if (t & 1) {
BZS else
ADDSL R8,R8,1 ; t = (t * 3) + 1;
ADDSI R8,1
BR endif
else: ; } else {
SR R8,1 ; t = t / 2;
endif: ; }
MOVE R3,R8
LIS R9,8
CALL DSPDEC ; printf("%d ",t);
BR loop ; }
LEA R3,stop
CALL DSPST ; printf("STOP");
CLR R1
JUMPS R1 ; --- really stop
stop: ASCII "STOP",0
-
To detect overflows, we modify the above as follows. New lines are marked
to stand out from the old ones!
TITLE HW3 Problem 2 program
USE "/group/class/22c018/hawk.macs"
USE "/group/class/22c018/hawk.system"
S main
main:
LOAD R2,PSTACK
CALL DSPINI
LIS R8,50 ; int t = 50
loop:
CMPI R8,1 ; while (t > 1) {
BLE endloop
LIS R9,1
AND R9,R8 ; if (t & 1) {
BZS else
ADDSL R8,R8,1 ; t = (t * 3) + 1;
BVS error ; ====== detect overflow
ADDSI R8,1
BVS error ; ====== detect overflow
BR endif
else: ; } else {
SR R8,1 ; t = t / 2;
endif: ; }
MOVE R3,R8
LIS R9,8
CALL DSPDEC ; printf("%d ",t);
BR loop ; }
LEA R3,stop
CALL DSPST ; printf("STOP");
CLR R1
JUMPS R1 ; --- really stop
error: ; ====== on overflow, come here
LEA R3,ermsg; ======
CALL DSPST ; ====== printf("ERR");
CLR R1 ; ======
JUMPS R1 ; ====== --- really stop
stop: ASCII "STOP",0
ermsg: ASCII "ERR!",0 ;=====
-
Part A:
The following C declaration of an array of two-element records
translate to SMAL Hawk assembly language as shown:
struct rec {
long int x;
char y,z;
} z[4];
; an array of 4 recs
COMMON zd,4*recs
zp: W zd
; fields of the structure rec
x = 0 ; an integer (4 bytes)
y = 4 ; a character (1 byte)
z = 5 ; a character (1 byte)
recs = 8 ; size of a rec (2 words)
Part B:
In terms of the above declarations, the nonsense code fragment can be
translated as:
LIS R8,0 ; for (i=0; i < 3; i++) {
loop: CMPI R8,3
BGE endloop
LOAD R9,zp ; R9 = z
MOVE R10,R8
ADDS R10,R9,3 ; R10 = &z[i]
MOVE R11,R8
ADDSI R11,1
ADDS R11,R9,3 ; R11 = &z[i+1]
LEA R12,R11,y ; R12 = &z[i+1].y
LOADS R13,R12
EXTB R13,R13,R12 ; R13 = z[i+1].y
LEA R14,R11,z ; R14 = &z[i+1].z
LOADS R15,R14
EXTB R15,R15,R14 ; R15 = z[i+1].z
ADD R14,R14,R15 ; R14 = z[i+1].y + z[i+1].z
STORE R14,R10,x ; z[i].x = R14
ADDSI R8,1
BR loop ; }
endloop:
This code is deliberately very stupid, which makes it considerably longer
than necessary. It takes no advantage that fields y and z of each array
element are in the same word and it takes no advantage of the fact that knowing
the address of one array element allows trivial computation of the address
of the next. This stupidity allows the easy identification of the relationship
between each machine instruction and a specific part of the high level
language statements
-
Here is an appropriately documented HAWK macro to load a halfword from memory,
with no alignment constraints:
assuming that the addressed halfword is aligned properly:
MACRO LOADHSNA =dst,=x
; LOAD Halfword Short NonAligned, in 8 instructions
ADDSI x,1
LOADS R15,x
EXTB R15,R15,x ; get second byte of halfword
ADDSI x,-1
LOADS dst,x
EXTB dst,dst,x ; get first byte of halfword
TRUNC dst,8 ; truncate first byte
ADDSL dst,R15,8 ; shove second byte over and merge
ENDMAC
-
The code in question assembles to the following:
1 USE "hawk.macs"
2
3 MACRO LOADHS =dst,=x
4 LOADS dst,x
5 EXTH dst,dst,x
6 ENDMAC
7
8 LIL R5,#00012345
+000000: E501 2345 9 looptop:
10 LOADHS R6,R5
+000004: F665 4665 11 BZS loopexit
+000008: BA02 12 ADDSI R5,2
+00000A: 1552 13 BR looptop
+00000C: B8FB 14 loopexit:
15
16 END