为什么我的 Fibonacci 6502 在 144 和 233 时出现故障?

Why is my Fibonacci 6502 malfunctioning for 144 and 233?

以下程序:

PORTB = 00
PORTA = 01
DDRB = 02
DDRA = 03

E  = %10000000
RW = %01000000
RS = %00100000

VARX = 00
VARY = 01
VARZ = 02

NUM = 05
DIV = 06
RES = 07
MOD = 08

BACK_TO_FRONT = 20

  .org 00

reset:
  lda #%11111111 ; Set all pins on port A to output
  sta DDRA

  lda #%11100000 ; Set top 3 pins on port B to output
  sta DDRB

  lda #%00011100 ; Set 8-bit mode; 2-line display; 5x8 font
  sta PORTA
  lda #0         ; Clear RS/RW/E bits
  sta PORTB
  lda #E         ; Set E bit to send instruction
  sta PORTB
  lda #0         ; Clear RS/RW/E bits
  sta PORTB

  lda #%01110000 ; Display on; cursor on; blink off
  sta PORTA
  lda #0         ; Clear RS/RW/E bits
  sta PORTB
  lda #E         ; Set E bit to send instruction
  sta PORTB
  lda #0         ; Clear RS/RW/E bits
  sta PORTB

  lda #%01100000 ; Increment and shift cursor; don't shift display
  sta PORTA
  lda #0         ; Clear RS/RW/E bits
  sta PORTB
  lda #E         ; Set E bit to send instruction
  sta PORTB
  lda #0         ; Clear RS/RW/E bits
  sta PORTB

  lda #[=10=]
  sta VARX

  lda #
  sta VARY

  lda #$a
  sta DIV

loop:
  lda VARX

  clv
  clc
  adc VARY
  clc
  clv

  sta VARZ

  lda VARY
  sta VARX

  lda VARZ
  sta VARY

  lda VARY
  sta NUM


  ldx #[=10=]

  store_digits:  
    jmp divide

    return_from_div:

    lda MOD
        sta BACK_TO_FRONT, x

        inx

        lda RES
        sta NUM

        lda #[=10=]
        cmp NUM
        bcc store_digits

   dex

   print_digits:
    ldy BACK_TO_FRONT, x
    lda digit_table, y
    sta PORTA
    lda #RS         ; Set RS; Clear RW/E bits
    sta PORTB
    lda #(RS | E)   ; Set E bit to send instruction
    sta PORTB
    lda #RS         ; Clear E bits
    sta PORTB

    dex

    sec
    cpx #
    bcc print_digits

    ldx #[=10=]
    delay:
            lda #%00000100
            sta PORTA
            lda #RS         ; Set RS; Clear RW/E bits
            sta PORTB
            lda #(RS | E)   ; Set E bit to send instruction
            sta PORTB
            lda #RS         ; Clear E bits
            sta PORTB
        cpx #$f
        beq next

        inx

        jmp delay 

    next:

        lda #%10000000
        sta PORTA

    lda #0         ; Clear RS/RW/E bits
    sta PORTB
    lda #E         ; Set E bit to send instruction
    sta PORTB
    lda #0         ; Clear RS/RW/E bits
    sta PORTB

  jmp loop

divide:
  lda #[=10=]
  sta RES

  lda #[=10=]
  sta MOD

  div_loop:
    lda NUM
    cmp DIV
    bcc answer

    lda NUM

    sec
    sbc DIV
    clc
    clv

    sta NUM

    inc RES
    jmp div_loop

  answer:
    lda NUM
    sta MOD
    jmp return_from_div

digit_table:
  .word c0c
  .word $cc4c
  .word $ac2c
  .word $ec6c
  .word c1c


  .org $fffc
  .word reset
  .word [=10=]00

在 65C02(WDC 版本)上运行。连接到 ROM(从地址 0x8000 开始)和 RAM 芯片(地址 0x4000)和连接到 HD44780(1602 标准 LCD)的 VIA(65C22)。

程序有效,但部分有效。它输出 1 然后 2 然后 3 ... 然后 89 而不是 144 打印 1,而不是 233 打印 2。然后 1 再然后 98 ???然后是61.

您决定返回 print_digits 的方式不正确:

; I've omitted the SEC since it's pointless
cpx #
bcc print_digits

仅当 X 无符号小于 1 时,才会跳转到 print_digits。唯一可能为真的值是 0,因此以上也可以描述为跳转到print_digits 如果 X 等于 0。

如果我们查看整个 print_digits 循环,则可以使用以下伪代码对其进行描述:

x = numDigits - 1;
do
{
    print(digits[x]);
    x--;
} while (x == 0);

只有当 numDigits 为 1 或 2 时,才会给出正确的输出。对于任何大于此值的值,您将打印一位数字,然后退出循环。


你真正想要的是这样的:

x = numDigits - 1;
do
{
    print(digits[x]);
    x--;
} while (x >= 0);

即替换为:

dex
sec
cpx #
bcc print_digits

与:

dex                ; Updates the N flag after decrementing X
bpl print_digits   ; Jump if N is clear, i.e. if X >= 0