[an error occurred while processing this directive]

.цв

10. Описание системы для программиста.

.ов.

10.1. Введение.

В этой главе рассказывается о том, как Вы можете использовать возможности системы в своих программах на ассемблере (или на другом языке программирования, если пригодная для работы версия такового появится). Дабы при появлении новых версий системы не произошло конфуза, мы рекомендуем Вам использовать только документированные возможности системы. Не рекомендуем Вам также самостоятельно заниматься модификацией системы.

В первую очередь Вам могут пригодиться драйверы устройств (дисплея, клавиатуры, принтера, дисковода) и файловая система. Утилиты типа Секторного Редактора и Редактора Памяти как правило вызываются из программ весьма редко, а Отладчик - почти никогда. Кроме того, полезной может оказаться возможность создать на базе системы самогрузную программу.

Естественно, работающая в системе программа вполне может быть абсолютно автономной, т.е. не использовать возможностей, предоставляемых системой.

Для понимания главы требуется знание архитектуры машины и системы команд процессора. Эта информация может быть почерпнута из Технического описания ПЭВМ (Книга "Программирование аппаратных средств.").

При описании используются символьные имена, числовые значения которых можно найти в файле SYSTEM.H. Его вполне можно включить в свою ассемблерную программу командой CHN SYSTEM.H, после чего все имена станут доступны Вашей программе.

10.2. Карта памяти системы.

Для работы системы резервируется младшая половина (по адрес FFF) банка 0, установленного всегда на 0 сегмент. Там располагаются системные переменные и буферы, а также ряд системных подпрограмм. Вы можете использовать стек и половину (старше ZPFREE) нулевой страницы, кроме того 100 байт (RESBUF) зарезервировано для работы резидента.

Часть системных буферов Вы можете захватить в своей программе. Это SEBUF (текущий буфер секторного редактора, 100 байт), EXBUF (200 байт для исполнения команды EXEC, используя буфер надо быть уверенным, что Ваша программа не вызывается из командного файла), CATAL, VTOC (по 100 байт, используются при работе ДОС), TSLIST (100 байт, используется ДОС и как буфер входной строки), FUNBUF (100 байт для хранения переопределяемых клавиш в формате ASZ, т.е. текст клавиши ограничен нулем; в версии 5.0 использовался DCI-формат). Расположение этих буферов следующее:

========================
 Адрес:  Буфер:  Длина:
------------------------
  500    RESBUF   100
  600    SEBUF    100
  800    EXBUF    200
  A00    CATAL    100
  B00    TSLIST   100
  C00    VTOC     100
  F00    FUNBUF   100
========================

Память 200.4FF, 700.7FF, D00..EFF занята под переменные, таблицы, буферы и подпрограммы системы.

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

Собственно система располагается в банках E и F, занимая их полностью. Обычно они установлены на 6 и 7 сегменты.

Ячейка NVERS, расположенная в банке F, содержит младшую цифру номера версии системы.

Резидент располагается в банках 6 и 7, при его работе они устанавливаются на 6 и 7 сегменты. Не следует устанавливать на эти сегменты другие банки, если Вы собираетесь использовать подпрограммы системы. Манипулировать режимом работы псевдо-ПЗУ (6 и 7 сегментов) из резидента можно свободно (включать режим чтения или чтения/записи при старшем/младшем полубанке на 6 сегменте).

Отметим, что резидент читается начиная со старшей половины банка 6 (туда и передается управление при его активизации), далее заполняется банк 7, после чего (если резидент длинный) заполняется младшая половина банка 6. Автоматической установки векторов сброса и других прерываний на адресах FFFX не происходит: об этом должен заботиться сам резидент.

Банки 1..5 при загрузке системы и при сбросе устанавливаются на соответствующие (1..5) сегменты. Они считаются свободным пользовательским пространством. Именно через адреса 1800..BFFF происходит чтение/запись файла командами '[COPY', '[LOAD', '[RUN', '[SAVE', '[GET', '[PUT', '[READ', '[WRITE'. Именно здесь располагается исполняемая или отлаживаемая В-программа. Отметим, что система (в том числе упомянутые команды) не препятствует установке на сегменты 1..5 других банков, в том числе непосредственно в диалоге. При исполнении резидента или В-программы банки 1..5 вполне можно использовать в своих целях.

Банки 8, 9, A, B, C, D используются системой для хранения виртуального диска, а два последних еще и при колоночной печати. Поэтому, если планируется колоночная печать, размер RAM-диска следует уменьшить. Система сама подключает и отключает их от сегментов, когда это требуется. Отметим, что Ваша программа вполне может захватить для своей работы некоторые из этих банков. Если Вы можете обойтись двумя банками, желательно захватить банки C, D, дабы не лишать пользователя вовсе возможности работать с RAM-диском. Второе требование: объявить в описании программы максимальный размер RAM-диска (48/32/0 кб).

10.3. RAM-диск и доп-память в системе.

Доп-память всегда считается частью виртуального диска. Напомним, что система поддерживает только одну плату доп-памяти. Если Ваша программа не помещается в основной памяти, то Вы, естественно, можете захватить дополнительную память (если она есть в машине), уничтожив таким образом RAM-диск.

Информация о наличии или отсутствии доп-памяти помещается загрузчиком в ISRAM. Там хранится C2, если доп-память есть, и 0, иначе.

Подробнее остановимся на расположении в памяти RAM-диска на случай, если Вам понадобится написать нестандартный драйвер для него. Треки располагаются следующим образом (соответственно при отсутствии и наличии доп-памяти):

========================
Банки:  8  9  A  B  C  D
------------------------
Tреки: 11  1  3  5  7  9
        0  2  4  6  8  A
========================

Верхний трек расположен в младшем полубанке, сектора хранятся последовательно, от 0 до F. Понятно, что треков 7..A нет, если диск размечен на 32 кб.

====================================================
Банки:  0  1  2  3...b  c  d  e  f  8  9  A  B  C  D
----------------------------------------------------
Треки: 11  1  3  5..16 18 1A 1C 1E 20 22 24 26 28 2A
        0  2  4  6..17 19 1B 1D 1F 21 23 25 27 29 2B
====================================================

Сначала изображены банки доп-памяти (0..f). Треки 20..2B (или 28..2B) также могут не существовать.

Информацию о размере RAM-диска можно прочитать в ячейке SIZERAM. Там хранится номер первого несуществующего трека (возможные значения: 0, 7, B, 20, 28, 2C).

10.4. Карта системного диска.

Система располагается на диске не в файле, а непосредственно на треках 0..8, которые объявлены занятыми, причем на каждом из них используются только сектора 0..F.

Трек 0 содержит следующую информацию:

=================================
 Сектор:    Содержимое:
---------------------------------
 0, 9, A    Начальный загрузчик
 2, 3, 7    Подпрограммы 0 банка
 4          Переменные системы
 5          RESBUF
 6          SEBUF
 B, C, D, E Заставка системы
 F          FUNBUF
=================================
Треки 1..4 содержат тело системы, а треки 5..8 - резидент:
=======================================
 Трек:   Полубанк:   Трек:   Полубанк:
---------------------------------------
  1       E младш.    5       6 старш.
  2       F младш.    6       7 младш.
  3       F старш.    7       7 старш.
  4       E старш.    8       6 младш.
=======================================

Отметим, что исполнение команды '[STORE' приводит к сохранению не только банков 6 и 7, но и RESBUF. Команда '[STATUS' сохраняет на диске FUNBUF и 100 байт с адреса 400, содержащих различные переменные системы.

Ячейка BOOTMODE, расположенная в 4 секторе 0 трека, управляет работой загрузчика: если ее старший бит сброшен, то загрузка треков 5..8 не производится. Шестой бит управляет автозапуском резидента сразу после загрузки (независимо от функциональной клавиши "ST"): если он установлен, то резидент будет запущен. Сброшенный младший бит BOOTMODE запрещает системе проводить разметку RAM-диска при загрузке (иначе, если только он не был размечен раньше, система производит его разметку). Нормальной загрузке, таким образом, соответсвует BOOTMODE=81. Ячейка BOOTMODE предназначена, в основном, для создания самогрузных программ на базе системы.

10.5. Обращение к системе из программы.

Вызовы подпрограмм системы осуществляются передачей управления на точки входа (векторы), вынесенные в 0 банк. Их две группы (так сложилось исторически), причем первая группа (адреса 200..233) содержит просто JMP-ы на некоторые из точек второй группы (25F..301). Поэтому можно, например, пользоваться только второй группой, хотя первая покажется писавшим программы для "Best tool kit" более привычной. Вторая группа точек входа состоит из команд JSR на один и тот же адрес 0 банка, по которому расположен так называемый переключатель памяти, передающий управление системе.

Некоторые подпрограммы системы можно подменить на свои собственные, заменив адрес в JSR второй группы или заменив адрес в таблице описания точек входа (сохранив и восстановив при выходе в систему старые значения). Каждой точке входа соответствует 3 байта в таблице описания точек входа JSTAB, расположенные по адресу JSTAB+6+ADR-SYSPR, где ADR - адрес точки во второй группе, 6 - системный резерв. Первый байт описателя содержит информацию об устанавливаемых для исполнения подпрограммы банках памяти: 7 бит - резидент(1)/система(0), 4 младших бита - непосредственно режим псевдо-ПЗУ, остальные биты нулевые. Два следующих байта - адрес в RTS-формате, т.е. HL-1.

Данная манипуляция полезна, например, при работе с нестандартными устройствами (мышь, винчестер, сетевой дисковод) или при передаче системе (путем подмены стандартного ввода) входной строки для разбора и исполнения.

К сожалению, нельзя гарантировать, что система пользуется своими подпрограммами через переключатели. В каждом конкретном случае надо смотреть отдельно. Например, удается заменить нижний уровень драйвера печати, драйвер дисковода и исполнение команды ДОС.

Об использовании таймера и прерываний NMI, IRQ, RESET и BRK. Вы можете использовать таймер, лишь бы в момент обращения к дисководу он был выключен. Система имеет собственные обработчик BRK (регистры процессора A, X, Y, S, P сохраняются в AXYSP) и RESET. Создавая свои программы обработки прерываний, желательно производить следующие манипуляции:

- скопировать содержимое NMIL..NMIL+5 системы в резидент, если Ваша программа является резидентом,

- сохранить три ячейки, расположенные по адресу (NMIL), либо (NMIL+2), либо (NMIL+4), т.е. те ячейки, куда указывает аппаратный вектор,

- установить на их месте JMP на свою программу обработки,

- при выходе в систему, в том числе по сбросу, восстановить замененные ячейки.

Два слова относительно завершения программы. Плохим тоном является отсутствие в программе выхода в систему, требующее от пользователя давить 'СБР'. В отладочных целях программа может вываливаться по BRK. Штатным завершением программы может быть либо JMP DEBUG (JMP DDEBUG), либо просто RTS. В первом случае система производит некоторые инициализации, например восстанавливает вектора стандартного ввода/вывода, окно и т.д., а во втором случае этого не происходит, что позволяет передать управление системе временно, перенаправив стандартный ввод на свою программу.

10.6. Потоки стандартного ввода/вывода.

В этом и двух следующих параграфах упоминается ряд символьных имен, описанных в файле IOSUB.H (CHN IOSUB.H для использования).

Начнем с прояснения уже упоминавшихся понятий 'стандарный ввод' и 'стандартный вывод'. Диалог с системой осуществляется по поточному принципу, т.е. система получает команды посимвольно из потока стандартного ввода, а выводит символы в поток стандартного вывода. Поток - это просто подпрограмма, принимающая или выдающая символы, адрес которой хранится в CSWL, CSWH (вывод) и KSWL, KSWH (ввод). Замена этих ячеек позволяет организовать работу с командными файлами, переопределяемыми клавишами, а также вывод на принтер. Вам это позволит перенаправить стандартный вывод на свою программу, осуществляющую, к примеру, запись символов в некоторую область памяти для последующего сохранения в файле или другой обработки. Перенаправление стандартного ввода, как уже говорилось, позволяет заставить систему обработать какую-либо строку как введенную с клавиатуры, и потом вернуть управление Вашей программе. Предполагается, что Вы сохраните старое значение CSWL/H, KSWL/H и восстановите их при окончательном выходе в систему.

Отметим, что если Вы перенаправляете ввод/вывод не путем модификации таблицы JSTAB, а изменением CSWL/H, KSWL/H, то Ваша программа обработки не может располагаться в 6, 7 сегменте.

Секторный редактор и редактор памяти не пользуются поточным вводом/выводом. Также непосредственно с клавиатуры ожидается ввод при постраничном выводе, происходит обработка '/' в команде ДОС, отрабатывается 'ПРОБЕЛ' и 'F1' во время длинного вывода, редактируются переопределяемые клавиши.

Переопределяемые клавиши и клавиша вызова их редактора 'УПР К' распознаются системой только при вводе через стандартный ввод с клавиатуры. Ни при исполнении командных файлов, ни при непосредственном обращении к драйверу клавиатуры отработки переопределяемых клавиш не происходит.

В Вашей собственной программе также полезно пользоваться поточным вводом/выводом в том случае, если она ведет диалог по типу Бейсика или 'The Best', т.е. с построчным набором команд. Если же диалог организован через систему меню, то целесообразно производить обмен непосредственно с конкретным устройством.

Векторы стандартного ввода/вывода:

COUT (DCOUT) - вывод <вх: А>, <вых: A, X, Y не изм.>;

RDKEY (DRDKEY) - ввод <вых: A, регистр X не изм.>;

PRBL3 - вывод символа A X раз <вх: A, X>, <вых:X=0, Y не изм.>.

HEXO (DHEXO) - вывод <вх: A> в шестн. виде <вых: X, Y не изм.>;

HEXO1 (DHEXO1) - вывод мл. тетрады <вх: A> в виде шестн. цифры, <вых: X, Y не изм.>;

STROUT (DSTROUT) - вывод сообщения на устройство <вх: SIGVEC, и SIGVEC+1 = адрес (LH) таблицы адресов сообщений, Y - номер сообщения>, <вых: A, X, Y не изм.>.

Таблица адресов содержит адреса сообщений в формате DDB (т.е. HL), сообщения заканчиваются 0. Адреса сообщений, как и сами сообщения не должны распологаться в адресах D000..DFFF.

Кроме обычных для драйвера устройства управляющих кодов, сообщение может содержать следующие команды, управляющие выводом:

=============================================================
 ATXYS - курсор в позицию X, Y (следуют за командой);
 HTABS - курсор в столбец X (следует за командой);
 HRPS -  повторить N раз символ S, за командой следуют N, S,
         после вывода символа курсор сдвигается вправо;
 VRPS -  повторить N раз символ S, за командой следуют N, S,
         после вывода символа курсор сдвигается вниз;
 JMPS -  за командой следуют два байта - адрес продолжения
         сообщения в формате DDB.
=============================================================

При выходе из программы желательно восстановить SIGVEC/SIGVEC+1.

INPUT - ввод строки в INBUF, используется системой для организации диалога с пользователем, <вых: INBUF - сообщение, заканчивается 8D, X - поз. курсора во введенной строке>.

10.7. Вывод на экран и ввод с клавиатуры.

Вывод производится на экран, страший байт адреса начала которого расположен в SCRBASE, цветом COLOR (установленный бит 7 - режим 64*32, иначе 32*32), в окно, описываемое следующими параметрами:

WNDLFT - левый отступ, байт;

WNDWDTH - ширина, байт;

WNDTOP - верхний отступ, строк;

WNDBTM - нижняя граница, строк.

Символ помещается в место расположения курсора (реально курсор виден только при вводе с клавиатуры). Оно хранится в CH (X-координата от WNDLFT, байт, можно изменять), CV (Y-координата, строк), BASL/BASH (адрес начала текущей строки). После вывода курсор смещается к следующему символу. Если при смещении курсора достигается верхняя/нижняя граница окна, то оно роллируется вниз/вверх, при этом ячейки BAS2L/H используются как рабочие.

Проиллюстрируем назначение ячеек рисунком:

┏════════════════════════════════┓
|          ↑       ↑        ↑    |
|        WNDTOP    CV    WNDBTM  |
|          ↓       |        |    |
|        ╔═══════════════╗  |    |
|        |         ↓     |  |    |
|←WNDLFT→|←CH═════→      |  |    |
|        |     окно      |  |    |
|        |               |  |    |
|        |←WNDWDTH══════→|  |    |
|        ╚═══════════════╝  ↓    |
┗════════════════════════════════┛

После изменения размеров окна или для изменения CV следует вызвать VTAB (DVTAB) или произвести возврат каретки, чтобы BASL/H пересчитались соответствующим образом. После изменения SCRBASE следует вызвать SCRES (DSCRES) или VTAB (DVTAB) с той же целью.

Драйвер экрана отрабатывает ряд управляющих кодов: LEFTC/RIGHTC/UPC/DNC соответствуют стрелкам, LFDC/RETC - возврату каретки, DELC/INSC вычеркивают/вставляют символ, CLSC/EOPC/EOLC очищают экран/конец экрана/конец строки, BELLC издает звуковой сигнал, NORC/INVC устанавливают нормальный/инверсный режим, REDC/GRNC/YELC/BLUEC/VIOLC/NAVYC/WHITC - цвета.

Код BLOSC запрещает вывод на экран. После него все символы до следующего BLOSC не отображаются. Установленный ст. бит BLOCSCR соответствует блокированному выводу (можно изменять).

При вводе с курсором его цвет (32*32) хранится в CURCOL, а символ (64*32) - в CURSOR (можно менять). Рабочие ячейки RNDL/H используются, в частности, для организации мерцания курсора в режиме 64*32. При вводе с курсором в YSAV1 - символ, на котором стоял курсор.

Векторы драйверов экрана и клавиатуры:

COUT1 (DCOUT1) - вывод на экран <вх: А>, <вых: A, X, Y не изм.>;

TBS - курсор влево <вых: X не изм.>;

TLF - курсор вниз <вых: X не изм.>;

THOME - очистка экрана <вых: X не изм.>;

VTAB (DVTAB) - установить CV <вх: А>, <вых: X, Y не изм.>;

GETKEY (DGETKEY) - ввод с клавиатуры с курсором <вых: А, X не изм.>;

INKEY (DINKEY) - ввод без курсора <вых: X, Y не изм>;

TRANSL - перекодирование <вх: А> как если бы он был введен с клавиатуры <вых: А; X, Y не изм.>;

SCRES (DSCRES) - восстановление K/CSWL/H, CV/CH, BASL/H, размеров окна, цвета, сброс BLOCSCR, включение соответствующего экранного режима.

10.8. Вывод на печать.

Драйвер принтера содержит два уровня. Нижний обеспечивает вывод на принтер байта и символа, а верхний - колоночную и рлонную печать, а также печать текстового экрана.

Для обращения к драйверу принтера нижнего уровня служат три вектора (возможен их перехват для обслуживания нестандартного принтера):

PRINIT (DPRINIT) - инициализация контроллера принтера <вых: Y не изм.>;

PRBYTE (DPRBYTE) - печать байта <вх: А>, <вых: Y не изм.>;

PRCHAR (DPRCHAR) - печать символа <вх: А> с перекодировкой согласно кодовой таблице принтера.

Во всех случаях в ячейке PSLOT должен хранится номер слота контроллера, умноженный на 10. При отсутствии принтера обнуление PSLOT приводит к блокировке верхнего уровня драйвера печати. При загрузке система находит контроллер принтера, установленный в слот с большим номером, и устанавливает PSLOT.

SYSPR - обращение к верхнему уровню драйвера печати <вх: А=PRPAG/PRSCR, PRMODE, PRINBUF>, <вых: PRSCR - текущий экран напечатан/PRPAG - переназначены CSWL/H на колоночную печать>.

Буфер PRINBUF содержит информацию, соответствующую команде '#':

  DS 1 число кодов инициализации принтера;

  DS ¤20 коды инициализации принтера.

Буфер PRMODE содержит:

  DS 1 режим: 0=рулон, 1=страницы с колонками;

  DS 6 параметры, соответствующие '"'.

Напомним значение параметров: число колонок, ширина колонки, число строк, пропуск до разделителя, разделитель, пропуск после.

Для выключения колоночной печати подайте PROFF на COUT.

.стSYSTEM.DOC.7

[an error occurred while processing this directive]