Сообщений 11    Оценка 60        Оценить  
Система Orphus

Программирование расширения ROM BIOS персонального компьютера

Автор: Сазонов Сергей Валерьевич
НПП ВНИИЭМ,

Источник: RSDN Magazine #4-2008
Опубликовано: 26.04.2009
Исправлено: 10.12.2016
Версия текста: 1.5
Расширение PCI ROM BIOS: структура и особенности
Расширение PCI ROM BIOS: методика разработки
Заключение
Литература
Приложение

В настоящее время в персональных компьютерах (ПК) широко применяются дополнительные PCI и PCI-Express устройства, имеющие ПЗУ с расширением ROM BIOS (далее PCI ROM BIOS). Расширение PCI ROM BIOS относится к т.н. firmware, т.е. к программному обеспечению, встроенному в «железо». Расширение PCI ROM BIOS содержит программные компоненты, не входящие по разным причинам в системный BIOS. Как правило, это код инициализации периферийного устройства, выполняемой до загрузки операционной системы (далее ОС). Кроме того, в PCI ROM BIOS может содержаться код поддержки функций устройства для некоторых ОС, если это невозможно обеспечить стандартным образом с помощью драйвера. Функции, выполняемые расширением PCI ROM BIOS, зависят от конкретного физического устройства, и их описание не является темой статьи. Ниже рассмотрена методика разработки расширения PCI ROM BIOS, упрощающая процесс разработки и уменьшающая количество потенциальных ошибок. Предлагаемая методика актуальна как для PCI-устройств, так и для устройств PCI-Express, т.к. их программная модель конфигурации и расширения ROM BIOS совместима с программной моделью PCI-устройств.

Расширение PCI ROM BIOS: структура и особенности

Расширение PCI ROM BIOS размещается в ПЗУ на плате устройства. В общем случае ПЗУ устройства может одновременно содержать несколько кодовых фрагментов для процессоров с различной архитектурой, расположенных последовательно и выровненных по границе кратной 512 байт. Программный модуль расширения PCI ROM BIOS включает в себя заголовок ПЗУ, структуру данных PCI-устройства, модуль инициализации и модуль рабочего кода. Заголовок ПЗУ служит идентификатором при поиске расширений PCI ROM BIOS. Структура данных PCI-устройства играет роль дополнительного идентификатора firmware конкретного устройства. Модуль инициализации выполняет первичную настройку параметров устройства. А модуль рабочего кода служит своего рода программным драйвером устройства.

Модуль расширения PCI ROM BIOS может занимать весь объём ПЗУ, но чаще всего используется только его часть. Байты контрольной суммы представляют собой контрольную сумму кода соответствующего сегмента от начала ПЗУ. Структура расширения PCI ROM BIOS PC/AT-совместимых ПК (т.е. для одного типа процессора) приведена на рисунке 1 и подробно описана в спецификации шины PCI [1].


Рисунок.1 - Структура расширения PCI ROM BIOS PC-совместимого ПК

Расширение PCI ROM BIOS начинается с заголовка, структура которого приведена ниже в таблице 1. Заголовок ПЗУ расширения PCI ROM BIOS, в отличие от заголовка ROM BIOS ISA-устройства, содержит указатель на структуру данных PCI-устройства. Эта структура считывается программой POST, входящей в системный BIOS. Структура данных PCI-устройства располагается в пределах 64 Кбайт от точки входа в программу расширения PCI ROM BIOS и имеет вид, приведённый в таблице 2.

Смещение Длина, байт Значение Назначение
0h 1 55h Сигнатура ПЗУ расширения ROM BIOS
1h 1 AAh Сигнатура ПЗУ расширения ROM BIOS
2h 1 xx Размер модуля инициализации, кратный 512 байт
3h 3 xx Точка входа
6h 18 xx Резерв
18h 2 xx Указатель на структуру данных PCI-устройства
Таблица 2. Структура данных PCI-устройства расширения PCI ROM BIOS.
Смещение Длина, байт Назначение
0h 4 Сигнатура (строка “PCIR”)
4h 2 Идентификатор производителя
6h 2 Идентификатор устройства
8h 2 Резерв
Ah 2 Длина структуры данных PCI-устройства
Ch 1 Версия структуры данных PCI-устройства
Dh 3 Код класса PCI-устройства
10h 2 Длина кодового сегмента
12h 2 Версия кода расширения PCI ROM BIOS
14h 1 Тип кода
15h 1 Индикатор
16h 2 Резерв

Каждое PCI-устройство имеет программно доступное пространство конфигурации, которое определяет используемые устройством ресурсы памяти, порты ввода/вывода и особенности протокола шины PCI/PCI-Expess данного устройства. Некоторые поля структуры данных PCI-устройства идентичны значениям пространства конфигурации PCI-устройства.

Идентификатор производителя (Vendor Identification) должен совпадать с одноимённым полем в пространстве конфигурации PCI-устройства.

Идентификатор устройства (Device Identification) должен совпадать с одноимённым полем в пространстве конфигурации PCI-устройства.

Код класса (Class Code) должен совпадать с одноимённым полем в пространстве конфигурации PCI-устройства.

Тип кода (Code Type) определяет тип процессора, для которого предназначен код данного расширения BIOS:

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

Индикатор (Indicator) определяет, является ли данный кодовый сегмент последним. Если бит 7 равен единице («1»), то это последний кодовый сегмент. Биты 0-6 зарезервированы.

Длина структуры данных PCI-устройства (PCI Data Structure Length) определяет длину этой структуры.

Расширение PCI ROM BIOS начинает функционировать при запуске или перезагрузке ПК, еще до загрузки ОС. Происходит это следующим образом. При запуске ПК программа POST (Power On Self Test), входящая в состав системного BIOS, выполняет поиск и проверку ресурсов материнской платы, поиск периферийных устройств и распределение системных ресурсов (портов ввода/вывода, памяти, прерываний) между ними [2]. Затем программа POST выполняет поиск и активизацию расширений PCI ROM BIOS периферийных устройств:

  1. Сканирование ОЗУ и поиск с шагом 512 байт сигнатуры расширения ROM BIOS, равной 0AA55h.
  2. Чтение заголовка расширения ROM BIOS и определение его длины.
  3. Вычисление и проверка контрольной суммы расширения PCI ROM BIOS.
  4. Чтение указателя на «структуру данных» PCI-устройства.
  5. Чтение «структуры данных» PCI-устройства и сравнение значений идентификатора производителя, идентификатора устройства и кода класса с одноимёнными полями в пространстве конфигурации данного PCI-устройства.
  6. Проверка типа кода на соответствие архитектуре используемого процессора.
  7. При успешном выполнении двух предыдущих пунктов загрузка расширения PCI ROM BIOS из ПЗУ в ОЗУ ПК, обычно в область адресов 0С0000h – 0DFFFFh.
  8. Передача управления процессором на точку входа программы расширения PCI ROM BIOS.
  9. Ожидание возврата управления.

Расширение PCI ROM BIOS: методика разработки

Для программирования расширения PCI ROM BIOS предпочтительней использовать ассемблер. Все языковые инструменты имеют как положительные, так и отрицательные стороны. Однако при решении поставленной задачи ассемблер имеет несколько преимуществ по сравнению с другими инструментами. Расширение PCI ROM BIOS имеет строго заданную структуру заголовка ПЗУ, которую удобнее всего реализовать с помощью ассемблера. Объём расширения PCI ROM BIOS сильно ограничен (максимум 128 Кбайт), что несколько затрудняет использование языков высокого уровня. Расширение PCI ROM BIOS предназначено для непосредственной работы с аппаратурой, т.е. для взаимодействия с регистрами, разрядами регистров и с прерываниями. В этом случае ассемблер наиболее удобен по сравнению с любыми языками высокого уровня.

В данном случае в качестве инструмента использовался Turbo Assembler (версия 3.1), входящий в состав пакета Borland C++ (версия 3.1) фирмы Borland. Этот продукт был популярен у отечественных программистов, и для него существует большое количество библиотек. Программировать и отлаживать расширение PCI ROM BIOS лучше всего либо в среде DOS, либо в среде Windows 95/98/Me в режиме командной строки, что упрощает непосредственное обращение к аппаратным ресурсам и использование прерываний системного BIOS. В Windows NT/2000/ХР таких возможностей у программиста нет. Кроме того, Turbo Debugger лучше функционирует в режиме командной строки, чем когда ОС работает в графическом режиме.

Расширения PCI ROM BIOS представляет собой bin-файл. Этот файл не является исполняемым файлом, что обусловлено его структурой отличной от исполняемого com- и exe-файла. Несмотря на его сходство с com-файлом, его нельзя получить простым переименованием com-файла потому, что все коды и данные com-файла начинаются со смещения 100h, в то время, как в bin-файле расширения PCI ROM BIOS коды и данные начинаются со смещения 0h. Более того, com-файл нельзя запустить под отладчиком и выполнить отладку, т.к. при сборке com-файла линкер исключает из него всю отладочную информацию. Поэтому для отладки программы требуется exe-файл.

Предлагается следующая технология программирования и отладки расширения PCI ROM BIOS. Сначала разрабатывается программа расширения PCI ROM BIOS (пусть файл исходного текста называется bios-exp.asm). Затем выполняется ее компиляция и сборка стандартного exe-файла. Командная строка для создания exe-файла должна иметь следующий вид:

tasm /m/l/zi  bios-exp.asm
tlink /v bios-exp.obj bios-exp.exe	

Далее выполняется отладка программы, после чего производится небольшая модификация исходного текста и создание двоичного bin-файла, записываемого в ПЗУ. Командная строка имеет следующий вид:

tasm /m/l/s  bios-exp.asm
tlink /t bios-exp.obj bios-exp.bin

При разработке программы расширения PCI ROM BIOS необходимо обратить внимание на следующие важные моменты.

Рекомендуется использовать единый исходный файл для получения exe- и bin-файла. Исполняемый exe-файл используется для отладки, а bin-файл записывается в ПЗУ. Эти файлы отличаются друг от друга не только форматом, но и функциональностью. Для получения двух различных файлов из одного исходного текста используется условная компиляция, что позволяет свести к минимуму синтаксические и функциональные ошибки, возникающие в процессе программирования.

Адресное пространство данных и кода в программе расширения PCI ROM BIO едино, поэтому необходимо использовать модель памяти «TINY». При работе с пакетом Turbo Assembler желательно использовать режим «IDEAL» вместо стандартного режима «MASM». Режим «IDEAL» позволяет более свободно обращаться со структурами данных, и его исходный текст более «читабелен», что уменьшает возможность появления синтаксических и функциональных ошибок в процессе программирования. Также рекомендуется использовать директиву «LOCALS», что позволяет использовать одинаковые названия меток, начинающихся с символов @@ в различных подпрограммах. Это значительно упрощает жизнь программиста при поиске имён меток.

Необходимо обратить внимание на точку входа в программу расширения PCI ROM BIOS. Это четвёртый элемент структуры заголовка ПЗУ, длина которого составляет 3 байта и представляет собой переход на код инициализации, с помощью команды JMP. Здесь кроется один подвох. Команда JMP может иметь длину от 2 до 5 байтов в зависимости от длины перехода и формируется ассемблером при компиляции исходного файла. При этом ассемблер пытается сократить исполняемый код, где только возможно. Даже прямое указание ассемблеру типа перехода NEAR для гарантированного получения трёхбайтной команды JMP не поможет, если адрес перехода лежит в пределах 128 байтов, что достаточно часто встречается. В тоже время длина команды JMP обязательно должна быть равна 3 байтам, иначе нарушится структура заголовка расширения PCI ROM BIOS, и, соответственно, нарушится указатель на структуру PCI-данных устройства. Решается эта проблема несколькими способами, из которых лучше использовать непосредственное резервирование данных:

EntryPointInit:   DB  0E9h     ; OPCODE инструкции "JMP" (forward)DW  (offset PROC ROM_Exp)-(offset RsvPciRom)

Необходимо обратить внимание на инициализацию сегментных регистров DS, SS при старте программы. Даже при использовании модели памяти TINY в exe-файле значение сегмента данных отлично от значения кодового сегмента. Аналогично дело обстоит и со стековым сегментом. Поэтому в exe-файл нужно включить следующие команды:

    mov     AX,_TEXT
    mov     DS,AX
    mov     AX,_DATA
    mov     SS,AX

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

    mov     AX,CS
    mov     DS,AX
    mov     SS,AX    

При использовании директив, автоматически выделяющих память под стек, Turbo Linker сообщает об ошибке «Fatal: cannot generate COM file: stack segment present». Чтобы избежать этого, необходимо вручную выделить память для стекового сегмента. Тогда Turbo Linker сообщит об отсутствии стека «Warning: No stack», но сгенерирует двоичный файл. Память под стек должна выделяться в конце сегмента программы, причем в начале программы необходимо инициализировать указатель стека регистр SP:

mov     SP, offset ProgStack
           *
           *
           *
EVENDATA                      ; выравнивание
ProgStack    DB 200h DUP(?)   ; резервирование памяти для STACK

Заголовок расширения PCI ROM BIOS должен содержать структуру данных PCI-устройства, значения определённых элементов которой должны совпадать со значениями одноимённых полей в пространстве конфигурации PCI-устройства. Это касается «Идентификатора производителя», «Идентификатора устройства» и «Кода класса».

Как правило, длина программы не кратна 512 байт. Поэтому созданную программу необходимо дополнить произвольными байтами до величины, кратной 512 байт, причем необязательно до полного объёма, используемого ПЗУ. Не запрограммированные байты ПЗУ имеют значения 0FFh и будут проигнорированы при сканировании программой POST.

Байт контрольной суммы подсчитывается путём сложения всех байтов программы с игнорированием знака переноса и дополнением полученной суммы до нуля. Размещается байт контрольной суммы не после последних байтов программы, как в работе [4], а после байтов, дополняющих программу до величины кратной блоку 512 байт. В противном случае контрольная сумма расширения PCI ROM BIOS будет неверной, и программа POST не передаст ему управление. Значение байта контрольной суммы можно вписать в исходный файл программы и повторно выполнить компиляцию, а можно с помощью любого HEX-редактора внести изменения в уже готовый двоичный файл.

Для корректного завершения работы exe-версии программы расширения PCI ROM BIOS необходимо выполнять стандартный возврат в DOS (даже если отладка производится в среде Windows 95/98/Me). Соответствующие строки кода выглядят следующим образом:

        ; возврат в DOS
    mov     AH,4Ch
    int     21h

С другой стороны, после окончания инициализации программы расширения PCI ROM BIOS выполняется возврат управления процессором программе POST, что реализуется одной командой:

        ; возврат в POST-программу системного BIOS
    retf

Существенной особенностью расширения PCI ROM BIOS является то, что оно выполняется не из ПЗУ устройства, а предварительно загружается в оперативную память ПК. Ранее в ISA-устройствах расширение ROM BIOS выполнялось непосредственно из ПЗУ периферийного устройства. Расширение PCI ROM BIOS, загруженное в ОЗУ, выполняет код инициализации. После инициализации данный код, как правило, не требуется и может быть выгружен из ОЗУ весь или частично. Далее управление процессором возвращается программе POST. Оставленный в ОЗУ модуль рабочего кода будет функционировать до перезагрузки/выключения ПК и выполнять роль драйвера PCI-устройства. Но, как правило, эту возможность не используют, предпочитая DOS/Windows-драйверы, полностью выгружая из ОЗУ код расширения PCI ROM BIOS. Полная выгрузка программы из памяти реализуется следующим образом:

        ; подготовка ROM Expansion к выгрузке из памяти
    mov     [InitSize],0         ; полное освобождение памяти

Одновременно с передачей управления процессором программе расширения PCI ROM BIOS программа POST передаёт ей в регистре АХ координаты данного устройства на шине PCI, которые необходимо сохранить. В регистре АН передаётся номер шины PCI (Bus Number). В старших 5 битах регистра AL передаётся номер устройства PCI (Device Number), а в младших 3 битах регистра AL передаётся номер функции (Function Number) данного устройства. Передача этих параметров упрощает конфигурирование ПК при наличии нескольких шин PCI, нескольких одинаковых устройств PCI и/или многофункциональных устройств, размещённых на одной плате расширения. Эти координаты позволяют получить доступ к пространству конфигурации PCI-устройства, т.е. к его параметрам и, главное, к его регистрам «Базового адреса». Регистр базового адреса PCI-устройства определяет доступ ко всем внутренним ресурсам устройства, для инициализации которых собственно и предназначена программа расширения PCI ROM BIOS. В ISA-устройствах базовый адрес постоянный и задается с помощью джамперов. В PCI-устройствах базовый адрес переменный и задается программным способом (первично BIOS в соответствии с процедурой Plug’n’Play при включении компьютера).

        ; сохранение базового адреса PCI-устройства на шине после запуска программы
    mov     [BusNumber],AH       ; Сохранение номера шины
    mov     [DeviceNumber],AL    ; Сохранение номера устройства

При отладке расширения PCI ROM BIOS с помощью exe-файла программа POST, естественно, не передаёт ей никаких параметров. Поэтому необходимо самостоятельно определить координаты искомого устройства на шине PCI. Для этого применить так называемые «Механизм конфигурации #1» и «Механизм конфигурации #2», встроенные в шину PCI. Эти механизмы используют специальный протокол и регистры CONFIG_ADDRESS (CF8h) и CONFIG_DATA (CFCh) или регистр Configuration_Space_Enable (CF8h) соответственно [1]. Однако лучше использовать соответствующие прерывания PCI BIOS [3], что значительно уменьшает трудоемкость и сложность реализации алгоритма поиска устройства на шине PCI. Перед использованием прерывания PCI BIOS необходимо убедиться в его наличии. Можно, например, выполнить поиск устройства по коду класса следующим образом:

PROC FindPciDevice near
        mov     [DevFound],0         ;сброс флага Device found
        mov     AX,0B103h
        mov     ECX,ClassCode        ;ECX=ClassCode
        int     1Ah                  ;поиск PCI-устройства по классу
        jc      @@End;               ;устройство не найдено;если устройство найдено
        mov     [BusNumber],BH       ;Сохранение номера шины
        mov     [DeviceNumber],BL    ;Сохранение номера устройства
        mov     [DevFound],1         ;Установка флага Device found
@@End:
        ret
ENDP FindPciDevice

Перед использованием функций PCI BIOS необходимо убедиться в его наличии. Подробное описание программных функций PCI BIOS приведено в документе [3].

Наконец, необходимо напомнить, что расширение PCI ROM BIOS выполняется в то время, когда не загружена ещё никакая ОС. В то же время очень велик соблазн использовать некоторые «привычные для программиста» прерывания и системные переменные. Необходимо (!) проверить, что они находятся под юрисдикцией BIOS, особенно это касается системного таймера.

Ниже приведен листинг шаблона программы расширения PCI ROM BIOS, суммирующий все особенности программирования, рассмотренные выше. Константа BIN_TYPE_FILE используется при условной компиляции. Если константа BIN_TYPE_FILE определена, то выполняется компиляция двоичного bin-файла расширения PCI ROM BIOS. В противном случае выполняется компиляция exe-файла, используемого для отладки программы.

Заключение

Практически единственной статьей на русском языке, описывающей основы функционирования расширения ROM BIOS и методику его программирования, является работа [4]. Также можно обнаружить почти полное повторение этой работы [5], датированное 2000 г. К сожалению, работа [4,5] касается ROM BIOS ISA-устройств, к тому же имеет несколько неточностей и не описывает особенностей расширения PCI ROM BIOS.

В конце 2007 г. из печати вышел перевод книги Д. Салихана [6] в которой, в числе прочих, рассмотрен вопрос программирования расширения PCI ROM BIOS. Для решения этой задачи Д. Салихан использует механизмы Plug’n’Play и IPL BIOS, а также точку входа для загрузки BEV (Bootstrap Entry Vector). В результате получается достаточно сложное решение. При этом используется операционная система Linux и соответствующие ей инструменты. Пока же большинству схемотехников, да и программистов, привычнее среда DOS/Windows. Тем не менее, книга Д. Салихана является хорошим источником информации и методик программирования.

Литература

  1. 1. PCI Local Bus Specification, revision 2.2.
  2. 2. Сазонов С.В. «ПК с самого начала». //«Hard’n’Soft» 7/1997г., с.68-71; 9/1997г., с.66-70; 10/1997г., с.58-61.
  3. 3. PCI BIOS Specification, revision 2.1.
  4. 4. Бордачёв А. Ю. «Как изменить «способности» компьютера». //М.: Инфоарт, 1994, «Персональные компьютеры. Справочная книга программиста», вып.10, с.45-54.
  5. 5. www.wasm.ru
  6. 6. Салихан Д. «BIOS. Дизассемблирование, модификация, программирование». //СПб.: BHV, 2007.

Приложение

Листинг шаблона программы расширения PCI ROM BIOS
      ;//------------------------------------------------------------------//
      ;// Title:     Модуль расширения PCI ROM BIOS                        //
      ;// File:      rom_exp.asm                                           //
      ;// Author(s): Сазонов С.В.                                          //
      ;//------------------------------------------------------------------//
IDEAL
P386
LOCALS
MODEL TINY

;для получения EXE-файла расставьте комментарии ;для получения BIN-файла удалите комментарии
BIN_TYPE_FILE   equ    1     ;настройка типа результирующего файла: EXE/BIN

CODESEG
IFDEF BIN_TYPE_FILE    ;для BIN-файла
START:
ENDIF

ORG    0h
;========== Структура PCI ROM Header ==========
RomSignByte1      DB  055h
RomSignByte2      DB  0AAh
InitSize          DB  0Bh      ;длина в блоках по 512 байт (~5,5Kбайт)
EntryPointInit:   DB  0E9h     ; OPCODE инструкции "JMP" (forward)DW  (offset PROC ROM_Exp)-(offset RsvPciRom)
RsvPciRom         DB  12h DUP (?)          ; зарезервировано
PciDataPointer    DW SHORT OFFSET PciSign  ; указатель на структуру PCI DATA;====== Конец структуры PCI ROM Header structure =======

EVENDATA            ; выравнивание;========== Структура PCI DATA ============
PciSign             DB  "PCIR"  ;50h,43h,49h,52h
VendorIdent         DW  0000h
DeviceIdent         DW  0001h
RsvPciData1         DW  0000h   ; зарезервировано
PciDataStrucLenrth  DW  SIZE_PciDataStruc
PciDataStrucRev     DB  01h
DevClassCode        DB  01h,01h,01h
ImageLength         DW  0Bh     ; длина в блоках по 512 байт
RevisionLevel       DW  01h
Codetype            DB  0       ;Intel x86, PC-AT compatible
Indicator           DB  080h    ;bit-7=1:Last image in ROM
RsvPciData2         DW  0000h   ; зарезервировано
DevSignPtr          DW  OFFSET DevSign  ; указатель на сигнатуру устройства;========= Конец структуры PCI DATA ==========
SIZE_PciDataStruc = (OFFSET DevSignPtr)+(SIZE DevSignPtr)-(OFFSET PciSign)
ENDS

CODESEG
BusNumber      DB 0   ;Номер шины
DeviceNumber   DB 0   ;Номер устройства
ClassCode      DD 0   ;Код класса (Base Class+Sub Class+PIF)
DevIndex       DW 0   ;Индекс номера устройства index
DevFound       DB 0   ;Флаг Device found: 0=не найдено/1=найдено
ENDS

CODESEG
;//----------------- PCI ROM BIOS expansion program -----------------//
PROC ROM_Exp near
IFDEF BIN_TYPE_FILE    ;// для BIN-файла;устанавливаем сегментные регистры 
BEGIN:
    mov     AX,CS
    mov     DS,AX
    mov     SS,AX
    mov     SP, offset ProgStack
ENDIF   ;// конец BIN-файла

IFNDEF BIN_TYPE_FILE   ;// для EXE-файла; устанавливаем сегментные регистры 
START:
    mov     AX,_TEXT
    mov     DS,AX
    mov     AX,_DATA
    mov     SS,AX
    mov     SP, offset ProgStack
ENDIF   ;// конец EXE-файла;сохранение базового адреса PCI-устройства на шине после запуска программы
    mov     [BusNumber],AH       ;Сохранение номера шины
    mov     [DeviceNumber],AL    ; Сохранение номера устройства ;подготовка ROM Expansion к выгрузке из памяти
    mov     [InitSize],0         ;полное освобождение памяти

IFNDEF BIN_TYPE_FILE   ;// для EXE-файла;поиск PCI-устройства с помощью функций PCI BIOS
    call    FindPciDevice        ;поиск PCI-устройства
    cmp     [DevFound],1         ;проверка флага DevFound
    jne     @@EndRomExp          ;завершение программы ROM expansion
ENDIF   

;//--------------------------------------------//;//            *                               //;//            *                               //;//  Пользовательские процедуры и подпрограммы //;//            *                               //;//            *                               //;//--------------------------------------------//

@@EndRomExp:
IFDEF BIN_TYPE_FILE    ;// для BIN-файла;возврат в POST-программу системного BIOS
    retf
ENDIF   

IFNDEF BIN_TYPE_FILE   ;// для EXE-файла;Возврат в DOS
    mov     AH,4Ch
    int     21h
ENDIF   
ENDP ROM_Exp

CODESEG
EVENDATA                      ;выравнивание
ProgStack    DB 200h DUP(?)   ;резервироание памяти для STACK
ENDS

IFDEF BIN_TYPE_FILE    ;для BIN-файла
CODESEG
@@RomCodeEnd:
;BlankRom = (InitSize * 512) - (offset @@RomCodeEnd)
BlankRom DB (55) DUP (0)   ; выравнивание по границе блока в 512 bytes

RomCheckSum   DB 0DDh      ;байт контрольной суммы
ENDS
ENDIF

END  START


Эта статья опубликована в журнале RSDN Magazine #4-2008. Информацию о журнале можно найти здесь
    Сообщений 11    Оценка 60        Оценить