Что собирает Commodore PET BASIC, начиная с $00C2?

Карты памяти нулевой страницы PET, которые я нашел, утверждают, что адрес нулевой страницы range$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

Однако, глядя на разборку ПЗУ, можно найти места, где происходит переход на адрес $00C2, например. http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/d/rom-1.html#C70A :

 C70A  4C C2 00             JMP iC2       

Глядя на дизассемблирование, начинающееся с $00C2 после загрузки PET, я вижу разумно выглядящий код:

.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, на наличие символов : и ?)


person Cactus    schedule 07.08.2015    source источник


Ответы (2)


Это часть цикла интерпретатора BASIC. Он считывает один байт токенизированной программы BASIC, устанавливая нулевой флаг, если это двоеточие или нулевой байт, и очищая перенос, если это число. Вы можете увидеть его использование в основной части цикла интерпретатора по адресу адрес C6B5.

Я не уверен, почему эта процедура была помещена на нулевую страницу. Использование LDA $0400 вместо LDA ($C9),Y на цикл (реже два) быстрее, но я не вижу особой разницы.

Я также должен отметить, что разборка ПЗУ, на которую вы смотрите, относится к ПЗУ BASIC 1.0, а карта памяти, на которую вы ссылались, относится к версиям 2.0 и 4.0.

Вот что говорится в Mapping the Commodore 64 Шелдона Лимона об эквивалентной подпрограмме C64:

115-138 $73-$8A CHRGET
Подпрограмма: Получить следующий текстовый символ BASIC

...

CHRGET — важная процедура, которую BASIC использует для чтения текстовых символов, таких как текст интерпретируемой программы BASIC. Он помещается на нулевую страницу, чтобы процедура выполнялась быстрее. Поскольку он отслеживает адрес считываемого символа внутри самой подпрограммы, подпрограмма должна находиться в ОЗУ, чтобы обновлять этот указатель. Указатель на адрес считываемого в данный момент байта на самом деле является операндом инструкции 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), которые можно проверить при выходе:

Carry Clear, если символ представляет собой цифру ASCII от 0 до 9. Carry Set, в противном случае. Нуль Устанавливается только в том случае, если символ был символом конца инструкции 0 или двоеточием ASCII, 58 ($3A). В противном случае нулевая очистка.

person Ross Ridge    schedule 07.08.2015
comment
Он также сохраняет Y и X, что потребует еще нескольких циклов. - person Jester; 07.08.2015
comment
@Ross Ridge: я скопировал свой вопрос и ваш ответ на недавно открытый сайт Retrocomputing.SE: retrocomputing.stackexchange .com/q/91/115 - person Cactus; 20.04.2016
comment
@Cactus Убедитесь, что вы правильно указали источник как вопроса, так и ответа. В противном случае ваш пост подлежит удалению. Сайт находится в закрытой бета-версии, поэтому я не могу проверить, сделали ли вы это или нет. - person Ross Ridge; 20.04.2016
comment
@RossRidge: я разместил его как «вики сообщества» и добавил ссылку на этот ответ в качестве комментария; Я думаю, этого должно быть достаточно. - person Cactus; 20.04.2016
comment
@Cactus Вам, вероятно, следует прочитать этот недавний и актуальный метапост: хотя правильно атрибутирован">meta.stackoverflow.com/questions/321299/ - person Ross Ridge; 20.04.2016
comment
FWIW, Applesoft BASIC использует идентичную процедуру на Apple II (по адресу $B1). - person fadden; 20.04.2016
comment
@fadden Вероятно, это во всех реализациях на базе 6502, полученных из Microsoft BASIC. - person Ross Ridge; 20.04.2016
comment
@RossRidge: этого нет в C128 Basic, который позволяет коду находиться в одном банке, а переменным — в другом. - person supercat; 13.05.2016

Это самомодифицирующийся код, обратите внимание на встроенный указатель на $C9. Исходник для него находится по адресу $E0B4, и он скопирован на нулевую страницу по коду по адресу $E0E5.

Похоже, он действительно сканирует текст и классифицирует текущий символ. Он установит ZF, если символ пробел, и CF будет ясно, если это цифра. Таким образом, это кажется полезным для преобразования строки в число, но это всего лишь предположение.

Обновление: пример подпрограммы, использующей этот код, находится по адресу $C863. Он, безусловно, выполняет некоторое преобразование строки в число, вы можете распознать шаблон, который вычисляет result = result * 10 + (current_char - '0') в цикле.

person Jester    schedule 07.08.2015