# ТЕХНИЧЕСКОЕ ОПИСАНИЕ КОНТРОЛЛЕРОВ "АЛЬТПРО"
с доп. памятью 64-512 Кб и версией ПЗУ не ниже 2.00

Фирмой "АльтПро" (экс-"Альтек") выпускаются контроллеры с дополнительной памятью 64, 128, 256, 512 Кб с одинаковой организацией. Все перечисленные контроллеры имеют 8 режимов работы доп. ОЗУ, различающихся, главным образом, адресами подключения дополнительной памяти с выработкой соответствующих сигналов отключения основных ПЗУ/ОЗУ, а также наличием или отсутствием доступа к HALT-режиму процессора БК. Поскольку распределение основной памяти в разных моделях БК существенно различается, часть режимов предназначена для использования с БК0010(-01), часть - с БК11М. Причём тип машины автоматически распознаётся при включении питания, и сразу подключается необходимый для работы режим.

Работа с дополнительной памятью осуществляется через программные запросы к специальному диспетчеру, получившему название "BIOS" по аналогии с IBM. Все точки входа BIOS расположены в области ПЗУ выше 167000 (эта часть получила название ROM-BIOS, она меняться не будет), обработка же запросов производится в загружаемой в ОЗУ части, называемой RAM-BIOS. Прямые обращения к этой части (кроме проверки наличия и считывания номера версии) не практикуются. Если RAM-BIOS в ОЗУ отсутствует, то большинство запросов будет вызывать сигнал ошибки - характерное затухающее подёргивание экрана с прерывистым звуковым сигналом.

BIOS обеспечивает бесконфликтное выделение памяти по запросу, освобождение памяти (обратная операция), пересылку либо обмен массивов, чтение/запись 1 слова, вызов подпрограммы из доп. памяти или безусловную передачу управления (JMP), изменение режима и др.

Корректное использование запросов BIOS обеспечивает взаимную совместимость программного обеспечения, переносимость программ на разные модели БК и контроллеров. Кроме того, использование запросов значительно упрощает и сокращает программы. (Короче, кто не использует запросы - тот сам виноват, такие программы распространять не будем и другим не советуем).

## УРОВНИ ЗАПРОСОВ BIOS

В распоряжении программистов имеется 3 уровня запросов BIOS: высокий, средний и низкий. Выделение памяти может быть произведено только на высоком уровне (выделенный фрагмент называется модулем), информация о модулях и свободной памяти содержится во внутреннем каталоге BIOS'а.

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

На среднем уровне используется обращение к памяти по логическому номеру сегмента (вся память разбита на сегменты длиной 20000 со сквозной нумерацией, несколько особых сегментов имеют меньшую длину). Такие запросы выполняются намного быстрее, так как отсутствует поиск в каталоге. При образовании модуля, используемого на среднем уровне, (при выделении памяти) необходимо установить признак неперемещаемости и затем с помощью спец. запроса получить фактическое значение логического номера сегмента.

На низком уровне используется обращение по коду режима и физическому адресу, что максимально быстро в рамках BIOS'а, но всё равно выполняется 40. чисто подготовительных операций (сохранение и восстановление регистров, вектора 4, блокировка СТОП, распознавание запроса и переключение режимов) + до 20. операций извлечения и контроля аргументов.

Поэтому в тех случаях, когда действительно нужна высокая скорость обращения к доп. памяти и при этом нельзя разместить используемые процедуры и данные просто внутри одного модуля, нужно вначале по запросу подключать требуемый модуль, затем работать с ним напрямую (по возможности без переключений), в конце возвращаться в исходный режим. Для максимально быстрого переключения режимов и страниц памяти служит особый запрос "сверхнизкого" уровня CH$WRK, который практически ничего не сохраняет и не проверяет, только переключает режим и передаёт управление, да ещё вписывает код нового рабочего режима в специальную ячейку @WRK$, что совершенно необходимо (для корректных возвратов) в том случае, если в процессе работы в новом режиме используются какие-либо запросы или могут происходить внешние прерывания, переключающие режимы. (При возвратах из других страниц и режимов код текущего рабочего режима извлекается из специального стека, расположенного внутри RAM-BIOS, ячейка WRK$ - указатель этого стека; в запросе CH$WRK - 19. операций, включая "BEQ", "JMP".)

При всех запросах, кроме оговорённых отдельно, стек не должен находиться выше 100000. Для выполнения этого условия рекомендуется использование запроса низкого уровня NEW$SP, обеспечивающего корректное образование нового стека.

## Запросы высокого и среднего уровней

Запросы высокого и среднего уровней имеют одинаковые точки входа, тип запроса определяется значением старшего байта аргумента, именуемого ниже "NASEG".

NASEG | - аргумент, в котором содержится имя модуля либо логический номер сегмента (=NAME/SEGMENT). Имя модуля (1 слово) представляет собой 2 символа (1-й - старший байт, 2-й - младший!), в старшем байте - идентификатор автора модуля, младший идентифицирует сам модуль. Если старший байт = 0, то это запрос среднего уровня и NASEG = логическому номеру сегмента; номера сегментов 376 и 377 обозначают текущий и DOS-режим соответственно (текущий - режим, из которого пришел запрос, DOS - режим ДОС, в него происходит выход по запросу EXIT$ - см. его описание).

Идентификатор автора модуля введён с целью предотвращения совпадения имён модулей разных авторов, список "занятых" знаков приведён в приложении 5 (просьба к программистам сообщать в АльтПро о "занимаемых" ими знаках).

ADRSME | - смещение от начала модуля, если это запрос высокого уровня, или от начала сегмента, если это запрос среднего уровня; если NASEG = 376 или 377, то ADRSME - физический адрес.

Описанные ниже запросы сохраняют R3-R5, остальные регистры, если это не оговорено отдельно, не сохраняются.

При вызове подпрограмм BIOS можно использовать только абсолютную адресацию!

### 1. Копирование или обмен массивов ( MOV$G )

            MOV     #ADRSME1,R0
            MOV     #ADRSME2,R1
            MOV     #LEN,R2
            JSR     R5,@#MOV$G      ;@#167520
            .WORD   NASEG1,NASEG2

Под номером 1 - массив-источник, под номером 2 - приёмник.

Отрицательное (NEG) значение LEN (длина в словах) обозначает обмен. Т.о., запрос обеспечивает обмен массивов длиной до 200000 байт.

### 2. Чтение или обмен одного слова ( CHW$G )

            JSR     R5,CHW$G        ;@#167517
            .WORD   ADRSME,NASEG

Обмен происходит с регистром R0; R1 - флаг (0 - обмен, иначе - чтение). Если R1=0 при выходе - ошибка.

### 3. Вызов подпрограммы из доп. памяти ( CAL$G )

            JSR     R5,CAL$G        ;@#167516
            .WORD   ADRSME,NASEG

Подпрограмме передаются R3-R5, из подпрограммы возвращаются все регистры. Можно использовать стандартную передачу параметров через стек, нельзя только в подпрограмме использовать адрес возврата (@SP) - он изменён!

На время работы вызываемой п/п блокируются прерывания по вектору 4 (программно - в @#4 заносится #STP$, в @#6 - #200, при возврате восстанавливаются прежние значения), и устанавливается высокий приоритет процессора (при возврате восстанавливается прежний).

Максимальная вложенность подпрограмм в RAM-BIOS v3.01 - 20 (decimal).

Если R1=0 при выходе, то произошла ошибка.

### 4. Безусловный переход ( JMP$G )

            JSR     R5,JMP$G        ;@#167515
            .WORD   ADRSME,NASEG

Аналогично блокируются прерывания по вектору 4 и устанавливается высокий приоритет процессора.

Если произошёл выход, то была ошибка, при этом R1=0.

### 5. Работа с каталогом, создание, удаление модулей и др. ( CAT$ )

            MOV     #NUMBER,R0      ;номер функции
            JSR     R5,@#CAT$       ;@#167521

R0=0 - создание модуля (создание записи о модуле в каталоге).

Аргументы:

R1 | - адрес записи, которую нужно занести в каталог (формат этой записи такой же, как у записи в каталоге - см. приложение 3; расположена она должна быть в основном ОЗУ - ниже 100000);
R2 | - код требуемого сегмента (см. прил. 2.2), если нужен определённый сегмент, или 0 - любой. В процессе обработки R2 очищается по маске #74000;

Следующие 2 параметра "предлагаемой" записи, а также признак #20, учитываются только при установленном бите #4 в <признаках> (см. прил.3). Это:

- код сегмента (т.е. R2 не равный 0);
- требуемое смещение модуля от начала сегмента (может быть равно 0) + 100000 - в слове <смещение> (см. прил.3).

Если после выхода R0=0, то модуль не создан из-за недостатка памяти или переполнения каталога. Если R0<0 - модуль под таким именем уже есть.

R0=2 | - безусловное удаление модуля (без проверки признаков и запуска END-2), в конце - переход к функции номер 6. Вход: R1 - имя модуля; R0 сохраняется.
R0=4 | - то же, но с вызовом END-2.

Если в запросах #2 и 4 после выхода R2=0 - ошибка.

R0=6 | - цикл удаления модулей, у которых отсутствуют родительские модули и которые не запрещено удалять в этом случае. R0, R2 сохраняются.
R0=10 | - чтение/запись слова каталога (через R1); после команды (JSR R5,@#CAT$) ещё два слова: имя, смещение (последнее – в записи каталога, см. ниже). Если в смещении установлен бит #100000, производится запись, иначе - чтение. Если R0 равен нулю после выхода - ошибка.
R0=12 | - возвращает информацию о RAM-BIOS. R0 - номер версии. Текущая версия - 3.05 (#305). R1 - физический адрес начала каталога модулей (он находится по данному адресу в системной странице в SYS-режиме, код включения = #2160), R2 - кол-во записей в каталоге.
R0=16 | - получение кода режима и адреса для обращения на низком уровне. Сохраняется R0. После команды (JSR R5,@#CAT$) ещё 2 слова: смешение, имя. Выход: R1 - физический адрес, R2 - код режима (из числа тех режимов, которые в двойной рамке в табл.1). Если R2=0 - ошибка.

## Общеупотребительные запросы низкого уровня

### 6. Сохранение области основной памяти ( SAVE$ )

            JSR     R5,@#SAVE$      ;@#167530

Вход: R0 - адрес вершины (т.е. адрес над областью); R1 - длина (вниз), байт; стек может быть в доп. памяти ( SP>100000 ).

Нормальный выход: R0,R1 не портятся. Нет места для сохранения: R0=0. Сохранение производится во внутреннем стеке сохранения RAM-BIOS, общий его объём в версии 3.01 - 1000 с небольшим байт.

Сохранение и восстановление (в резидентных программах) должно быть в одном вызове (прерывании), иначе может нарушиться порядок (LIFO: Last In - First Out).

### 7. Восстановление области памяти, сохранённой по SAVE$ (RESTO$)

            JSR     R5,@#RESTO$     ;@#167531

Регистры не портит, стек может быть в дополнительной памяти.

### 8. Создание нового стека в основном ОЗУ с его (ОЗУ) сохранением ( NEW$SP )

Вызов: | либо: | либо:
--- | --- | ---
    JSR R5,@#NEW$SP
    .WORD   TOP
    .WORD   LEN
    MOV #TOP,R0
    JSR R5,@#NEW$SP+2
    .WORD   LEN
    MOV #TOP,R0
    MOV #LEN,R1
    JSR R5,@#NEW$SP+4

NEW$SP=167630;
TOP | - адрес вершины нового стека (адрес над стеком);
LEN | - длина, байт (вниз) (для сохранения ОЗУ)

Старый стек может располагаться в доп. памяти (выше 100000).

НОРМАЛЬНЫЙ ВЫХОД: | разряд Z=0 (т.е. "не 0"), R0 не равно 0; SP = #TOP-2, @SP = <прежний SP>; портит R0,R1.
НЕТ МЕСТА ДЛЯ СОХРАНЕНИЯ: | Z=1, R0=0, SP и R1 не изменяются.

Сохранение области ОЗУ происходит по SAVE$ (см. выше) во внутреннем буфере BIOS'а стекового типа, его размер - 1000 с небольшим. При создании нового стека необходимо дополнительно резервировать min 44 байта в связи с дребезгом СТОП (наблюдался случай, когда прерывание по вектору 4 успевало произойти 8 раз, после чего подряд 8 RTI и т.д.).

Возврат в старый стек с восстановлением ОЗУ:

            MOV     @SP,SP
            JSR     R5,@#RESTO$     ;@#167531

### 9. Быстрая установка/чтение кода текущего режима с передачей управления ( CH$WRK )

Вызов: | либо: | либо:
--- | --- | ---
    JSR R5,@#CH$WRK
    .WORD   mode
    .WORD   addr
    MOV mode,R0
    JSR R5,@#CH$WRK+2
    .WORD   addr
    MOV mode,R0
    JSR R5,@#CH$WRK+4

3-й вариант - без передачи управления (т.е. с возвратом на следующий за "JSR" адрес).

CH$WRK=167734;
ВХОД: | при mode <= 0 производится только считывание кода текущего режима (в R4) без установки нового, на передачу управления это не влияет;
ВЫХОД: | R4 = код текущего режима до выполнения CH$WRK; R5,R0 портятся (R0=177130).

Ничего не проверяет, не блокирует прерывания, не пользуется стеком (кроме первых 2-3 команд ещё до переключений режимов - т.е. нормально работает, даже если в новом режиме SP будет указывать на ПЗУ).

В подключаемом режиме в сегменте 160000... должен присутствовать ROM-BIOS.

### 10. Завершение работы программы и выход в ДОС ( EXIT$ )

            JSR     R5,@#EXIT$      ;@#167527

Инициализирует RAM-BIOS (в частности, очищает стек возвратов из подпрограмм, вызванных по запросам CAL$G и CAL$N) и выходит в режим "DOS", обычно на 100000 (см. прил.6). Таким образом, обеспечивается корректный выход в ДОС из любого режима. Также очищает стек сохранений (используемый запросами SAVE$ и NEW$SP).

Кроме того, удаляются модули, у которых установлен признак удаления по EXIT$, а также все модули, у которых отсутствует родительский модуль и при этом их удалять не запрещено ("удаление мусора").

## Прочие запросы низкого уровня

### 11. Пересылка или обмен массивов ( MOV$N )

            MOV     sadr,R0         ;адрес источника
            MOV     dadr,R1         ;адрес приёмника
            MOV     n,R2            ;длина массива - n слов
            JSR     R5,@#MOV$N      ;@#167526
            .WORD   smod,dmod       ;коды режимов источника,приёмника

Длина массива меньше 0 (NEG) означает обмен массивов, иначе - пересылка.

Коды режимов - это коды подключения режимов и страниц (см. прил.1) + флаги:

#100000 | - "любой режим" (устанавливать, если массив в основном ОЗУ или ПЗУ);
#40000 | - устанавливать, если в этом режиме в сегменте 160000... отсутствует ROM-BIOS (ПЗУ или его копия); в этом случае пересылка производится без обращения к ROM-BIOS (п/п пересылки - в стеке);

Код режима = 0 означает текущий рабочий режим (берётся из ячейки @WRK$ - при штатном использовании запросов BIOS, включая CAL$.., JMP$.., эта ячейка всегда содержит код текущего режима). Правильность установки флагов режимов не контролируется.

Все регистры сохраняются. Стек должен быть ниже 100000. Перекрытие массивов приведёт к ошибке, если приёмник выше источника. Если заданы несовпадающие режимы и отсутствует флаг #100000, пересылка ведётся через основное ОЗУ (с адреса = SP) с его сохранением, перекрытия и пересылка из ПЗУ в этом случае недопустимы.

### 12,13. Чтение и обмен слов ( RDW$N и CHW$N )

        JSR     R5,@#RDW$N или @#CHW$N      ;@#167524 или @#167525
        .WORD   addr, mode & flags

Читает слово в R0 или обменивает с R0.

Флаги и 0 означают то же, что и в MOV$N. В случае установки флага #40000 чтение и обмен производятся в несколько раз медленнее, чем без него.

### 14,15. Вызов подпрограммы и безусловный переход (CAL$N и JMP$N)

        JSR     R5,@#CAL$N или @#JMP$N      ;@#167522 или @#167523
        .WORD   addr,mode

В отличие от предыдущих запросов учитывается только реальный код режима и страницы (флаги и 0 не интерпретируются); CAL$N и JMP$N применимы только для тех режимов и страниц, в которых в сегменте 160000... есть ROM-BIOS.

Подпрограмме передаются и из подпрограммы возвращаются все регистры. Можно использовать стандартную передачу параметров через стек, нельзя только в подпрограмме использовать адрес возврата (@SP) - он изменён!

На время работы вызываемой по CAL$N п/п блокируются прерывания по вектору 4 (программно - в @#4 заносится #STP$, в @#6 - #200, при возврате восстанавливаются прежние значения), и устанавливается высокий приоритет процессора (при возврате восстанавливается прежний).

Максимальная вложенность подпрограмм в RAM-BIOS v3.01 - 20.

### 16-18. Точки входа переключения режимов ( MOD$, MOD$S, MOD$J )

Подключение режима R4 ( @#167754 ): | Подключение системного режима (с RAMBIOS) ( @#167744 ): | Подключение режима R4 & JMP ( @#167752 ):
--- | --- | ---
    JSR R4,@#MOD$
    JSR R4,@#MOD$S
    JSR  R4,@#MOD$J
    .WORD  ADDR

После физического переключения режима обращения к стеку отсутствуют, регистры (кроме R4) не портятся.

Приведённые запросы не меняют @WRK$ (код текущего режима на вершине стека возвратов), программисты должны сами заботиться о том, чтобы при переключённом режиме не было прерываний (так как возврат из прерываний, переключающих режимы, будет происходить в режим @WRK$ - а он другой).

Приведённые запросы выполняют только переключение и не содержат "лишних" операций, см. поставляемые в комплекте с документацией исходники.

## Использование стека запросами BIOS

В процессе обработки запросов BIOS (только вызываемых по "JSR R5,...", кроме CH$WRK) стек опускается на следующую глубину:

- общая обработка всех запросов опускает стек на 20 в максимуме, для простых запросов типа RDW$N, JMP$N, CAL$N это и есть предельное опускание стека;
- при обработке простых запросов высокого уровня в стек добавляется ещё несколько слов;
- пересылка массивов между разными страницами доп. ОЗУ опускает стек на 40 (всего - вместе с общей обработкой);
- если при этом при подключении одной из страниц отсутствует ROM-BIOS, то подпрограмма пересылки записывается в стек, что опускает его дополнительно ещё на 44;
- при этом нужно ещё иметь резерв в 44 байта на случай нажатия в этот момент кнопки СТОП - в наихудшем случае нам доводилось наблюдать 8 прерываний подряд от одного нажатия СТОП.

## Приложение 1. Режимы работы и распределение памяти.

Память в контроллерах "АльтПро" разбита на страницы по 32 Кб, части (сегменты) одной такой страницы подключаются в области адресов 100000-177777, сегменты разных страниц одновременно подключить нельзя. Сегментами ниже называются фрагменты памяти по 10000 байт. Сегмент с номером X=0...7 может быть подключён либо с адреса 1X0000, либо с адреса 1X0000+-40000 в зависимости от номера режима.

Распределение памяти в различных режимах приведено в табл.1, затем следуют пояснения общего характера, которые рекомендуется прочитать, и примечания специального характера, которые понадобятся тем, кто пишет некорректные программы; тем, кто пишет корректные программы, рекомендуем пользоваться запросами BIOS, значительно упрощающими работу с доп. памятью и предотвращающими конфликты.

Таблица 1. Режимы работы и распределение памяти.
Название режима | SYS | Std10 | ОЗУ10 | All | Std11 | ОЗУ11 | Hlt10 | Hlt11
Код включения | 160 | 60 | 120 | 20 | 140 | 40 | 100 | 20000
Вырабатываемые сигналы
Откл.монитора БК10 |  |  | + | + |  |  | + | +
Откл.монитора БК11М |  | + |  | + |  | + |  | +
Откл. верх.ОЗУ-11М | + | + | + | + |  |  |  |
АДРЕСА | номера подключаемых сегментов
HDD: 170-177000 | ПЗУ | 7 | 7 | 3 | 7 | 7 | 7 | 7
170(177000hdd)-0 | ПЗУ | - | 7W/- | 3R | - | - | 7W | 7W
160000-170000 | ПЗУ | ПЗУ | 6 | 2 | ПЗУ | 6 | 6R/6 | 6
150000-160000 | 1 | 5 | 5 | 1 | - | 5 | 5 | 5
140000-150000 | 0 | 4 | 4 | 0 | - | 4 | 4 | 4
130000-140000 | 7 | 3 | 3 | 7 | - | - | 3 | -
120000-130000 | 6 | 2 | 2 | 6 | - | - | 2 | -
110000-120000 | - | - | 1 | 5 | - | - | 1 | -
100000-110000 | - | - | 0 | 4 | - | - | 0R | -

ПОЯСНЕНИЯ

Буква 'W' после номера сегмента означает, что ОЗУ доступно только по записи, 'R' - только по чтению, через дробную черту - старая версия контроллеров / новая (по номеру версии ПЗУ не определяется), '-' - не подключается ничего.

ПЗУ в контроллерах имеет объём 10000 байт, в режиме SYS одно и то же ПЗУ подключается и со 160000, и со 170000 (благодаря этому изменяется адрес запуска компьютера).

В контроллерах "SMK" ("винтовых") во всех режимах, кроме SYS, в адресах 170000-177000 подключено ОЗУ, в дисководных - нет, выше 177000 - во всех одинаково.

Внутри таблицы в рамки выделены группы режимов и адресов, используемые при пересылке данных для доступа ко всем 8 сегментам страницы памяти (одна рамка для БК10, другая - БК11М: это области, неперекрывающиеся с ПЗУ и охватывающие всю страницу). Однако при размещении и вызовах подпрограмм на БК11М RAM-BIOS использует два первых режима (SYS и Std10) в окне 120000-140000, т.к. для работы с подпрограммами необходимо наличие ROM-BIOS в адресном пространстве.

РАСШИФРОВКА РЕЖИМОВ:

SYS - используется для запуска, пересылки данных на БК10 и RAM-BIOS'ом (он - всегда в 0-й странице);

Std10, Std11 - стандартные, традиционные режимы работы для БК10 и 11М соответственно, Std10 используется также для пересылки данных на БК10;

ОЗУ10 - вместо монитора БК10 и ПЗУ-160000 подключается ОЗУ (на многих БК10 требуется простая доработка, иначе доп. ОЗУ подключается параллельно ПЗУ монитора и приходится записывать в это ОЗУ копию монитора); используется также для доступа к доп. памяти на БК11М;

All - позволяет на БК10 подключить ОЗУ ко всему адресному пространству, что используется для загрузки копии Вильнюсского Бейсика; применяется также для доступа к доп. памяти на БК11М;

ОЗУ11 - подключение ОЗУ вместо ПЗУ на БК11М, для отключения ПЗУ монитора БК11М простая доработка требуется всегда;

Hlt10, Hlt11 - открывают доступ к HALT-режиму процессора на БК10 и БК11М соответственно. Максимально "продвинутые" режимы: везде, где можно, подключается ОЗУ вместо ПЗУ и на БК10 нижняя часть ОЗУ монитора защищена от записи (квази-ПЗУ) для повышения глюкоустойчивости.

Доработки для отключения ПЗУ монитора описаны в файле "СХЕМЫ.EDP".

На контроллерах с доп. ОЗУ менее 256 Кб на БК10 может быть подключено ПЗУ Бейсика традиционно записью #10 в 177130, правда на режимы ОЗУ это никак не влияет.

При подключении ОЗУ параллельно чему-либо (ПЗУ, регистры) в случае конфликта данных (в одном - 0, в другом - 1) в подавляющем большинстве случаев читается 1 (для микросхем такой конфликт не страшен, все они имеют внутреннюю защиту - хотя, конечно, конфликты снижают помехоустойчивость и потому нежелательны). Поэтому при параллельном подключении ОЗУ и ПЗУ в ОЗУ надо предварительно записывать копию ПЗУ, а при параллельном подключении ОЗУ и регистров в ОЗУ должны быть нули.

При включении режима "All" из режимов Hlt10, Hlt11 (а на "старых" контроллерах ещё и из режима ОЗУ10) в ОЗУ режима "All" по адресу 177130 вписывается <20 + код страницы>; при использовании запросов BIOS таких переключений не бывает.

КОДЫ ПОДКЛЮЧЕНИЯ СТРАНИЦ ОЗУ:

64 Кб - | 0,2000;
128 Кб - | 0,2000,4,2004;
256 Кб - | 0,2000,4,2004,10,2010,14,2014;
512 Кб - | 0,2000,4,2004,10,2010,14,2014, 1,2001,5,2005,11,2011,15,2015.

Объем памяти можно определить по байту 167777 ПЗУ контроллера (см. приложение 4).

При переключениях коды режима и страницы необходимо складывать по BIS.

## Приложение 2.1 Формат таблицы сегментов BIOS.

Вся память разделена на сегменты длиной 20000 (несколько особых сегментов имеют меньшую длину). Соответствие логических номеров физическим кодам сегментов задано в таблице, где каждый сегмент описывается одним словом. Адрес таблицы можно получить следующим образом после запроса CAT$ (вызов #12, результат в R1) при условии подключения страницы с RAM-BIOS'ом:

            SUB -(R1),R1
            MOV (R1)+,R2        ;R2 - кол-во сегментов
                                ;R1 - адрес начала таблицы

Кроме кода режима и кода страницы, которые мы упоминали ранее (см. также прил. 2.2), используются следующие биты:

#100000 | - сегмент подключается с адреса @#120000, иначе - с адреса 100000 на БК11М, 140000 - на БК10. На БК11М означает также, что при используемом в BIOS подключении этого сегмента одновременно с ним будет подключено и ПЗУ (т.е. будет доступен ROM-BIOS - используются режимы с кодами 160 и 60). Для размещения программ на БК11М используются именно такие сегменты, так как нужен доступ к ROM-BIOS.
#40000 | - длина сегмента меньше на #10000 (есть два стандартных случая установки этого бита: 10000 над RAM-BIOS'ом и 10000 перед 4 Кб с таблицей разделов).
#20000 | - вычитание из длины сегмента #650 (т.е. 177130-177777).
#10000 | - вычитание из длины сегмента #350 (для модема без винчестера в HALT-режиме, устанавливается совместно с битом #20000).
#4000 | - начало сегмента смещено на 10000 (устанавливается совместно с битом #40000).

## Приложение 2.2 Коды сегментов, используемые в BIOS.

Физические номера сегментов согласно табл.1 приложения 1 | Для БК10 | Для БК11М
--- | --- | ---
0, 1 | 160 + код.страницы | 20 + код.стр.
2, 3 | 100060 + код.страницы | 100120 + код.стр.
4, 5 | 60 + код.страницы | 120 + код.стр.
6, 7 | 100160 + код.страницы | 100020 + код.стр.

## Приложение 3. Формат записи каталога модулей.

Запись каталога имеет следующую структуру:

00 | слово | <имя> | - 1-й байт - идентификатор автора модуля (старший байт), байт=#0 используется для служебных целей; 2-й байт - идентификатор модуля;
02 | слово | <длина в словах> | - меньше 100000 (в словах);
04 | слово | <признаки>: |

#1 | - можно удалять при нехватке памяти (пока не используется);
#2 | - модуль нельзя перемещать (0 - можно). Необходимо устанавливать, если есть обращения к модулю на среднем или низком уровне;
#4 | - нельзя разбивать модуль на части (размещать в разных сегментах), 0 - можно;
#10 | - удалять модуль по запросу EXIT$ или перезапуску, 0 - да;
#20 | - возможность запуска модуля (1 - да; актуально для модулей, содержащих программы). Установка этого признака приводит к размещению с адреса 120000 до 140000, что актуально для БК11М (см. прил. 2.1), на БК10 этот бит предпочтительно не устанавливать;
#40 | - подлежит удалению, если родительский модуль в памяти (в каталоге) отсутствует ( 1 - да), реально автоматическое удаление таких модулей производится при запросах EXIT$, CAT$ при R0=#2,4,6, и сделано это для автоматического удаления мусора;
#100 | - перед удалением модуля запускать END-2 (по CALL);
#200 | - есть расширенное имя внутри модуля (см. слово 10);

06 | слово | <имя родительского модуля> | - формат такой же, как и у слова 00; задаётся программистом при создании модуля; 0 - не определено - при удалениях равносильно тому, что родительский модуль всегда есть;
10 | слово | <смещение до расширенного имени> | - смещение от начала модуля до текста .ASCIZ;
12 | слово | <смещение> | - смещение от начала сегмента до начала модуля;
14 | байт | <сегмент> | - логический номер сегмента начала модуля;
15 | байт | <резерв>. |

## Приложение 4. Кодировка версии контроллера.

Номер версии доступен программно - он содержится в последнем слове ПЗУ (по адресу 167776). В старшем байте содержится ключ и информация об объёме дополнительной памяти, в младшем байте - информация о типе контроллера и номере версии ПЗУ.

174000 | - A16;
174400 | - A16 + контроллер "винта" с доп. ОЗУ 4 Кб (170-177000);
175000 | - A16M;
175400 | - не используется;
|  | если младший байт > 0 - то это старая версия ПЗУ совмещённого контр. винчестера и дисковода SMK64 - её нужно заменить (ПЗУ установлено на панелях); если млад. байт имеет значение от 200 до 300 - то это контроллер SMK, если > 300 - это дисководный контроллер A64M-A512M.
176000 | - 64 Кб
176400 | - 128 Кб
177000 | - 256 Кб
177400 | - 512 Кб

В старой версии ПЗУ ( мл. байт > 0 ) ROM-BIOS отсутствует.

Проверка на наличие не менее 64 Кб и современной версии ПЗУ осуществляется одной командой: CMP @#167776,#176200 \ BHIS - Ok

Внимание! Программисты, загружающие в ОЗУ с адреса 160000 свою версию драйверов, должны область 167460-170000 (точки входа BIOS и номер версии контроллера) копировать 1:1 из ПЗУ !

## Приложение 5. Зарезервированные знаки в именах модулей.

Для старшего байта имени модуля (идентификатор изготовителя) по состоянию на 1.06.98 г. зарезервированы следующие знаки:

$ % `(обратный апостроф) R L

Программисты, желающие закрепить за собой какой-либо другой символ, должны сообщить об этом в фирму-изготовитель (АльтПро) для предотвращения совпадений и программных конфликтов.

## Приложение 6. Стек возвратов и режим DOS.

Стек возвратов из подпрограмм, вызываемых по запросам CAL$G и CAL$N растёт вниз (каждый CAL$ добавляет в стек 4 слова), в исходном состоянии (после загрузки или EXIT$) представляет собой следующее:

TOP: | <код режима (DOS)> | - код исходного режима, того, в котором работает ДОС с оболочкой; изначально это Std10 или Std11, т.е. стандартный режим БК10 или 11М, коды 60 или 140; если программа перемещает ДОС в другой режим (например, Halt10 или Halt11), то она должна корректировать и эту ячейку (см.ниже);
TOP-2: | < old PC > | - псевдо-адрес возврата - 100000;
TOP-4: | <PS & @#6> | - здесь - 0;
TOP-6: | < @#4 > | - копия ячейки 4 для её восстановления - 100442;
TOP-10: | <код текущ. режима> | - при запуске и EXIT$ устанавливается = коду режима DOS, указатель WRK$ устанавливается = TOP-10 (таким образом, WRK$ указывает на ячейку с кодом текущего режима).

Указатель стека возвратов WRK$, адрес = 120016 в системной странице (код её включения - #2160), после запуска или EXIT$ содержит #TOP-10, при каждом CAL$ он опускается на 10; ячейка DOS$ (адрес 120020 в системной странице), введённая для доступа к коду DOS-режима, всегда содержит #TOP.

После первого CAL$ (стек возвратов опускается на 10):

TOP-10: | <код предыдущего режима> | - код режима, из которого был CAL$;
TOP-12: | <old PC> | - адрес возврата;
TOP-14: | <PS & @#6> | - сохранённые слово состояния процессора и @#6;
TOP-16: | < @#4 > | - сохранённая при запросе CAL$ ячейка 4;
TOP-20: | <код текущ. режима> | - код нового режима.

При включении питания компьютера и при перезапуске без логической обработки включается стандартный режим (Std10 или Std11), в нем обычно загружается ДОС, и он же объявляется режимом "DOS" при инсталляции RAM-BIOS. Однако в дальнейшем в ряде случаев (например, при подключении HALT-режима), DOS-режим меняется программами типа WINDOWS, OS/A, HALT-DRIVER. Короче, программисты могут изменять содержимое ячеек TOP - TOP-6, используя доступ через ячейку DOS$.

## Приложение 7. Обработка ошибок.

В случае возникновения ошибки BIOS вписывает код ошибки в байт ERR$ = 120004 в системной странице (код её включения - #2160) при условии, что RAM-BIOS в этой странице имеется, после чего выдаёт сигнал ошибки - характерное затухающее подёргивание экрана с прерывистым звуковым сигналом.

Признак наличия RAM-BIOS: в ячейке 120010 системной страницы содержится #120012.

Коды ошибок (на 1.06.98 г.):

#100 | - разрушен конец RAM-BIOS;
#1 | - несуществующий запрос BIOS;
#2 | - нарушение или переполнение стека возвратов; переполнение фиксируется при CAL$, если адрес в ячейке WRK$ (120016) ниже, чем содержимое WRKLIM (120014);
#340 | - ошибка при попытке восстановления области памяти по RESTO$ (нарушение стека сохранения).

Признак целостности байта ERR$: байт 120005 = 111 (octal).

## Приложение 8. Стандартные адреса и константы BIOS.

1) В области ROM-BIOS:

    BEGIN$=167342   ;начало ROM-BIOS; здесь располагаются подпрогра-
                    ;ммы пересылки массивов, стандартное обращение к
                    ;которым бывает только при  подключенном  ПЗУ  -
                    ;поэтому при переносе ROM-BIOS в ОЗУ  эту  часть
                    ;можно не копировать;
    BEG$R5=167460   ;начало точек входа запросов BIOS - эту часть  и
                    ;всё, что ниже, при переносе ROM-BIOS в ОЗУ нуж-
                    ;но копировать;
    STP$=167712     ;стандартная подпрограмма блокировки кнопки СТОП
    ARTI$=167714    ;в этой ячейке находится команда RTI
    DIR1$=167720    ;3 "прямых" точки входа (не по JSR R5,...) - на-
    DIR2$=167724    ;пример, для обработки прерываний в доп. ОЗУ;  в
    DIR3$=167730    ;версии RAM-BIOS 3.05 - не задействованы: для их
                    ;использования надо поместить адрес  обработчика
                    ;пользователя в  таблицу  подпрограмм  обработки
                    ;запросов в системной странице...
    MOD$S=167744    ;3 точки входа переключения  режимов  на  низком
    MOD$J=167752    ;уровне (используются при заблокированных преры-
    MOD$=167754     ;ваниях;
    VERS$=167776    ;номер версии ПЗУ и код контроллера

    JMP$G=167515    ;ТОЧКИ ВХОДА ЗАПРОСОВ по  JSR R5,@#_имя_
    CAL$G=167516
    CHW$G=167517
    MOV$G=167520
    CAT$=167521
    CAL$N=167522
    JMP$N=167523
    RDW$N=167524
    CHW$N=167525
    MOV$N=167526
    EXIT$=167527
    SAVE$=167530
    RESTO$=167531
    NEW$SP=167630
    CH$WRK=167734

2) В области RAM-BIOS (в системной странице доп. ОЗУ):

    R$VERS=120002   ;содержит номер версии RAM-BIOS;
    ERR$=120004     ;мл.байт - код ошибки, ст.байт = 111;
    PZP$=120006     ;содержит адрес подпрограммы  обработки  нестан-
                    ;дартного перезапуска;
    CTRL0$=120010   ;содержит #120012 - по этой константе проверяет-
                    ;ся целостность начала RAM-BIOS;
    MAIN$=120012    ;содержит адрес диспетчера запросов;
    WRK$=120016     ;указатель стека режимов
    DOS$=120020     ;указатель на ячейку с кодом DOS-режима

## Приложение 9. Краткие сведения о HALT-режиме.

Необходимым условием работы HALT-режима является наличие ОЗУ по записи по адресу 177674, где в 2 последовательных ячейках сохраняется PC и PS при HALT-прерывании. Кнопка СТОП всегда вызывает именно это прерывание, но из-за отсутствия указанного ОЗУ вслед за HALT-прерыванием происходит прерывание по вектору 4 (причём, в результате этого PC в стеке оказывается на 2 больше, чем надо).

HALT-прерывание происходит по вектору 160002, совместить это с драйвером дисковода возможно, подключив со 160000 ОЗУ вместо ПЗУ (см. реализации WIN-DEMO и OS/A WASP).

В ячейке 160004 (new PS) должен быть установлен бит #2000 - "высокий приоритет процессора для HALT-режима" - чтобы заблокировать прерывания от дребезга кнопки СТОП, и обработчик HALT-прерывания должен некоторое время не делать никаких операций, изменяющих PS, поскольку при "обычных" операциях бит #2000 в PS всегда сбрасывается.

Итак, алгоритм обработки HALT-прерывания в программах типа WIN-DEMO, OS/A WASP (работающих по СТОП+клавиша) в первом приближении (ориентировочно!) следующий:

1. Задержка против дребезга СТОП и против запаздывания появления признака нажатой клавиши (последнее случается величиной до 40000 SOB'ов при 6 МГц - от момента нажатия).
2. Переключение режимов и извлечение адреса возврата и PS.
3. Команда по <адресу возврата - 2> вызывает HALT-прерывание (0 и ещё кое-какие)? Если да, то сэмулировать прерывание по век тору 4.
4. Клавиша нажата? Если нет, то прибавить 2 к адресу возврата и сэмулировать прерывание по вектору 4.
5. Собственно обработка прерывания.

(с) В.Е.Новак, А.И.Глускер 1997-98 гг.