ВХОДНЫЕ ТОЧКИ TR-DOS
Способ работы со стандартными командами TR-DOS подробно приведен в её фирменной инструкции. При программировании на BASICе пользоваться ими легко и удобно. Однако при более сложной работе со SPECTRUMом возникает необходимость обращаться к операционной системе, минуя BASIC и интерпретатор TR-DOS, например, из программы, написанной в машинных кодах. Предлагаемый в фирменном руководстве к TR-DOS способ (имитация строки BASICа в кодах) громоздок и неудобен. Гораздо лучше обращаться непосредственно к операционной системе, находящейся в "теневом" ПЗУ. Для этого в TR-DOS существуют специальные возможности, и на некоторых из них я остановлюсь.
Включение DOS происходит при переходе на один из адресов, находящийся в диапазоне 15616-15871 (3D00-3DFF), т.е. там, где в основном ПЗУ находится таблица символов и, следовательно, при нормальной работе управление туда никогда не передается. Схема контроллера BETA сделана так, что при выборке команды в этом диапазоне адресов срабатывает триггер, который заменяет основное ПЗУ тeнeвым - DOS, одновременно становятся доступными порты контроллера (см. приложение). Обратное переключение происходит при переходе на любой адрес в ОЗУ, так что доступ к DOS весьма ограничен - Вы не можете непосредственно из своей программы обращаться ни к его портам, ни к ПЗУ, за исключением указанного диапазона адресов. Однако в этом диапазоне находятся все входные точки для вызова большинства необходимых функций DOS.
Фактически имеется 23 точки входа, однако применяются только некоторые из них, т.к. не все они известны. Основные входные точки начинаются с команды NOP (00), по-видимому, для компенсации задержки при переключении ПЗУ (возможен и запуск по следующему адресу):
DEC HEX
15616 3D00 - вход в DOS из BASIC.
15619 3D03 - вызов команды DOS из BASIC.
15622 3D06 - канал связи с дисковым файлом - программа ввода.
15629 3D0D - канал связи с дисковым файлом - программа вывода (в описании канала используется 3D0E).
15635 3D13 - выполнение команды, заданной в регистре "C" процессора (см. далее).
15652 3D24 - связана с инициализацией системной области DOS - если при вызове включен флаг "C", выделяется 112 байт для системной области DOS, и регистр HL устанавливается на начало этой области (5CC2). При обращении по адресу #3021 предварительно проверяется наличие системной области.
15663 3D2F - переход на любой адрес DOS.
Используя последнюю из указанных точек, можно получить полный доступ к TR-DOS ПЗУ. По адресу 15663 (#3D2F) вслед за командой NOP следует единственная команда RET. Она позволяет осуществлять переход по любому адресу DOS, предварительно помещенному на вершину стека, например, следующим образом:
LD HL,ADR_DOS ; адрес в DOS ПЗУ
CALL DOS ; чтобы получить на стеке адрес возврата
... ... ; продолжение программы
DOS PUSH HL ; на стеке-адрес подпрограммы DOS
JP #3D2F ; вызов подпрограммы через точку входа
Этот способ хорош в том случае, когда есть дизассемблированный текст программы TR-DOS с отмеченными адресами соответствующих подпрограмм. Любознательным читателям можно рекомендовать самостоятельно получить такой текст и разобраться в нем (необходимые для этого исходные коды можно записать: SAVE "DOS" CODE 0,16383). Правда, следует предупредить, что интерпретатор DOS написан крайне сложно и невразумительно. Процесс анализа дизассемблированного текста весьма напоминает решение кроссворда, только пользы от этого занятия несколько больше. Для облегчения задачи расшифровки кодов отметим участки, которые занимают некоторые процедуры и области данных:_
v5.01 |
v5.03 |
ПРОЦЕДУРЫ И ДАННЫЕ |
0000-0007 |
0000-0007 |
холодный старт; полная инициализация системы |
0008-000F |
|
RST8, инициализация, в DE задана вершина памяти |
0010-0012 |
|
RST10,вывод символа из регистра A, как в SOS |
0018-001A |
|
RST18,вывод строки символов, начиная с (HL); последний символ должен быть #00 или >#7F |
0020-0022 |
|
RST20, вызов программы из основного ПЗУ;
адрес задается двумя байтами, следующими после RST20 |
0028-002A |
|
RST28,возвращает в HL адрес текущего канала с учетом сдвига, заданного в регистре C |
0066-0068 |
0066-0069 |
переход на адрес обработки NMI от клавиши "Magic" |
0069- |
|
копирует стандартные литеры A...U в область UDG устанавливает стандартные значения системных переменных |
016C-01D2 |
|
вызов DOS из BASICа (через #3D03, т.е. 15619) |
01C7- |
|
LD A,(HL) и устанавливает флаг Z, если A=#0D или #80 |
01D3- |
01D3- |
выход из DOS после выполнения команды;
литеры #0D,#0F,#10,#11 подпрограммы #3D13 (резерв) |
0239- |
|
вход в DOS из BASICа (через #3D00,т.е. 15616) |
0355-03A0 |
0360-03 AB |
название версии TR-DOS |
03FB- |
0405- |
выполнение литеры #18 подпрограммы #3D13 |
0429- |
|
команда CAT |
0530- |
|
команда NEW |
0686- |
|
команда COPY |
077D- |
|
команда ERASE |
07F6-0FFF |
0800-0FFF |
свободные ячейки памяти (около 2 KB #FF) |
1000- |
|
команда "*" |
1003-1017 |
|
текст "Подсоединен интерфейс 1" |
108D-1138 |
10A5-1150 |
текст системной информации для LIST |
115D-11A7 |
|
печать LIST (регистр HL) в десятичной форме |
11B6- |
|
команда LIST |
1348- |
|
команда COPY s |
1514- |
|
команда COPY B |
1644- |
165C- |
выполнение литеры #08 подпрограммы #3D13 |
164C- |
1664- |
выполнение литеры #09 подпрограммы #3D13 |
1693- |
|
команда MOVE |
17DD-17DE |
|
Пересылка - LDIR, RET (нужно задать HL,BC,DE) |
17E0- |
|
команда VERIFY |
17E5- |
|
команда LOAD |
1971- |
|
команда PEEK |
1975- |
|
команда POKE |
197D- |
|
команда MERGE |
1A9C- |
|
команда SAVE |
1CBC- |
1CF0- |
выполнение литеры #0A подпрограммы #3D13 |
1CC7- |
|
команда RETURN |
1D19- |
|
команда RUN |
1E01- |
1E3D- |
выполнение литеры #05 подпрограммы #3D13 |
1E11- |
1E4D- |
выполнение литеры #06 подпрограммы #3D13 |
1E86- |
|
команда FORMAT |
1F7D-1F8D |
1FB9-1FC9 |
таблица |
1FAF- |
1FEB- |
выполнение литеры #16 подпрограммы #3D13 |
1FBA- |
1FF6- |
выполнение литеры #17 подпрограммы #3D13 |
1FC1- |
|
форматирование дорожки |
2051- |
|
проверка дорожки |
208A- |
|
форматирование дорожки, N-1 в регистре E |
213C- |
|
команда OPEN# |
260C- |
|
команда CLOSE |
26EF- |
2739- |
выполнение литеры #15 подпрограммы #3D13 |
271C-27F1 |
2766-283B |
тексты сообщений TR-DOS, начиная с "O.K." |
27F2- |
283C- |
переход с адреса #3D13, определение литеры команды |
2842-288D |
288C-28D7 |
таблица адресов подпрограмм, адресуемых регистром C при обращении через #3D13 |
288E- |
28D8- |
выполнение литеры #07 подпрограммы #3D13 |
2896- |
28E0- |
выполнение литеры #13 подпрограммы #3D13 |
2899- |
28E3- |
выполнение литеры #14 подпрограммы #3D13 |
28E5- |
|
при A=0 - перенос 16 байт заголовка из адреса HL в #5CDD, при A<>0 - из #5CDD по адресу HL |
28A8- |
28F2- |
выполнение литеры #0C подпрограммы #3D13 |
28B1- |
28FB- |
выполнение литеры #0B подпрограммы #3D13 |
28C5- |
290F- |
выполнение литеры #0E подпрограммы #3D13 |
28DC- |
2926- |
выполнение литеры #12 подпрограммы #3D13 |
294D- |
|
команда "40" |
2964- |
|
команда"80" |
2968-29EA |
29B1-2A34 |
тексты сообщений TR-DOS, начиная с "*ERROR*" |
2A09-2A0B |
|
вывод в порт - OUT (C),A и RET |
2A0C- |
2A56-2A06 |
обслуживание запроса прерывания NMI от клавиши "Magic" |
2D57- |
|
команда GOTO |
2F79-2F7B |
|
запись команды из регистра A в ВГ93 |
2FA9-2FE7 |
|
таблица |
30B3-317B |
30FD-31F2 |
тексты ключевых слов TR-DOS, начиная с "SAVE" |
317E- |
2FF3-3031 |
таблица |
31B3-3C00 |
|
свободные ячейки памяти (2637 байт #FF) |
3D00-3D2F |
3D00-3D2F |
область стандартных точек входа в TR-DOS |
3D8E- |
3D98- |
выполнение литеры #00 подпрограммы #3D13 |
3DC1- |
3DCB- |
выполнение литеры #01 подпрограммы #3D13 |
3E3A- |
3E44- |
выполнение команды ВГ93 из регистра B, |
|
|
данные в регистре A |
3E59- |
3E63- |
выполнение литеры #02 подпрограммы #3D13 |
3EF8- |
3F02- |
выполнение литеры #03 подпрограммы #3D13 |
3EFC- |
3F06- |
выполнение литеры #04 подпрограммы #3D13 |
3F09- |
|
чтение дорожки (со всей служебной информацией) |
3FB0- |
|
процедура блочной записи - OUTI и RET |
3FE6-3FFF |
31FD-3C00 |
свободные ячейки |
Обратите внимание, что ПЗУ версии 5.01 содержит более 4кб свободного пространства, открывая широкие перспективы по его доработке, пока слабо освоенные.