Что собирает Commodore PET BASIC, начиная с $00C2?
Я обнаружил, что карты памяти нулевой страницы для 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
Однако, глядя на разборку ПЗУ, можно найти места, где адрес $00C2
например, http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/pet/d/rom-1.html:
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
за :
а также персонажи?)
2 ответа
Это часть цикла интерпретатора BASIC. Он читает один байт программы BASIC с токенами, устанавливает нулевой флаг, если это двоеточие, или нулевой байт, и очищает перенос, если это число. Вы можете увидеть, что он используется в основной части цикла интерпретатора по адресу C6B5.
Я не уверен, почему эта процедура была помещена в нулевую страницу. Это цикл (или редко два) быстрее использовать LDA $0400
над LDA ($C9),Y
, но я не вижу, чтобы это действительно имело большое значение.
Следует также отметить, что разборка ПЗУ, на которую вы смотрите, похоже, предназначена для ПЗУ BASIC 1.0, а карта памяти, на которую вы ссылаетесь, предназначена для версий 2.0 и 4.0.
Вот что Mapping Commodore 64 Шелдона Лимона говорит об эквивалентной процедуре C64:
115-138 $ 73- $ 8A CHRGET
Подпрограмма: Получить следующий основной текстовый символ...
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. Нести набор, в противном случае. Ноль Устанавливается только в том случае, если символ был оператором-терминатором 0 или двоеточием ASCII, 58 ($3A). В противном случае Zero Clear.
Это самоизменяющийся код, обратите внимание на встроенный указатель на $C9
, Источник для этого в $E0B4
и копируется на нулевую страницу с помощью кода в $E0E5
,
Похоже, что это действительно сканирование текста и классификация текущего символа. Это установит ZF
если символ является пробелом, и CF
будет понятно, если это цифра. Таким образом, это кажется полезным для преобразования строки в число, но это только предположение.
Обновление: пример подпрограммы, которая использует этот код в $C863
, Это, конечно, делает некоторое преобразование строки в число, вы можете распознать шаблон, который вычисляет result = result * 10 + (current_char - '0')
в петле.