【问题标题】:What does the Commodore PET BASIC assemble starting from $00C2?Commodore PET BASIC 从 $00C2 起组装什么?
【发布时间】:2015-10-30 21:42:46
【问题描述】:

我发现的 PET 的零页内存映射声称零页地址范围$00C2..$00D9 用于静态数据,例如http://www.classiccmp.org/dunfield/pet/petmem.txt 说:

 RIDATA 00C2        Cassette Temp (64#00AA) read flags: 0=scan,
                    1-15=count, $40=load, $80=end of tape marker
 RIPRTY 00C3        Cassette Short Cnt (64#00AB): counter of seconds
                    before tape write / checksum
 PNT    00C4-00C5   Pointer: Current Screen Line Address
 PNTR   00C6        Cursor Column on Current Line
 SAL    00C7-00C8   Pointer: Tape Buffer/ Screen Scrolling
 EAL    00C9-00CA   Tape End Addresses/End of Program
 CMP0   00CB-00CC   Tape Timing Constants
 QTSW   00CD        Flag: Editor in Quote Mode, $00 = NO
 BITTS  00CE        Cassette Temp (64#00B4): Tape read timer flag
                    =IRQ enabled for Timer 1
        00CF        End of tape read
        00D0        Read character error
 FNLEN  00D1        Length of Current File Name
 LA     00D2        Current Logical File Number
 SA     00D3        Current Secondary Address
 FA     00D4        Current Device Number
 LNMX   00D5        Physical Screen Line Length
        00D5        4.80: right side of window
 TAPE1  00D6-00D7   Pointer: Start of Tape Buffer
 TBLX   00D8        Current Cursor Physical Line Number
 DATAX  00D9        Current Character to Print

但是,查看ROM反汇编,可以找到地址$00C2跳转到的地方,例如。 http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/d/rom-1.html#C70A

 C70A  4C C2 00             JMP iC2       

在启动 PET 后查看从 $00C2 开始的反汇编,我可以看到看起来合理的代码:

.C:00c2  E6 C9       INC $C9
.C:00c4  D0 02       BNE $00C8
.C:00c6  E6 CA       INC $CA
.C:00c8  AD 00 04    LDA $0400
.C:00cb  C9 3A       CMP #$3A
.C:00cd  B0 0A       BCS $00D9
.C:00cf  C9 20       CMP #$20
.C:00d1  F0 EF       BEQ $00C2
.C:00d3  38          SEC
.C:00d4  E9 30       SBC #$30
.C:00d6  38          SEC
.C:00d7  E9 D0       SBC #$D0
.C:00d9  60          RTS

这个区域是做什么用的?将这个程序组装到这个区域的代码在哪里?这段代码应该做什么? (它似乎正在扫描从$0400 开始的区域以查找: 字符?)

【问题讨论】:

    标签: assembly jit 6502 commodore


    【解决方案1】:

    它是 BASIC 解释器循环的一部分。它读取标记化的 BASIC 程序的一个字节,如果是冒号或零字节则设置零标志,如果是数字则清除进位。您可以在 address C6B5 看到它在解释器循环的主要部分中使用。

    我不确定为什么将这个例程放在零页中。使用 LDA $0400 比使用 LDA ($C9),Y 快一个周期(或很少两个周期),但我看不出它实际上有什么不同。

    我还应该注意,您正在查看的 ROM 反汇编似乎适用于 BASIC 1.0 ROM,而您引用的内存映射适用于 2.0 和 4.0 版本。

    以下是 Sheldon Leemon 的 Mapping the Commodore 64 对等效 C64 例程的评价:

    115-138   $73-$8A   CHRGET
    子程序:获取下一个 BASIC 文本字符

    ...

    CHRGET 是 BASIC 用于读取文本字符的关键例程, 例如正在解释的 BASIC 程序的文本。它 放置在零页上以使例程运行得更快。由于它保持 跟踪例程中正在读取的字符的地址 例程本身必须在 RAM 中才能更新该指针。 指向当前正在读取的字节地址的指针真的是 LDA 指令的操作数。从 CHRGET 输入时, 例程通过修改 TXTPTR 处的操作数来递增指针 (122, $7A),从而允许读取下一个字符。

    在 CHRGOT (121, $79) 处输入允许读取当前字符 再次。 CHRGET 例程跳过空格,设置各种标志或 状态寄存器 (.P) 以指示读取的字符是否为 数字、语句终止符或其他类型的字符,并返回 在累加器 (.A) 中使用检索到的字符。

    ...

    由于这是一个中心例程,因此给出了反汇编列表 如下,以便更好地了解其工作原理。

    115 $73   CHRGET  INC TXTPTR   ; increment low byte of TXTPTR
    117 $75           BNE CHRGOT   ; if low byte isn't 0, skip next
    119 $77           INC TXTPTR+1 ; increment high byte of TXTPTR
    121 $79   CHRGOT  LDA          ; load byte from where TXTPTR points
                                   ; entry here does not update TXTPTR,
                                   ; allowing you to readl the old byte again
    122 $7A   TXTPTR  $0207        ; pointer is really the LDA operand
                                   ; TXTPTR+1 points to 512-580 ($200-$250)
                                   ; when reading from the input buffer
                                   ; in direct mode
    124 $7C   POINTB  CMP #$3A     ; carry flag set if > ASCII numeral 9
    126 $7E           BCS EXIT     ; character is not a numeral--exit
    128 $80           CMP #$20     ; if it is an ASCII space...
    130 $82           BEQ CHRGET   ; ignore it and get next character
    132 $84           SEC          ; prepare to subtract
    133 $85           SBC #$30     ; ASCII 0-9 are between 48-57 ($30-$39)
    135 $87           SEC          ; prepare to subtract again
    136 $88           SBC #$D0     ; if < ASCII 0 (57, $39) then carry is set
    138 $8A   EXIT    RTS          ; carry is clear only for numeral on return
    

    累加器(.A 寄存器)保存读取的字符 退出例行程序。可以测试的状态寄存器 (.P) 位 对于退出是:

    如果字符是 ASCII 数字 0-9,则进位清除。携带套装, 否则。仅当字符是语句终止符时设置为零 0 或 ASCII 冒号,58 ($3A)。否则,清零。

    【讨论】:

    • 它还保留了YX,这将花费更多的周期。
    • @Ross Ridge:我已将我的问题和您的答案复制到新开放的 Retrocomputing.SE 网站:retrocomputing.stackexchange.com/q/91/115
    • @Cactus 确保您正确归属问题和答案的来源。否则您的帖子可能会被删除。该网站处于私人测试阶段,因此我无法验证您是否已这样做。
    • FWIW,Applesoft BASIC 在 Apple II(地址 $B1)上使用相同的例程。
    • @fadden 它可能出现在从 Microsoft BASIC 派生的所有基于 6502 的实现中。
    【解决方案2】:

    它是自修改代码,注意$C9 处的嵌入指针。它的来源在$E0B4,并通过$E0E5 的代码复制到零页。

    看起来确实是在扫描文本,并对当前字符进行分类。如果字符是空格,它将设置ZF,如果是数字,它将设置CF。因此,将字符串转换为数字似乎很有用,但这只是猜测。

    更新:使用此代码的示例例程位于$C863。它肯定是在做一些字符串到数字的转换,你可以识别循环计算result = result * 10 + (current_char - '0')的模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-19
      • 2014-04-26
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      相关资源
      最近更新 更多