【问题标题】:Why is my Fibonacci 6502 malfunctioning for 144 and 233?为什么我的斐波那契 6502 在 144 和 233 时出现故障?
【发布时间】:2020-05-22 03:29:45
【问题描述】:

以下程序:

PORTB = $6000
PORTA = $6001
DDRB = $6002
DDRA = $6003

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

VARX = $4000
VARY = $4001
VARZ = $4002

NUM = $4005
DIV = $4006
RES = $4007
MOD = $4008

BACK_TO_FRONT = $4020

  .org $8000

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 #$0
  sta VARX

  lda #$1
  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 #$0

  store_digits:  
    jmp divide

    return_from_div:

    lda MOD
        sta BACK_TO_FRONT, x

        inx

        lda RES
        sta NUM

        lda #$0
        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 #$1
    bcc print_digits

    ldx #$0
    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 #$0
  sta RES

  lda #$0
  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 $8c0c
  .word $cc4c
  .word $ac2c
  .word $ec6c
  .word $9c1c


  .org $fffc
  .word reset
  .word $0000

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

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

【问题讨论】:

  • cpx #$1 / bcc print_digits 看起来不对。为什么你只想在X unsigned lower than 1 时继续打印数字?由于dex 更新了N 标志,您应该能够用bpl print_digits 替换打印循环的最后3 条指令。
  • 还有什么特殊原因导致您不使用jsr / rts 像往常一样从divide 调用和返回?
  • BPL = 在 Plus 上的分支,所以 dex 递减,直到它达到 0,然后再减 1。并且设置了负标志,因此不再设置跳跃。使用我想要的密件抄送(而 x 大于 1)。显然我得到了相反的结果:-) 它从 1 中减去 x 不?不像我想的那样来自 x 的 1?
  • 但是您在打印每个数字之后 递减 X,因此只要 X >= 0,您就希望保持循环,即使用 BPL
  • 您当前的代码基本上对应于x = numDigits-1; do { print(digits[x]); x--; } while (x == 0); 这显然只适用于由 1 位或 2 位数字组成的数字。

标签: assembly fibonacci 6502


【解决方案1】:

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

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

只有当X的无符号小于1时才会跳转到print_digits。唯一可能的值是0,所以上面也可以描述为如果@987654326跳转到print_digits @ 等于 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 #$1
bcc print_digits

与:

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

【讨论】:

  • 嗯,之前我尝试过 BNE 而不是 BCC,这会导致无限循环!
  • 零而不是 1(我想要 x != 0 ...)
  • bne 而不是原始代码中的bcc 不应导致无限循环。但是如果要打印的数字只包含一位数字,它会使你的循环执行大约 256 次。
  • 啊,好吧,是的,这正是发生的事情,并且输出了大量垃圾。所以 0-1 是 250 左右的下溢?
猜你喜欢
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
相关资源
最近更新 更多