Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

Просмотров: 3055

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.


1. Создать новую процедуру, вызывающую прерывание 60H.

2. Перенести вектор прерывания для 16H в 60H.

3. Изменить вектор 16H, чтобы он указывал на новую процедуру.

4. Завершить программу, оставляя ее резидентной [1.3.4].




Раздел 3. Управление программами.




Большинство программ загружаются в память, запускаются, а

затем удаляются операционной системой при завершении. Языки высо-

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

ассемблере имеется другая возможность и данный раздел демонстри-

рует ее. Некоторые программы действуют как драйверы устройств

или драйверы прерываний и они должны быть сохранены в памяти

("резидентными") даже после их завершения (вектора прерываний

обеспечивают механизм, посредством которого последующие программы

могут обращаться к резидентным процедурам). Иногда программе

необходимо запустить из себя другую программу. На самом деле DOS

позволяет программе загрузить в память вторую копию COMMAND.COM,

которая может использована как средство интерфейса с пользовате-

лем или выполнения команд типа COPY или DIR.

Программы могут быть в двух форматах: .EXE или .COM. Программы

первого типа могут быть больше 64K, но они требуют некоторой

обработки перед тем, как DOS загрузит их в память. С другой сто-

роны COM программы существуют прямо в том формате, который нужен

для загрузки в память. COM программы особенно полезны для корот-

ких утилит. В обоих случаях код, составляющий программу, предва-

ряется в памяти префиксом программного сегмента (PSP). Это об-

ласть размером 100H байт, которая содержит информацию необходимую

DOS для работы программы; PSP также обеспечивает место для файло-

вых операций ввода/вывода [5.3.5]. При загрузке EXE файла и DS и

ES указывают на PSP. Для COM файлов CS также сначала указывает на

PSP. Отметим, что MS DOS 3.0 имеет функцию, которая возвращает

номер сегмента PSP. Это функция 62H прерывания 21H; ей ничего не

надо подавать на входе, а в BX возвращается номер параграфа.

Одна из причин, по которой интересно положение PSP, состоит в

том, что его первое слово содержит номер прерывания DOS, которое

будет приводить к завершению программы. Когда выполняется послед-

ний оператор RET программы, то значения на вершине стека указы-

вают счетчику команд (регистр IP) на начало PSP, таким образом

код завершения выполняется как следующая инструкция программы.

Дальнейшее обсуждение этого смотрите в пунктах [1.3.4] и [1.3.6].


Для справки приводим значение полей PSP:


Смещение Размер поля Значение

0H DW номер функции DOS завершения программы

2H DW размер памяти в параграфах

4H DW резерв

6H DD длинный вызов функции диспатчера DOS

AH DD адрес завершения (IP,CS)

EH DD адрес выхода по Ctrl-Break (IP,CS)

12H DD адрес выхода по критической ошибке

16H 22 байта резерв


2CH DW номер параграфа строки среды

2EH 46 байтов резерв

5CH 16 байтов область параметров 1 (формат FCB)

6CH 20 байтов область параметров 2 (формат FCB)

80H 128 байтов область DTA по умолчанию/получает

командную строку программы




1.3.1 Манипуляции с памятью.




Когда MS DOS загружает программу, то она помещается в младшую

область памяти, сразу же за COMMAND.COM и установленными драйве-

рами устройств или другими утилитами, которые резидентны в памя-

ти. В этот момент времени вся память за программой отведена этой

программе. Если программе нужна память для создания области дан-

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

код и затем поместить требуемую область данных в любое место за

концом кода. Для определения адреса конца программы поместите в

конце программы псевдосегмент типа:


ZSEG SEGMENT

;

ZSEG ENDS


В ассемблере IBM PC ZSEG будет последним сегментом, так как

сегменты располагаются в алфавитном порядке. С другими ассембле-

рами нужно действительно поместить эти строки в конце программы.

В самой программе достаточно поставить оператор MOV AX,ZSEG и AX

будет указывать на первый свободный сегмент памяти за программой.

Такой подход будет работать до тех пор, пока программа не

будет предполагать о наличии памяти, которой на самом деле нет.

Он не будет также работать в многопользовательской среде, когда

несколько программ могут делить между собой одну и ту же область

адресов. Для решения этой проблемы MS DOS имеет возможность отс-

леживать 640K системной памяти и отводить по требованию программы

блоки памяти любого размера. Блок памяти - это просто непрерывная

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

доступной памяти, в частности, он может быть больше одного сег-

мента (64K). Если затребован слишком большой блок, то DOS выдает

сообщение об ошибке. Любая возможность перекрытия блоков исключе-

на. Кроме того MS DOS может освобождать, урезать или расширять

существующие блоки. Хотя программа не обязана использовать эти

средства, но удобно и предусмотрительно делать это. Некоторые

функции DOS требуют, чтобы были использованы средства управления

памятью DOS, например, завершение резидентной программы [1.3.4]

или вызов другой программы из данной [1.3.2].

Прежде чем отвести память, существующий блок (вся память от

начала программы до конца) должен быть обрезан до размера прог-

раммы. Затем, при создании блока, DOS создает 16-байтный управ-

ляющий блок памяти, который расположен непосредственно перед

блоком памяти. Первые 5 байтов этого блока имеют следующее значе-

ние:


байт 0 ASCII 90 - если последний блок в цепочке, иначе

ASCII 77.

байты 1-2 0 если блок освобожден

байты 3-4 размер блока в 16-байтных параграфах


DOS обращается к блокам по цепочке. Адрес первого блока хра-


нится во внутренней переменной. Значение этой переменной позво-

ляет DOS определить положение первого отведенного блока, а из

информации, содержащейся в нем, может быть найден следующий блок



и т.д., как показано на рис. 1-4. Как только Вы начали использо-

вать систему распределения памяти DOS, то Вы обязаны придержи-

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

то цепочка будет разорвана и DOS начнет выдавать сообщения об

ошибке.

MS DOS обеспечивает три функции распределения памяти, номера

от 48H до 4AH прерывания 21H. Функция 48H отводит блок памяти, а

49H - освобождает блок памяти. Третья функция ("SETBLOCK") ме-

няет размер памяти, отведенной для программы; эта функция должна

быть использована перед двумя остальными. После ее выполнения

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

должна освободить все отведенные ею блоки перед завершением.

Иначе эта память будет недоступной для последующего использова-

ния.


Средний уровень.


Все три функции распределения памяти прерывания 21H используют

16-битный адрес начала блока памяти, с которым они оперируют.

Этот адрес соответствует сегменту, с которого начинается блок

(блок всегда начинается со смещения 0 данного сегмента). Таким

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

умноженному на 16. Также, для всех трех функций, BX содержит

число 16-байтных разделов памяти (параграфов), которые будут

отводиться или освобождаться. Если функция не может быть выполне-

на, то устанавливается флаг переноса, а в AX возвращается код

ошибки, объясняющий причину. Возможны три кода ошибки:


7 разрушен управляющий блок памяти

8 недостаточно памяти для выполнения функции

9 неверный адрес блока памяти


Функция отведения блока использует коды 7 и 8, а освобождения - 7

и 9, в то время как функция изменения блока использует все три

кода. В следующем примере сначала отводится блок, размером 1024

байта. При этом BX содержит требуемое число 16-байтных парагра-

фов, а при завершении стартовый адрес блока равен AX:0 (т.е.

смещение 0 в сегменте со значением, содержащимся в AX). Вторая

часть примера освобождает этот же блок, как и требуется при за-

вершении программы. В данном случае значение полученное в AX

помещается в ES. DOS следит за размером блока и знает какое коли-

чество параграфов надо освободить.


;---отведение блока размером 1024 байта

MOV AH,48H ;номер функции

MOV BX,64 ;требуем 64 параграфа

INT 21H ;пытаемся отвести блок

JC ERROR ;обрабатываем ошибку в случае неудачи

MOV BLOCK_SEG,AX;иначе сохраняем адрес блока

.

;---освобождаем тот же блок

MOV AX,BLOCK_SEG ;получаем стартовый адрес блока

MOV ES,AX ;помещаем его в ES

MOV AH,49H ;номер требуемой функции

INT 21H ;освобождаем блок памяти



Наконец, приведем пример использования функции 4AH. ES содер-


жит значение сегмента PSP, т.е. самого первого байта памяти, с

которого загружена программа. Это значение присваивается ES при

старте задачи. Для использования SETBLOCK надо либо вызывать эту

функцию в самом начале программы (прежде чем ES будет изменен),

либо сохранить его начальное значение для последующего использо-

вания.

BX содержит требуемый размер блока в 16-байтных параграфах.

Для определения этого размера поместите добавочный "искуственный"

сегмент в конец программы. В макроасссемблере IBM PC сегменты

располагаются в алфавитном порядке, поэтому Вы можете поместить

его в любое место программы, при условии, что его имя это что-то

вроде "ZSEG". В других ассемблерах действительно помещайте фик-

тивный сегмент в конец программы. Программа может прочитать пози-

цию этого сегмента и, сравнивая ее со стартовым сегментом, полу-

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

рузки программы и ES и DS содержат номер параграфа самого начала

программы в префиксе программного сегмента; для COM файлов CS

также указывает на эту позицию, но для EXE файлов это не так.

;---освобождение памяти (ES имеет значение при старте)

MOV BX,ZSEG ;получаем # параграфа конца программы + 1

MOV AX,ES ;получаем # параграфа начала программы

SUB BX,AX ;вычисляем размер программы в параграфах

MOV AH,4AH ;номер функции

INT 21H ;освобождаем память

JC MEMORY_ERROR ;проверяем на ошибку


;---

ZSEG SEGMENT

ZSEG ENDS




1.3.2 Запуск одной программы из другой.




MS DOS обеспечивает функцию EXEC (номер 4BH прерывания 21H),

реализующую вызов одной программы из другой. Первая программа

называется "родителем", а загружаемая и запускаемая - "потомком".


Высокий уровень.


В Бейсик версии 3.0 введена команда SHELL. Со значительными

ограничениями она позволяет бейсиковской программе загрузить и

выполнить другую программу. Формат этой команды SHELL ком_строка.

Командная строка может быть просто именем программы или она может

содержать кроме имени параметры, которые обычно следуют за именем

программы в командной строке. Если ком_строка не указана, то

загружается копия COMMAND.COM и появляется запрос операционной

системы. В этот момент можно выполнить любую команду MS DOS, а по

завершению вернуть управление бейсиковской программе, введя ко-

манду EXIT.

Имеется ряд ограничений при использовании SHELL. Если загру-

жаемая программа меняет режим работы дисплея, то он не будет

автоматически восстановлен при возврате. Перед загрузкой програм-

мы все файлы должны быть закрыты, и это не может быть программа,

которая остается резидентной после завершения. Обсуждение ряда

других проблем содержится в руководстве по Бейсику.


Средний уровень.


Функция 4BH более сложна, чем остальные, требуя четырех подго-

товительных шагов:


1. Подготовить в памяти место, доступное программе.


2. Создать блок параметров.

3. Построить строку, содержащую накопитель, путь и имя прог-

раммы.

4. Сохранить значения регистров SS и SP в переменных.


Поскольку при загрузке программы MS DOS выделяет ей всю дос-

тупную память, то необходимо освободить место в памяти. Если не

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

программы. В [1.3.1] объяснено как это сделать с помощью функции

SETBLOCK. После того как память освобождена, Вы должны просто

поместить в BX требуемое число 16-байтных параграфов, заслать 4AH

в AH и выполнить прерывание 21H, делая доступным программе именно

то число параграфов, которое ей требуется.

Блок параметров, на который должны указывать ES:BX это

14-байтный блок блок памяти, в который Вы должны поместить сле-

дующую информацию:


DW сегментный адрес строки среды

DD сегмент и смещение командной строки

DD сегмент и смещение первого FCB

DD сегмент и смещение второго FCB



Строка среды - это строка, состоящая из одной или более специ-

фикаций, которым следует MS DOS при выполнении программы. Элемен-

ты строки среды такие же, как и те что можно обнаружить в диско-

вом файле CONFIG.SYS. Например, в строку может быть помещено

VERIFY = ON. Просто начните строку с первого элемента, завершив

его символом ASCII 0, потом запишите следующий и т.д. За послед-

ним элементом должны следовать два символа ASCII 0. Строка должна

начинаться на границе параграфа (т.е. ее адрес по модулю 16 дол-

жен быть равен нулю). Это вызвано тем, что соответствующий вход в

блоке параметров, указывающий на строку, содержит только 2-байт-

ное сегментное значение. Все это не нужно, если новая программа

может работать с той же строкой среды, что и программа "роди-

тель". В этом случае надо просто поместить два символа ASCII 0 в

первые 2 байта блока параметров.

Следующие 4 байта блока параметров указывают на командную

строку для загружаемой программы. "Командная строка" - это сим-

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

ке программы из DOS она может иметь вид вроде EDITOR A:CHAPTER1\

NOTES.MS. При этом вызывается редактор и ему передается имя файла

в подкаталоге накопителя A для немедленного открытия. Когда Вы

подготавливаете командную строку для EXEC, то надо включать толь-

ко последнюю часть информации, но не имя загружаемой программы.

Перед командной строкой должен стоять байт, содержащий длину этой

строки, и она должна завершаться символом <ВК> (ASCII 13).

Последние 8 байтов блока параметров указывают на управляющие

блоки файлов (FCB). FCB содержит информацию об одном или двух

файлах, указанных в командной строке. Если открываемых файлов

нет, то надо заполнить все 8 байт символом ASCII 0. В [5.3.5]

объяснено, как работает FCB. Начиная с версии MS DOS 2.0, исполь-

зование FCB необязательно и Вы можете не включать информацию FCB,

вместо этого используя новую конвенцию дескриптора файлов (file