m68k Hex to Decimal not working right
Вопрос
I'm writing a small OS for a M68k computer that I'm developing, and I've ran into a little issue. I need to be able to show the user a hexadecimal value (say $1F) in decimal (31.) I've written the following code for doing that, but it has a few issues:
ConvertHexByteToDecimal:
move sr, -(sp) ; Back up status register to stack.
move #$2700, sr ; Disable interrupts.
move.b d2, -(sp) ; Back up d2 to the stack.
and.b #$0F, d2 ; Get rid of the high nybble
cmp.b #$9, d2 ; Is the low nybble in the range of 0-9?
bgt.s @convertHex ; If not, branch.
move.b (sp)+, d3 ; Restore the 10's place from the stack
and.b #$F0, d3 ; Get rid of the low nybble
add.b d3, d2 ; Add the 10's place.
bra.s @done ; If so, branch.
@convertHex:
sub.b #$A, d2 ; Subtract $A from the hexadecimal meeper.
move.b (sp)+, d3 ; Restore the 10's place from the stack
and.b #$F0, d3 ; Get rid of the low nybble
add.b #$10, d3 ; Add 1 to the 10's place.
add.b d3, d2 ; Add the 10's place to the number.
@done:
move.b d2, d1 ; Copy to output register.
move (sp)+, sr ; Restore status register.
rts ; Return to sub.
The code works nicely on values up to $F. For example, if I input $B, it outputs 11. However, once the numbers go past $F, it starts being broken. If I input $10 into it, I get 10 outputted, and so on. It always wraps back after a $xF.
Does anyone have any ideas as to why it's doing this?
Решение
If you're trying to output a number as decimal, you won't be able to do it by processing one nybble at a time. Powers of two and powers of ten do not mesh, other than 100 == 20 == 1
.
All other non-negative powers of 10 end with a 0
while non-negative powers of two end with 2
, 4
, 6
or 8
(never 0
).
To solve this, the idea is to use division by powers of ten to get what you want. Assembly-like psuedo-code like:
// Desired value is in num
push num // example $1f/31
if num < 100 goto tens // no hundreds, so skip
val = num / 100 + '0'
output val
num = num % 100
tens:
if num < 10 goto ones // is >= 10 so do this bit
val = num / 10 + '0' // gives us '3'
output val
num = num % 10 // remainder is 1
ones:
val = num + '0' // gives us '1'
output val
pop num
Note that we're doing the same sort of operations as your code but you're effectively doing base-16 division and modulus rather than base-10.
You'll have to convert that pseudo-code into 68k yourself, it's been about two decades since I cut code for that chip.