Лекция 28.ppt
- Количество слайдов: 19
Структура резидентной программы. Структура EXE-, COM- файлов. Процедурные типы. Передача функций в качестве параметров Лекция 28
Прерывание — это особое состояние вычислительного процесса. В момент прерывания нарушается нормальный порядок выполнения команд программы и управление передается специальной процедуре, которая входит в состав ДОС и называется процедурой обработки прерывания. Каждое прерывание характеризуется в рамках ДОС порядковым номером и связано со своей процедурой обработки. Для связи с любыми процедурами прерываний используются векторы прерываний - четырехбайтные абсолютные адреса точек входа в эти процедуры. Векторы прерываний располагаются в младших адресах оперативной памяти, начиная с нулевого адреса: прерывание номер 0 — по адресу 0, номер 1 — по адресу 1*4 = 4, номер N — по адресу N * 4.
С помощью следующих двух процедур программист может прочитать содержимое любого вектора или установить его новое значение. Процедура GETINTVEC. Возвращает вектор прерывания с указанным номером. Обращение: GETINTVEC (
При нормальном завершении программы она выгружается из памяти. Вы можете прекратить работу программы и оставить ее резидентной в памяти, если воспользуетесь процедурой KEEP, которая завершает программу и оставляет ее в памяти. Procedure Keep(Exit. Code : Word); Вся программа остается в памяти, включая сегмент данных, сегмент стека и кучу, так что необходимо задать максимальный размер кучи, с использованием директивы компилятора $M. Параметр Exit. Code соответствует параметру, передаваемому в стандартную процедуру Halt.
Резидентная программа (или TSR-программа, от англ. Terminate and Stay Resident — «завершиться и остаться резидентной» ) — в операционной системе MS-DOS программа, вернувшая управление оболочке операционной системы, либо надстройке над операционной системой, но оставшаяся в оперативной памяти персонального компьютера. Резидентная программа активизируется каждый раз при возникновении прерывания, вектор которого эта программа изменила на адрес одной из своих процедур. Резидентные программы - это постоянно находящиеся в памяти программы помощи, калькуляторы, справочники и словари, русификаторы, вирусы и многое другое. Находясь в оперативной памяти, резидентная программа пассивна до наступления ключевого события — таким событием может быть прерывание.
Структура резидентной программы Резидентные программы состоят из двух частей: резидентной и вспомогательной части. При запуске программы выполняется только вспомогательная часть, подготавливающая резидентную часть к активизации. Вспомогательная часть выполняет следующие действия: 1. ) сохраняет векторы "захватываемых" прерываний во внутренних переменных; 2. ) устанавливает эти векторы по адресу резидентной части программы; 3. ) инициализирует внутренние переменные резидентной части; 4. ) завершает работу программы без удаления резидентной части из памяти компьютера.
С того момента как резидентная часть программы находится в оперативной памяти, и на нее указывает вектор "захваченного" прерывания, она может быть активизирована путем вызова этого прерывания. Построение резидентной части может осуществляться по трем схемам выполнения. • Сначала вызывается системная обработка, а затем производится добавочная пользовательская обработка, написанная программистом. Эта схема подходит в том случае, когда программист хочет чем-либо дополнить системную обработку. • Выполняется сначала пользовательская обработка и только потом системная. Этот случай пригоден для изменения содержимого регистров или осуществления каких-либо действий перед системной обработкой. • Полностью исключается системная обработка и заменяется пользовательской.
Структура EXE-, COM- файлов Структура COM - файла проста. В файлах данного типа содержатся только машинный код и данные программы. Размер COM - файла ограничен 64 кб, т. е. размером одного сегмента памяти. В основном COM файлы пишут на языке Ассемблера, но это не обязательно. Написать файл можно на любом языке, который можно потом компилировать.
Структура EXE файла Состоять EXE файлы могут из нескольких сегментов, следовательно их размер не ограничен 64 кб. По структуре EXE файл сложнее, кроме кода программы в файле также содержатся: заголовок файла, таблица настройки адресов, данные и т. п. Примерная структура EXE файла: • Заголовок EXE файла - содержит данные необходимые для загрузки программы. • Тело программы - основная часть программы, выполняющая какие-либо действия. • Конец программы - завершающая часть программы, которая сохраняет нужные и удаляет ненужные данные из оперативной памяти, закрывает все открытые данной программой файлы и т. п.
Процедурные типы Основное назначение процедурных типов - дать программисту гибкие средства передачи функций и процедур в качестве фактических параметров обращения к другим процедурам и функциям. Для объявления процедурного типа используется заголовок процедуры (функции), в котором опускается ее имя, например: type Proc 1 = procedure(a, b, с: Real; var d: Real); Ргос2 = procedure; Func 1 = function: string; Func 2 = function(var s: string): Real;
После объявления процедурного, или функционального, типа его можно использовать для описания формальных параметров – имен процедур и функций. Кроме того, необходимо написать те реальные процедуры или функции, имена которых будут передаваться как фактические параметры. После определения процедурного типа появляется возможность описывать переменные этого типа. Такие переменные называют процедурными переменными. Как и целая переменная, которой можно присвоить значение целого типа, процедурной переменной можно присвоить значение процедурного типа. Таким значением может быть, конечно, другая процедурная переменная, но оно может также представлять собой идентификатор процедуры или функции.
Как и при любом другом присваивании, значения переменной в левой и в правой части должны быть совместимы по присваиванию. Процедурные типы, чтобы они были совместимы по присваиванию, должны иметь одно и то же число параметров, а параметры на соответствующих позициях должны быть одинакового типа. Имена параметров в описании процедурного типа никакого влияния не оказывают.
Кроме того, для обеспечения совместимости по присваиванию процедура или функция, если ее нужно присвоить процедурной переменной, должна удовлетворять следующим требованиям: 1) это не должна быть стандартная процедура или функция; 2) такая процедура или функция не может быть вложенной; 3) она не должна быть процедурой прерывания (interrupt). Использование процедурных типов не ограничивается просто процедурными переменными. Как и любой другой тип, процедурный тип может участвовать в описании структурного типа.
Когда процедурной переменной присваивается значение процедуры, то на физическом уровне происходит следующее: адрес процедуры сохраняется в переменной. Фактически процедурная переменная весьма напоминает переменную-указатель, только вместо ссылки на данные она указывает на процедуру или функцию. Как и указатель, процедурная переменная занимает 4 байта (два слова), в которых содержится адрес памяти.
Параметры процедурного типа Поскольку процедурные типы допускается использовать в любом контексте, то можно описывать процедуры или функции, которые воспринимают процедуры и функции в качестве параметров. Параметры процедурного типа особенно полезны в том случае, когда над множеством процедур или функций нужно выполнить какие-то общие действия. Если процедура или функция должны передаваться в качестве параметра, они должны удовлетворять тем же правилам совместимости типа, что и присваивании. Такие процедуры или функции должны компилироваться с директивой far, они не могут быть встроенными функциями, не могут быть вложенными и не могут описываться с атрибутом interrupt.
Рассмотрим пример. Пусть необходимо вывести таблицы значений трех функций: sin(x), sin(x)*cos(х) и sin(x)/x. Напишем процедуру вывода таблицы значений функции, использующую функцию в качестве параметра. type func=function(x: real): real; {$F+} {включаем дальний вызов функций} function f 1(х: real): real; begin f 1: =sin(x); end; function f 2(х: real): real; begin f 2: =sin(x)*cos(x); end;
function f 3(x: real): real; begin f 3: =sin(x)/x; end; {$F-} {отключаем дальний вызов функций} {вывод таблицы произвольной функции f на отрезке [а, b]с шагом h} procedure fun_table(f: func; a, b, h: real); var x: real; begin x : =a ; while x<=b do begin writeln(x: 8: 2, ’ ‘, f(x): 8: 2); x: =x+h end;
writeln; end; {процедуры вывода таблицы функции} begin {выводим таблицы трех функций f 1, f 2 и f 3 на разных отрезках} fun_table(f 1, 0, 3. 14, 0. 5) ; fun_table(f 2, 0, 1. 57, 0. 2); fun_table(f 3, -5, 5, 2) ; readln; end.
Домашнее задание • 1. Составить опорный конспект лекции по теме «Структура резидентной программы» на основе презентации. • 2. Turbo Pascal. Немнюгин С. А. СПб. : Питер, 2002, cтр. 155 -183.


