Archived page.
This is an archived copy of my old (academic) homepage formerly hosted at Chalmers. It is no longer being updated.
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.