-
Here is an appropriately commented SMAL Hawk assembly language program
that is very close in its logic to the original C program. Since this
example demonstrates separate assembly, it is made up of two source files:
TITLE funct.a, homework 4 problem 1
USE "/group/class/22c018/hawk.macs"
INT FUNCT
; -------------------
; Activation record structure, indexed from R2
;RA = 0 ; return address
X = 4 ; saved parameter
A = 8 ; local variable
AR = 12 ; activation record size
FUNCT:
; on entry, R3 = parameter X
; on exit, R3 = result
; uses R3
CMPI R3,2 ; see if X <= 2
BLE FUNQT ; quit and return X if so
STORES R1,R2 ; save RA
STORE R3,R2,X ; save X
ADDSI R3,-1 ; set up parameter for call
ADDI R2,AR
JSR R1,FUNCT ; recursive call FUNCT(X-1)
STORE R3,R2,A-AR ; save result as A
LOAD R3,R2,X-AR ; recorver X for next call
ADDSI R3,-3 ; set up parameter for call
JSR R1,FUNCT ; recursive call FUNCT(X-3)
SUBI R2,AR
LOAD R1,R2,A ; recover A from first call
ADD R3,R3,R1 ; setup to return A+FUNCT(X-3)
LOADS R1,R2 ; recover RA
FUNQT:
JUMPS R1 ; return!
END
TITLE main.a, homework 4 problem 1
USE "/group/class/22c018/hawk.macs"
USE "/group/class/22c018/hawk.system"
S MAIN
EXT FUNCT
PFUNCT: W FUNCT
; -------------------
MAIN:
LOADS R2,PSTACK
CALL DSPINI
LIS R8,1 ; initialize loop counter I
LP:
MOVE R3,R8 ; setup parameter for call
CALL FUNCT ; call FUNCT(I)
LOADI R4,8 ; setup parameter for call
CALL DSPDEC ; call DSPDEC(FUNCT(I),8)
ADDSI R8,1 ; increment I
CMPI R8,8 ; test for end of loop
BLT LP ; continue loop if I < 8
LIS R1,0
JUMPS R1 ; exit gracefully
END
-
- 1/1 - not possible (result >= 1)
- 1/2 - .100000000000...
- 1/3 - .010101010101...
- 1/4 - .010000000000...
- 1/5 - .001100110011...
- 1/6 - .001010101010...
- 1/7 - .001001001001...
- 1/8 - .001000000000...
- 1/9 - .000111000111...
- 1/10 - .000110011001...
-
Consider the following simple (but typical) binary floating point format.
_ _ _ _ _ _ _ _ _ _ _
|_|_|_|_|_|_|_|_|_|_|_|
| | | |
s exp mantissa
For all integer x between 1 and 10, here are the closest approximations to
the values of 1/x, shown in binary in this system, with errors given:
- 1/1 - 0 1001 100000 = 1.0000 no error
- 1/2 - 0 1000 100000 = 0.5000 no error
- 1/3 - 0 0111 101011 = 0.3359 error .00260
- 1/4 - 0 0111 100000 = 0.2500 no error
- 1/5 - 0 0110 110011 = 0.1992 error .00078
- 1/6 - 0 0110 101011 = 0.1680 error .00130
- 1/7 - 0 0110 100101 = 0.1445 error .00167
- 1/8 - 0 0110 100000 = 0.1250 no error
- 1/9 - 0 0101 111001 = 0.1113 error .00022
- 1/10 - 0 0101 110011 = 0.0996 error .00039
-
Here is a fast version of strcpy():
; --------------
STRCPY:
; on entry R3 = destination address
; on entry R4 = source address
; uses R3,R4,R5,R6,R7
; part 1, copy odd stuff from the first word!
LOADSCC R5,R4 ; get the word (and see if it has a null)
BCS STRLST ; this is the last word!
STRSTA:
MOVE R6,R4 ; see if we're on a word boundary
TRUNC R6,2
BZS STRBOD ; if so, we have first word of body
EXTB R6,R5,R4; get one byte
LOADS R7,R3
STUFFB R7,R6,R3; stuff that byte into place
STORES R7,R3
ADDSI R3,1 ; bump pointers
ADDSI R4,1
BR STRSTA ; continue copying first bytes
; part 2, copy string body
STRBOD:
MOVE R6,R3 ; see if destination is aligned
TRUNC R6,2
BZR STRLST ; we're not aligned! Do it slow!
STRBLP:
STORES R5,R3 ; save the word
ADDSI R3,4 ; bump the pointers
ADDSI R4,4
LOADSCC R5,R4 ; get the word (and see if it has a null)
BCR STRBLO ; if not the last word, go onward!
; part 3, copy remainder
STRLST:
EXTB R6,R5,R4; get next byte
BZS STRQT ; quit if byte is null
LOADS R7,R3
STUFFB R7,R6,R3; stuff that byte into place
STORES R7,R3
ADDSI R3,1 ; bump pointers
ADDSI R4,1
LOADS R5,R4 ; get next word
BR STRLST
; part 4, wrapup
STRQT:
LOADS R7,R3
STUFFB R7,R6,R3; stuff null into place
STORES R7,R3
JUMPS R1 ; return
-
Here is a routine to convert BCD numbers to printable ASCII:
; -------------
BCDTOA:
; on entry, R3 = BCD number
; on entry, R4 = address of 8 character string
; on exit, R3 = address of string (as in C library)
; uses R5,R6,R7
LEA R5,R4,8 ; compute address of end of string
; part 1 -- put digits into end of string
BCDLP:
MOVE R6,R3 ; get a BCD digit
TRUNC R6,4
ADDI R6,'0' ; make it into ASCII
ADDSI R5,-1 ; push pointer onward
LOADS R7,R5
STUFFB R7,R6,R5; stuff character into string
STORES R7,R5
SRU R3,4 ; shift next digit into place
BZR BCDLP ; if more digits, convert them
; part 2 -- put blanks before the digits
LIS R6,' ' ; the blank!
BCDBL:
CMP R5,R4 ; see if more space in string
BEQ BCDQT ; if not, quit
ADDSI R5,-1 ; push pointer onward
LOADS R7,R5
STUFFB R7,R6,R5; stuff blank into string
STORES R7,R5
BR BCDBL ; iterate
BCDQT:
MOVE R4,R3 ; put pointer in place for return
JUMPS R1 ; return