m68k 十六进制到十进制无法正常工作
我正在为正在开发的 M68k 计算机编写一个小型操作系统,但遇到了一个小问题。我需要能够以十进制 (31) 向用户显示十六进制值(例如 $1F)。我为此编写了以下代码,但它有一些问题:
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.
该代码在高达 $ 的值上运行良好F。例如,如果我输入 $B,它会输出 11。但是,一旦数字超过 $F,它就会开始被破坏。如果我输入 10 美元,就会输出 10 美元,依此类推。它总是在 $xF 之后回绕。
有谁知道它为什么这样做?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您尝试将数字输出为十进制,则无法通过一次处理一个半字节来完成此操作。除
100 == 20 == 1
之外,二的幂和十的幂不啮合。所有其他 10 的非负幂以
0
结尾,而 2 的非负幂以2
、4
、6 结尾
或8
(绝不是0
)。为了解决这个问题,我们的想法是使用十的幂除法来得到你想要的。类似汇编的伪代码:
请注意,我们正在执行与您的代码相同类型的操作,但您实际上是在执行以 16 为基数的除法和取模,而不是以 10 为基数。
你必须自己将该伪代码转换为 68k,自从我为该芯片削减代码以来已经有大约二十年了。
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 with2
,4
,6
or8
(never0
).To solve this, the idea is to use division by powers of ten to get what you want. Assembly-like psuedo-code like:
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.