Archived page.

This is an archived copy of my old (academic) homepage formerly hosted at Chalmers. It is no longer being updated.

Go to the new page.



GETTIME

Fullständig GETTIME rutin från övning 3.

-- {File: gettime.s12 - Language: s12-asm} -- 1 ; gettime.s12 2 ; Implementation of the GETTIME routine, and a small program that performs a 3 ; very simple test of the routine (i.e. for one known value). 4 ; 5 ; GETTIME inspects the 32-bit unsigned CLOCK value that is used to count the 6 ; number of 10ms ticks since the beginning of time (i.e. system startup or 7 ; something). GETTIME stores at the address pointed to by X the number of 8 ; [X+0] = hours 9 ; [X+1] = minutes 10 ; [X+2] = seconds 11 ; elapsed, according to CLOCK. 12 ; 13 ; Essentially: 14 ; seconds = (CLOCK / 100) Mod 60; 15 ; minutes = (CLOCK / 100 / 60) Mod 60; 16 ; hours = (CLOCK / 100 / 60 / 60); 17 ; The tricky part here is, of course, the fact that CLOCK is 32 bits and that 18 ; the CPU12 doesn't really support 32 bit values. :-( 19 ; 20 ; We've got: 21 ; * EDIV : Extended DIVision - 32 bits in (Y:D) divided by 16 bits in X 22 ; results in 16 bits quotient in Y, and 16 bits remainder in D 23 ; 24 ; Problem 1: (CLOCK / 100) can not always be represented by a 16 bit value 25 ; Solution 1.a: (for seconds) rearrange terms: 26 ; seconds = (CLOCK Mod 6000) / 100 27 ; Problem 2: The value (100*60*60) is larger than 0xFFFF (and again CLOCK/100, 28 ; CLOCK/60 or CLOCK/6000, ... is not neccessarily smaller than 0xFFFF). 29 ; Solution 2.a: (for hours): 30 ; 60*60*100 = 2*2*3*5 * 2*2*3*5 * 2*2*5*5 = 2^6 * 3^2 * 5^4 = 2^6 * 5625 31 ; Implement division with (60*60*100) as CLOCK / 2^6 / 5625, where division 32 ; with 2^6 is implemented using right-shifting. 33 ; 34 ; To find the minutes, multiply hours with 60*60*100 (using something similar 35 ; to the above), and subtract this from CLOCK. The result of this is at most 36 ; (60*60*100)-1, which when divided by 100 is at most 3600 < 0xFFFF. 37 38 ; Boilerplate code 39 ORG $1000 40 41 start: 42 movw #$0BAD,CLOCK+2 ; this should be 544 hours, 16 minutes 43 movw #$C0DE,CLOCK ; and 4 seconds (note 544 > 255, so timmar will 44 ; be incorrect) 45 ldx #timmar 46 jsr GETTIME 47 48 bra start 49 50 ; resultat 51 timmar RMB 1 52 minuter RMB 1 53 sek RMB 1 54 55 ; clocka 56 CLOCK RMB 4 57 58 GETTIME: 59 ; intro - store registers 60 pshd 61 pshy 62 pshx 63 64 ; calc seconds : (CLOCK Mod 6000) / 100 65 ldd CLOCK 66 ldy CLOCK+2 67 ldx #6000 68 ediv ; D = CLOCK Mod 6000 69 70 ldy #0 71 ldx #100 72 ediv ; Y = (CLOCK Mod 6000) / 100 73 xgdy ; D <=> Y 74 75 pulx 76 stab 2,X 77 pshx 78 79 ; calc hours 80 ; problem: 60*60*100 = 360'000 > 0xFFFF :-( 81 ; 60*60*100 = 2*2*3*5 * 2*2*3*5 * 2*2*5*5 = 2^6 * 3^2 * 5^4 = 2^6 * 5625 82 ; I.e shift left by 6 and then divide by 5625. hooray 83 ldd CLOCK ; lower bits 84 lsrd ; 6x Logic Shift Right on D 85 lsrd 86 lsrd 87 lsrd 88 lsrd 89 lsrd 90 pshd ; put it away for now 91 92 ldaa CLOCK+3 ; bits 16 ... 23 93 lsla ; shift left twice => high bits = bits that would have 94 lsla ; been shiftet away 95 oraa 0,SP ; or with high bits from CLOCK-thing 96 staa 0,SP 97 98 ldd CLOCK+2 ; all high bits 99 lsrd ; 6x again 100 lsrd 101 lsrd 102 lsrd 103 lsrd 104 lsrd 105 106 puly ; put low bits in Y 107 xgdy ; Y <=> D 108 ldx #5625 109 ediv ; Y = (CLOCK >> 6) / 5625 = CLOCK / 360'000 110 111 xgdy ; Y <=> D 112 pulx 113 stab 0,X 114 pshx 115 116 ; calc minutes 117 ; multiply hours by 5625 and then 2^6; subtract this from CLOCK 118 ; THEN divide stuff 119 ldy #5625 ; Note: hours is still in D 120 emul ; result in (Y:D) 121 122 xgdy ; Y <=> D 123 lsld ; 6x shift high bits to left 124 lsld 125 lsld 126 lsld 127 lsld 128 lsld 129 pshd ; and put that away (1) 130 131 xgdy ; Y <=> D 132 psha ; store A for later 133 lsra ; shift right twice => low bits = bits that would have 134 lsra ; been shifted out 135 oraa 2,SP ; or with low bits from (1) 136 staa 2,SP ; 137 138 pula ; restore whole low bits 139 lsld ; 6x shift low bits to left 140 lsld 141 lsld 142 lsld 143 lsld 144 lsld 145 146 ldy CLOCK+2 ; load clock value 147 148 pshd ; prepare subtraction (low bits) 149 ldd CLOCK 150 subd 0,SP 151 std 0,SP 152 153 xgdy 154 sbcb 3,SP 155 sbca 2,SP 156 std 2,SP 157 158 puld 159 puly ; so, the result of the subtraction is Y:D 160 161 ldx #6000 162 ediv ; temp1 = Y = (Clock - Hours*stuff) / (60*100) 163 164 xgdy 165 ldy #0 166 ldx #60 167 ediv ; D = temp1 Mod 60 168 169 pulx 170 stab 1,X ; store results 171 ; phew, done 172 173 ; outro - restore registers 174 ;pulx ; already done 175 puly 176 puld 177 rts 178 179 ;EOF --}}}1-- vim:syntax=asm:foldmethod=marker:ts=4:noexpandtab:

Ladda ned koden här.