Фирмой "АльтПро" (экс-"Альтек") выпускаются контроллеры с дополнительной памятью 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 │ MOV #TOP,R0 │ MOV #TOP,R0
.WORD TOP │ JSR R5,@#NEW$SP+2 │ MOV #LEN,R1
.WORD LEN │ .WORD LEN │ 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 │ MOV mode,R0 │ MOV mode,R0
.WORD mode │ JSR R5,@#CH$WRK+2 │ JSR R5,@#CH$WRK+4
.WORD addr │ .WORD addr │
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
режима R4 │ного режима (с RAM-│ & JMP
( @#167754 ): │BIOS) ( @#167744 ): │ ( @#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. ┌───────────────┬───────────────────────┬───────────────────┐
│ Физич. номера │ │ │
│ сегментов со- │ Для БК10 │ Для БК11М │
│ гласно табл.1 │ │ │
│ приложения 1 │ │ │
├───────────────┼───────────────────────┼───────────────────┤
│ 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 ─ не используется; |
• 176000 ─ 64 Кб ──> ┐ • 176400 ─ 128 Кб ──> │ • 177000 ─ 256 Кб ──> │ • 177400 ─ 512 Кб ──> ┘ | если младший байт > 0 - то это старая версия ПЗУ совмещенного контр. винчестера и дисковода SMK64 - ее нужно заменить (ПЗУ установлено на панелях); если млад. байт имеет значение от 200 до 300 - то это контроллер SMK, если > 300 - это дисководный контроллер A64M-A512M. |
--------------------------------- | |
В старой версии ПЗУ ( мл. байт > 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 (работающих по СТОП+клавиша) в первом приближении (ориентировочно!) следующий:
- Задержка против дребезга СТОП и против запаздывания появления признака нажатой клавиши (последнее случается величиной до 40000 SOB'ов при 6 МГц - от момента нажатия).
- Переключение режимов и извлечение адреса возврата и PS.
- Команда по <адресу возврата - 2> вызывает HALT-прерывание (0 и еще кое-какие)? Если да, то сэмулировать прерывание по вектору 4.
- Клавиша нажата? Если нет, то прибавить 2 к адресу возврата и сэмулировать прерывание по вектору 4.
- Собственно обработка прерывания.
================ (с) В.Е.Новак, А.И.Глускер 1997-98 гг. =====