командой POP на выходе. Можно также использовать стек для передачи величин
из подпрограммы в вызывающую программу. Хотя рассмотренная подпрограмма не
возвращает каких-либо значений, в языке PASCAL предполагается, что
подпрограмма возвращает одно слово в регистре AX или двойное слово в
регистровой паре DX:AX.
В результате компановки двух программ будет построена карта
компановки, в которой первый элемент PASCALL представляет
PASCALL-программу, второй элемент CODESEG (имя сегмента кода) представляет
ассемблерную подпрограмму. Далее следует несколько подпрограмм для
PASCALL-программы. Эта довольно тривиальная программа занимает в
результате шест.5720 байт памяти - более 20К. Компилирующие языки обычно
генерируют объектные коды значительно превышающие по объему размеры
компилируемой программы.
КОМПОНОВКА ПРОГРАММ НА ЯЗЫКЕ CИ И АССЕМБЛЕРЕ
________________________________________________________________
Трудность описания связи программ на языке C и ассемблерных программ
состоит в том, что различные версии языка C имеют разные соглашения о
связях и для более точной информации следует пользоваться руководством по
имеющейся версии языка C. Здесь приведем лишь некоторые соображения,
представляющие интерес:
- Большинство версий языка C обеспечивают передачу параметров
через стек в обратной (по сравнению с другими языками)
последовательности. Обычно доступ, например, к двум параметрам,
передаваемым через стек, осуществляется следующим образом:
MOV ES,BP
MOV BP,SP
MOV DH,[BP+4]
MOV DL,[BP+6]
...
POP BP
RET
- Некоторые версии языка C различают прописные и строчные буквы,
поэтому имя ассемблерного модуля должно быть представлено в том же
символьном регистре, какой используют для ссылки C-программы.
- В некоторых версиях языка C требуется, чтобы ассемблерные
программы, изменяющие регистры DI и SI, записывали их содержимое в
стек при входе и восстанавливали эти значения из стека при выходе.
- Ассемблерные программы должны возвращать значения, если это
необходимо, в регистре AX (одно слово) или в регистровой паре DX:AX
(два слова).
- Для некоторых версий языка C, если ассемблерная программа
устанавливает флаг DF, то она должна сбросить его командой CLD перед
возвратом.
ОСНОВНЫЕ ПОЛОЖЕНИЯ НА ПАМЯТЬ
________________________________________________________________
- В основной программе, вызывающей подпрограмму, необходимо
определять точку входа как EXTRN, а в подпрограмме - как PUBLIC.
- Будьте внимательны при использовании рекурсий, когда подпрограмма 1
вызывает подпрограмму 2, которая в свою очередь вызывает подпрограмму 1.
- Если кодовые сегменты необходимо скомпоновать в один сегмент, то
необходимо определить их с одинаковыми именами, одинаковыми классами и
атрибутом PUBLIC.
- Для простоты программирования начинайте выполнение с основной
программы.
- Определение общих данных в основной программе обычно проще (но не
обязательно). Основная программа определяет общие данные как PUBLIC, а
подпрограмма (или подпрограммы) - как EXTRN.
ВОПРОСЫ ДЛЯ САМОПРОВЕРКИ
________________________________________________________________
21.1. Предположим, что программа MAINPRO должна вызвать под программу
SUBPRO. а) Какая директива в программе MAINPRO указывает ассемблеру, что
имя SUBPRO определено вне ее собственного кода? б) Какая директива в
подпрограмме SUBPRO необходима для того, чтобы имя точки входа было
доступно в основной программе MAINPRO?
21.2. Предположим, что в программе MAINPRO определены переменные QTY
как DB, VALUE как DW и PRICE как DW. Подпрограмма SUBPRO должна разделить
VALUE на QTY и записать частное в PRICE. а) Каким образом программа
MAINPRO указывает ассемблеру, что три переменные должны быть доступный
извне основной программы? б) Каким образом подпрограмма SUBPRO указывает
ассемблеру, что три переменные определены в другом модуле?
21.3. На основании вопросов 21.2 и 21.3 постройте работающую
программу и проверьте ее.
21.4. Измените программу из предыдущего вопроса так, чтобы программа
MAINPRO передавала все три переменные, как параметры. Подпрограмма SUBPRO
должна возвращать результат через параметр.
21.5. Теперь предлагаем упражнение, на которое потребуется больше
времени. Требуется расширить программу из вопроса 21.4 так, чтобы
программа MAINPRO позволяла вводить количество (QTY) и общую стоимость
(VALVE) с клавиатуры, подпрограмма SUBCONV преобразовывала ASCII-величины
в двоичное представление; подпрограмма SUBCALC вычисляла цену (PRICE); и
подпрограмма SUBDISP преобразовывала двоичную цену в ASCII-представление и
выводила результат на экран.
ГЛАВА 22 Программный загрузчик
__________________________________________________________________________
Ц е л ь: Раскрыть особенности загрузки выполнимых модулей в память
для выполнения.
ВВЕДЕНИЕ
________________________________________________________________
В данной главе описана организация базовой версии DOS и операции,
которые выполняет DOS для загрузки выполнимых модулей в память для
выполнения. DOS состоит из четырех основных программ, которые обеспечивают
конкретные функции:
1. Блок начальной загрузки находится на первом секторе нулевой
дорожки дискеты DOS, а также на любом диске, форматированном командой
FORMAT /S. Когда вы инициируете систему (предполагается, что DOS
расположен на дисководе A или C) происходит автоматическая загрузка с
диска в память блока начальной загрузки. Этот блок представляет собой
программу, которая затем загружает с диска в память три программы,
описанные ниже.
2. Программа IBMBIO.COM обеспечивает интерфейс низкого уровня с
программами BIOS в ROM; она загружается в память, начиная с адреса
шест.00600. При инициализации программа IBMBIO.COM определяет
состояние всех устройств и оборудования, а затем загружает программу
COMMAND.COM. Программа IBMBIO.COM управляет операциями ввода-вывода
между памятью и внешними устройствами, такими как видеомонитор и
диск.
3. Программа IBMDOS.COM обеспечивает интерфейс высокого уровня с
программами и загружается в память, начиная с адреса шест.00B00. Эта
программа управляет оглавлениями и файлами на диске, блокированием и
деблокированием дисковых записей, функциями INT 21H, а также содержит
ряд других сервисных функций.
4. Программа COMMAND.COM выполняет различные команды DOS, такие
как DIR или CHKDSK, а также выполняет COM, EXE и BAT-программы. Она
состоит из трех частей: небольшая резидентная часть, часть
инициализации и транзитная часть. Программа COMMAND.COM, подробно
рассмотренная в следующем разделе, отвечает за загрузку выполняемых
программ с диска в память.
На рис.22.1 показана карта распределения памяти. Некоторые элементы
могут отличаться в зависимости от модели компьютера.
__________________________________________________________________________
Начальный Программа
адрес
00000 Векторная таблица прерываний (см.гл.23)
00400 Область связи с ROM (ПЗУ)
00500 Область связи с DOS
00600 IBMBIO.COM
XXXX0 IBMDOS.COM
Буфер каталога
Дисковый буфер
Таблица параметров дисковода или таблица распределения файлов
(FAT, по одной для каждого дисковода)
XXXX0 Резидентная часть COMMAND.COM
XXXX0 Внешние команды или утилиты (COM или EXE-файлы)
XXXX0 Пользовательский стек для COM-файлов (256 байтов)
XXXX0 Транзитная часть COMMAND.COM, записывается в самые старшие
адреса памяти.
__________________________________________________________________________
Рис.22.1. Карта распределения DOS в памяти.
КОМАНДНЫЙ ПРОЦЕССОР COMMAND.COM
________________________________________________________________
Система загружает три части программы COMMAND.COM в память во время
сеанса работы постоянно или временно. Ниже описано назначение каждой из
трех частей COMMAND.COM:
1. Резидентная часть непосредственно следует за программой
IBMDOS.COM (и ее области данных), где она находится на протяжении
всего сеанса работы. Резидентная часть обрабатывает все ошибки
дисковых операций ввода-вывода и управляет следующими прерываниями:
INT 22H Адрес программы обработки завершения задачи.
INT 23H Адрес программы реакции на Ctrl/Break.
INT 24H Адрес программы реакции на ошибки дисковых операций
чтения/записи или сбойный участок памяти в таблице
распределения файлов (FAT).
INT 27H Завершение работы, после которого программа остается
резидентной.
2. Часть инициализации непосредственно следует за резидентной
частью и содержит средства поддержки AUTOEXEC-файлов. В начале работы
системы данная часть первой получает управление. Она выдает запрос на
ввод даты и определяет сегментный адрес, куда система должна
загружать программы для выполнения. Ни одна из этих программ
инициализации не потребуются больше во время сеанса работы. Поэтому
первая же команда вводимая с клавиатуры и вызывающая загрузку
некоторой программы с диска перекрывают часть инициализации в памяти.
3. Транзитная часть загружается в самые старшие адреса памяти.
"Транзит" обозначает, что DOS может перекрыть данную область другими
программами, если потребуется. Транзитная часть программы COMMAND.COM
выводит на экран приглашение DOS A> или C>, вводит и выполняет
запросы. Она содержит настраивающий загрузчик и предназначена для
загрузки COM- или EXE-файлов с диска в память для выполнения. Если
поступил запрос на выполнение какой-либо программы, то транзитная
часть строит префикс программного сегмента (PSP) непосредственно
вслед за резидентной частью COMMAND.COM. Затем она загружает
запрошенную программу с диска в память по смещению шест.100 от начала
программного сегмента, устанавливает адреса выхода и передает
управление в загруженную программу. Ниже приведена данная
последовательность:
IBMBIO.COM
IBMDOS.COM
COMMAND.COM (резидент)
Префикс программного сегмента
Выполняемая программа
...
COMMAND.COM (транзитная часть, может быть перекрыта).
Выполнение команды RET или INT 20H в конце программы приводит к
возврату в резидентную часть COMMAND.COM. Если транзитная часть была
перекрыта, то резидентная часть перезагружает транзитную часть с диска в
память.
ПРЕФИКС ПРОГРАММНОГО СЕГМЕНТА
________________________________________________________________
Префикс программного сегмента (PSP) занимает 256 (100H) байт и всегда
предшествует в памяти каждой COM- или EXE-программе, которая должна быть
выполнена. PSP содержит следующие поля:
00 Команда INT 20H (CD20).
02 Общий размер доступной памяти в формате хххх0. Напримеp, 512K