Double Dabble for the Motorola 68000:
. 00113 ******************************************************************************
. 00114 *
. 00115 * Format - Convert a number to ASCII decimal
. 00116 *
. 00117 * Input:
. 00118 * The first bytes of Dabble = the number to convert
. 00119 * D1 = number of bits to convert
. 00120 * D2 = number of bytes to convert
. 00121 * D3 = number of packed BCD bytes in result
. 00122 *
. 00123 * Output:
. 00124 * Output string with length byte starting at Out+1
. 00125 *
. 00126 * Uses:
. 00127 * D0
. 00128 * D4
. 00129 * D5
. 00130 * A0
. 00131 * A1
. 00132 * A2
. 00133 *
. 00134 * Note:
. 00135 * Implemented with the Double Dabble algorithm:
. 00136 *
. 00137 * https://en.wikipedia.org/wiki/Double_dabble
. 00138 *
.00000530 00139 Format:
.00000530 207C 0000076A 00140 movea.l #Dabble,A0 ; Clear the BCD digits
.00000536 D0C2 00141 adda.w D2,A0
.00000538 1A03 00142 move.b D3,D5
. 00143
.0000053A 00144 Format0:
.0000053A 4218 00145 clr.b (A0)+
.0000053C 5305 00146 subq.b #1,D5
.0000053E 66FA (0000053A) 00147 bne Format0
. 00148
.00000540 207C 00000769 00149 movea.l #Dabble-1,A0 ; Determine index of number to convert
.00000546 D0C2 00150 adda.w D2,A0 ; This is the LSB
. 00151
.00000548 2248 00152 move.l A0,A1 ; Determine index of BCD digits
.0000054A D2C3 00153 adda.w D3,A1 ; BCD digits are big endian order
. 00154 ; Index := Num number bytes + Num BCD bytes - 1
. 00155
.0000054C 00156 Format1:
.0000054C 2449 00157 move.l A1,A2 ; Index to BCD digits
.0000054E 1A03 00158 move.b D3,D5 ; Number of bytes in converted BCD
. 00159
.00000550 00160 Format2:
.00000550 1012 00161 move.b (A2),D0 ; Isolate lower nybble
.00000552 0240 000F 00162 andi #$F,D0
.00000556 0C00 0005 00163 cmpi.b #4+1,D0 ; If greater than 4, add 3
.0000055A 6500 0004 (00000560) 00164 blo FormatLoNotGT4
. 00165
.0000055E 5600 00166 addq.b #3,D0
. 00167
.00000560 00168 FormatLoNotGT4:
.00000560 1812 00169 move.b (A2),D4 ; Isolate upper nybble
.00000562 0244 00F0 00170 andi #$F0,D4
.00000566 0C04 0050 00171 cmpi.b #$40+$10,D4 ; If greater than 4, add 3
.0000056A 6500 0006 (00000572) 00172 blo FormatHiNotGT4
. 00173
.0000056E 0604 0030 00174 addi.b #$30,D4
. 00175
.00000572 00176 FormatHiNotGT4:
.00000572 8004 00177 or.b D4,D0 ; Combine nybbles
.00000574 1480 00178 move.b D0,(A2)
.00000576 538A 00179 subq.l #1,A2
.00000578 5305 00180 subq.b #1,D5 ; More BCD digits to check?
.0000057A 66D4 (00000550) 00181 bne Format2
. 00182
.0000057C 1012 00183 move.b (A2),D0 ; Shift the number left one bit
.0000057E E300 00184 asl.b #1,D0
.00000580 E314 00185 roxl.b #1,D4 ; Save X flag
.00000582 1480 00186 move.b D0,(A2)
.00000584 1A02 00187 move.b D2,D5
.00000586 5305 00188 subq.b #1,D5
.00000588 6700 0010 (0000059A) 00189 beq Format3 ; No additional bytes
. 00190
.0000058C 00191 FormatShiftNumber:
.0000058C 1022 00192 move.b -(A2),D0 ; Shift the rest of the number
.0000058E E20C 00193 lsr.b #1,D4 ; Recover X flag
.00000590 E310 00194 roxl.b #1,D0
.00000592 E314 00195 roxl.b #1,D4 ; Save X flag
.00000594 1480 00196 move.b D0,(A2)
.00000596 5305 00197 subq.b #1,D5
.00000598 66F2 (0000058C) 00198 bne FormatShiftNumber
. 00199
.0000059A 00200 Format3:
.0000059A 2449 00201 movea.l A1,A2 ; Shift the BCD digits left one bit
.0000059C 1A03 00202 move.b D3,D5
. 00203
.0000059E 00204 FormatShiftBCD:
.0000059E 1012 00205 move.b (A2),D0
.000005A0 E20C 00206 lsr.b #1,D4 ; Recover X flag
.000005A2 E310 00207 roxl.b #1,D0
.000005A4 E314 00208 roxl.b #1,D4 ; Save X flag
.000005A6 1480 00209 move.b D0,(A2)
.000005A8 538A 00210 subq.l #1,A2
.000005AA 5305 00211 subq.b #1,D5
.000005AC 66F0 (0000059E) 00212 bne FormatShiftBCD
. 00213
.000005AE 5301 00214 subq.b #1,D1 ; More bits to process?
.000005B0 669A (0000054C) 00215 bne Format1
. 00216
.000005B2 227C 00000767 00217 movea.l #Out+1,A1 ; Address the output string
.000005B8 5288 00218 addq.l #1,A0 ; Address MSB of BCD digits
.000005BA 4204 00219 clr.b D4 ; Clear output digit count
. 00220
.000005BC 00221 Format4:
.000005BC 1010 00222 move.b (A0),D0 ; Isolate upper digit
.000005BE 0200 00F0 00223 andi.b #$F0,D0
.000005C2 6600 0008 (000005CC) 00224 bne FormatEmitHi
. 00225
.000005C6 4A04 00226 tst.b D4 ; Leading zero?
.000005C8 6700 000E (000005D8) 00227 beq FormatSkipHi
. 00228
.000005CC 00229 FormatEmitHi:
.000005CC E808 00230 lsr.b #4,D0 ; Shift into lower nybble
. 00231
.000005CE 0600 0030 00232 addi.b #'0',D0 ; Convert to ASCII numeral
.000005D2 5289 00233 addq.l #1,A1
.000005D4 1280 00234 move.b D0,(A1)
.000005D6 5204 00235 addq.b #1,D4
. 00236
.000005D8 00237 FormatSkipHi:
.000005D8 1018 00238 move.b (A0)+,D0 ; Isolate lower digit
.000005DA 0200 000F 00239 andi.b #$F,D0
.000005DE 6600 0008 (000005E8) 00240 bne FormatEmitLo
. 00241
.000005E2 4A04 00242 tst.b D4 ; Leading zero?
.000005E4 6700 000C (000005F2) 00243 beq FormatSkipLo
. 00244
.000005E8 00245 FormatEmitLo:
.000005E8 0600 0030 00246 addi.b #'0',D0 ; Convert to ASCII numeral
.000005EC 5289 00247 addq.l #1,A1
.000005EE 1280 00248 move.b D0,(A1)
.000005F0 5204 00249 addq.b #1,D4
. 00250
.000005F2 00251 FormatSkipLo:
.000005F2 5303 00252 subq.b #1,D3 ; More digits?
.000005F4 66C6 (000005BC) 00253 bne Format4
. 00254
.000005F6 11C4 0767 00255 move.b D4,Out+1 ; Store length of result
.000005FA 6600 0012 (0000060E) 00256 bne FormatDone ; Check for all 0's
. 00257
.000005FE 103C 0001 00258 move.b #1,D0 ; Default to "0"
.00000602 11C0 0767 00259 move.b D0,Out+1
.00000606 103C 0030 00260 move.b #'0',D0
.0000060A 11C0 0768 00261 move.b D0,Out+1+1
. 00262
.0000060E 00263 FormatDone:
.0000060E 4E75 00264 rts
And for the Atmel AVR:
. 00296 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
. 00297 ;
. 00298 ; Format - Convert a number to ASCII decimal
. 00299 ;
. 00300 ; Input:
. 00301 ; The first bytes of Dabble = the number to convert
. 00302 ; R16 = number of bytes to convert
. 00303 ; R17 = number of bits to convert
. 00304 ; R18 = number of packed BCD bytes in result
. 00305 ;
. 00306 ; Output:
. 00307 ; Output string with length byte starting at Out+1
. 00308 ;
. 00309 ; Uses:
. 00310 ; R0
. 00311 ; R19
. 00312 ; R20
. 00313 ; R21
. 00314 ; R22
. 00315 ; R23
. 00316 ; R28
. 00317 ; R29
. 00318 ; R30
. 00319 ; R31
. 00320 ;
. 00321 ; Note:
. 00322 ; Implemented with the Double Dabble algorithm:
. 00323 ;
. 00324 ; https://en.wikipedia.org/wiki/Double_dabble
. 00325 ;
.0000ED 00326 Format:
.0000ED E0EB [1] 00327 ldi R30,low(Dabble) ; Clear the BCD digits
.0000EE E0F1 [1] 00328 ldi R31,high(Dabble)
.0000EF 2400 [1] 00329 clr R0
.0000F0 0FE1 [1] 00330 add R30,R17
.0000F1 1DF0 [1] 00331 adc R31,R0
.0000F2 2F72 [1] 00332 mov R23,R18
. 00333
.0000F3 00334 Format0:
.0000F3 9201 [2] 00335 st Z+,R0
.0000F4 957A [1] 00336 dec R23
.0000F5 F7E9=0000F3 [1/2] 00337 brne Format0
. 00338
.0000F6 2F62 [1] 00339 mov R22,R18 ; Determine address of BCD digits + 1
.0000F7 0F61 [1] 00340 add R22,R17 ; BCD digits are big endian order
.0000F8 E04B [1] 00341 ldi R20,low(Dabble) ; Index := Num number bytes + Num BCD bytes
.0000F9 E051 [1] 00342 ldi R21,high(Dabble)
.0000FA 0F46 [1] 00343 add R20,R22
.0000FB 1D50 [1] 00344 adc R21,R0
. 00345
.0000FC 00346 Format1:
.0000FC 2F32 [1] 00347 mov R19,R18 ; Number of bytes in converted BCD
. 00348
.0000FD 2FE4 [1] 00349 mov R30,R20 ; Address lowest BCD byte
.0000FE 2FF5 [1] 00350 mov R31,R21
. 00351
.0000FF 00352 Format2:
.0000FF 9162 [3] 00353 ld R22,-Z ; Isolate lower nybble
.000100 2F76 [1] 00354 mov R23,R22
.000101 706F [1] 00355 andi R22,$F
.000102 3065 [1] 00356 cpi R22,4+1 ; If greater than 4, add 3
.000103 F008=000105 [1/2] 00357 brlo FormatLoNotGT4
. 00358
.000104 5F6D [1] 00359 subi R22,$100-3 ; Add 3
. 00360
.000105 00361 FormatLoNotGT4:
.000105 7F70 [1] 00362 andi R23,$F0 ; Isolate upper nybble
.000106 3570 [1] 00363 cpi R23,$40+$10 ; If greater than 4, add 3
.000107 F008=000109 [1/2] 00364 brlo FormatHiNotGT4
. 00365
.000108 5D70 [1] 00366 subi R23,$100-$30 ; Add $30
. 00367
.000109 00368 FormatHiNotGT4:
.000109 2B67 [1] 00369 or R22,R23 ; Combine nybbles
.00010A 8360 [1] 00370 st Z,R22
. 00371
.00010B 953A [1] 00372 dec R19 ; More BCD digits to check?
.00010C F791=0000FF [1/2] 00373 brne Format2
. 00374
.00010D 9160 010B [2] 00375 lds R22,Dabble ; Shift the number left one bit
.00010F 0F66 [1] 00376 add R22,R22
.000110 9360 010B [2] 00377 sts Dabble,R22
. 00378
.000112 E0EC [1] 00379 ldi R30,low(Dabble+1)
.000113 E0F1 [1] 00380 ldi R31,high(Dabble+1)
.000114 2F31 [1] 00381 mov R19,R17
.000115 953A [1] 00382 dec R19
.000116 F029=00011C [1/2] 00383 breq Format3 ; No additional bytes
. 00384
.000117 00385 FormatShiftNumber:
.000117 8160 [1] 00386 ld R22,Z ; Shift the rest of the number
.000118 1F66 [1] 00387 rol R22
.000119 9361 [2] 00388 st Z+,R22
.00011A 953A [1] 00389 dec R19
.00011B F7D9=000117 [1/2] 00390 brne FormatShiftNumber
. 00391
.00011C 00392 Format3:
.00011C 2F32 [1] 00393 mov R19,R18 ; Shift the BCD digits left one bit
.00011D 2FE4 [1] 00394 mov R30,R20
.00011E 2FF5 [1] 00395 mov R31,R21
. 00396
.00011F 00397 FormatShiftBCD:
.00011F 9162 [3] 00398 ld R22,-Z
.000120 1F66 [1] 00399 rol R22
.000121 8360 [1] 00400 st Z,R22
.000122 953A [1] 00401 dec R19
.000123 F7D9=00011F [1/2] 00402 brne FormatShiftBCD
. 00403
.000124 950A [1] 00404 dec R16 ; More bits to process?
.000125 F6B1=0000FC [1/2] 00405 brne Format1
. 00406
.000126 E0EB [1] 00407 ldi R30,low(Dabble) ; Address the packed BCD digits
.000127 E0F1 [1] 00408 ldi R31,high(Dabble)
.000128 0FE1 [1] 00409 add R30,R17
.000129 1DF0 [1] 00410 adc R31,R0
. 00411
.00012A E0CA [1] 00412 ldi R28,low(Out+1+1) ; Address the output buffer
.00012B E0D1 [1] 00413 ldi R29,high(Out+1+1)
. 00414
.00012C 00415 Format4:
.00012C 9161 [2] 00416 ld R22,Z+ ; Isolate upper digit
.00012D 2F76 [1] 00417 mov R23,R22
.00012E 7F60 [1] 00418 andi R22,$F0
.00012F F411=000132 [1/2] 00419 brne FormatEmitHi
. 00420
.000130 2300 [1] 00421 tst R16 ; Leading zero?
.000131 F021=000136 [1/2] 00422 breq FormatSkipHi
. 00423
.000132 00424 FormatEmitHi:
.000132 9562 [1] 00425 swap R22 ; Shift into lower nybble
. 00426
.000133 5D60 [1] 00427 subi R22,$100-'0' ; Convert to ASCII numeral
.000134 9369 [2] 00428 st Y+,R22
. 00429
.000135 9503 [1] 00430 inc R16
. 00431
.000136 00432 FormatSkipHi:
.000136 707F [1] 00433 andi R23,$F ; Isolate lower digit
.000137 F411=00013A [1/2] 00434 brne FormatEmitLo
. 00435
.000138 2300 [1] 00436 tst R16 ; Leading zero?
.000139 F019=00013D [1/2] 00437 breq FormatSkipLo
. 00438
.00013A 00439 FormatEmitLo:
.00013A 5D70 [1] 00440 subi R23,$100-'0' ; Convert to ASCII numeral
.00013B 9379 [2] 00441 st Y+,R23
. 00442
.00013C 9503 [1] 00443 inc R16
. 00444
.00013D 00445 FormatSkipLo:
.00013D 952A [1] 00446 dec R18 ; More digits?
.00013E F769=00012C [1/2] 00447 brne Format4
. 00448
.00013F 2300 [1] 00449 tst R16 ; Store length of result
.000140 F421=000145 [1/2] 00450 brne FormatDone ; Check for all 0's
. 00451
.000141 E360 [1] 00452 ldi R22,'0' ; Default to "0"
.000142 9360 010A [2] 00453 sts Out+1+1,R22
. 00454
.000144 9503 [1] 00455 inc R16
. 00456
.000145 00457 FormatDone:
.000145 9300 0109 [2] 00458 sts Out+1,R16