m68k 十六进制到十进制无法正常工作

发布于 2024-12-22 11:45:55 字数 1356 浏览 1 评论 0原文

我正在为正在开发的 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

流殇 2024-12-29 11:45:55

如果您尝试将数字输出为十进制,则无法通过一次处理一个半字节来完成此操作。除 100 == 20 == 1 之外,二的幂和十的幂不啮合。

所有其他 10 的非负幂以 0 结尾,而 2 的非负幂以 246 结尾8(绝不是 0)。

为了解决这个问题,我们的想法是使用十的幂除法来得到你想要的。类似汇编的伪代码:

    // 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

请注意,我们正在执行与您的代码相同类型的操作,但您实际上是在执行以 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 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文