Приведем здесь также несколько стандартных процедур, осуществляющих работу с директориями, а также с файлами, но внешним относительно самих файлов образом (без их открытия).
Процедура erase(f: file) удалит файл, связанный с файловой переменной f. Если такого файла нет, произойдет ошибка, реакцию на которую можно отрегулировать при помощи директивы компилятора {$I}.
Процедура rename(f: file; s: string) даст файлу, связанному с файловой переменной f, новое имя, указанное в строке s. Если такого файла нет, произойдет ошибка.
Процедура chdir(s: string) сделает текущей директорию, указанную в строке s. Если такой директории нет, произойдет ошибка.
Процедура getdir(disk: byte; s:string) запишет в строку s имя текущей директории на указанном диске (0 ― текущий диск, 1 ― диск А, 2 ― диск В и т.д.).
Процедура mkdir(s: string) создаст в текущей директории новую поддиректорию с указанным в строке s именем. Если в текущей директории уже существуют файл или директория с указанным именем, произойдет ошибка.
Процедура rmdir(s: string) удалит пустую директорию с заданным в строке s именем. Если такой директории нет, произойдет ошибка.
Пробельные символы
К пробельным символам (присутствующим в файле, но невидимым на экране) относятся:
· символ горизонтальной табуляции (#9);
· символ перевода строки (#10) (смещение курсора на следующую строку, в той же позиции);
· символ вертикальной табуляции (#11);
· символ возврата каретки (#13) (смещение курсора на начальную позицию текущей строки; в кодировке UNIX один этот символ служит признаком конца строки);
· символ конца файла (#26);
· символ пробела (#32).
СОДЕРЖАНИЕ РАБОТЫ: Создать программу считывания произвольного файла и создание нового нетипизированного файла, копируя блоками. Научиться использовать подпрограммы обработки директорий.
ВОПРОСЫ ВЫХОДНОГО КОНТРОЛЯ:
1. Приведите пример объявления нетипизированного файла.
2. Опишите структуру допустимых процедур и функций при работе с нетипизированными файлами.
3. Перечислите и опишите подпрограммы обработки директорий.
4. Перечислите пробельные символы.
ДОМАШНЕЕ ЗАДАНИЕ
Выучить определения нетипизированных файлов, процедуры допустимые для работы с типизированными и нетипизированными файлами.
ЛАБОРАТОРНАЯ РАБОТА №22 Тема: Разработка программ с использованием прерываний BIOS и DOS, процедурных типов
Цель: Развить умения разрабатывать программы с использованием процедурного типа
Программное обеспечение: TURBO PASCAL 7.1
Оснащение: персональный компьютер, практикум
Время проведения: 2 уч. часа
Литература:
Павловская Т.А. Паскаль. Программирование на языке высокого уровня. Учебник для вузов. СПб.: Питер, 2008. С. 153-163.
Время выполнения: 2 часа.
ВОПРОСЫ ВХОДНОГО КОНТРОЛЯ:
1. Перечислите типы файловых переменных, пример их объявления.
2. Запишите структуру процедур открытия и закрытия файла.
3. Перечислите и опишите подпрограммы обработки директорий.
КРАТКИЕ ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Структура *.ЕХЕ программ
Программа в формате ЕХЕ, созданная компоновщиком, состоит из следующих двух частей:
1) заголовка ― записи, содержащей информацию по управлению и настройке программы;
2) собственно загрузочного модуля.
В заголовке находится информация о размере выполняемого модуля, области загрузки в памяти, адресе стека и относительных смещениях, которые должны заполнить машинные адреса в соответствии с относительными шестнадцатеричными позициями:
00 ― (шестнадцатеричное 4D5A) компоновщик устанавливает этот код для идентификации правильного ЕХЕ файла;
02 ― число байтов в последнем блоке ЕХЕ файла;
04 ― число блоков по 512 байт ЕХЕ файла, включая заголовок;
06 ― число настраиваемых элементов;
08 ― число 16-ти байтовых блоков (параграфов) в заголовке (необходимо для локализации начала выполняемого модуля, следующего после заголовка);
0А ― минимальное число параграфов, которые должны находится после загруженной программы;
0С ― переключатель загрузки в младшие или старшие адреса. При компоновке пользователь должен решить, будет ли его программа загружаться для выполнения в младшие адреса памяти или в старшие. Обычным является загрузка в младшие адреса. Значение 0000 указывает на загрузку в старшие адреса, а FFFF ― в младшие. Иные значения определяют максимальное число параграфов, которые должны находиться после загруженной программы;
0Е ― относительный адрес сегмента стека в выполняемом модуле;
10 ― адрес, который загрузчик должен поместить в регистр SP перед передачей управления в выполнимый модуль;
12 ― контрольная сумма ― сумма всех слов в файле (без учета переполнения) используется для проверки потери данных;
14 ― относительный адрес, который загрузчик должен поместить в регистр IP до передачи управления в выполняемый модуль;
16 ― относительный адрес кодового сегмента в выполняемом модуле. Этот адрес загрузчик заносит в регистр CS;
18 ― смещение 1-ого настраиваемого элемента в файле;
1А ― номер оверлейного фрагмента: 0 означает, что заголовок относится к резидентной части ЕХЕ файла;
1С ― таблица настройки, содержащая переменное число настраиваемых элементов, соответствующее значению по смещению 06.
Заголовок имеет минимальный размер 512 байт и может быть больше, если программа содержит большое число настраиваемых элементов. Позиция 06 в заголовке указывает число элементов в выполняемом модуле, нуждающихся в настройке. Каждый элемент настройки в таблице, начинающейся в позиции 1С заголовка, состоит из 2-х байтовых величин смещений и 2-х байтовых сегментных значений. Система строит префикс программного сегмента (PSP) следом за резидентной частью COMMAND.COM, которая выполняет операцию загрузки. Затем COMMAND.COM осуществляет следующее:
― считывает форматированную часть заголовка в память;
― вычисляет размер выполнимого модуля (общий размер файла в позиции 04 минус размер заголовка в позиции 08) и загружает модуль в память с начала сегмента;
― считывает элементы таблицы настройки в рабочую область и прибавляет значение каждого элемента таблицы к началу сегмента (позиция 0E);
― устанавливает в регистрах SS и SP значения из заголовка и прибавляет адрес начала сегмента;
― устанавливает в регистрах DS и ES сегментный адрес PSP;
― устанавливает в регистре CS адрес PSP и прибавляет величину смещения в заголовке (позиция 16) к регистру CS. Если сегмент кода непосредственно следует за PSP, то смещение в заголовке равно 256 (100H). Регистровая пара CS:IP содержит стартовый адрес в кодовом сегменте, т.е. начальный адрес программы. После инициализации регистры CS и SS содержат правильные адреса сегментов, а регистр DS (и ES) должен быть настроен в программе на собственный сегмент данных:
Mov AX,datasegname; {Установить в DS}
Mov DS,AX; {адрес сегмента данных}
Структура СОМ - программ.
Различия между программами в ЕХЕ и СОМ файлах:
― РАЗМЕР ПРОГРАММЫ. Программа в формате ЕХЕ может иметь любой размер, в то время как СОМ-файл ограничен размером одного сегмента и не превышает 64 К. Размер СОМ-файла всегда меньше, чем размер соответствующего ЕХЕ-файла; одна из причин этого - отсутствие в СОМ-файле 512-байтового заголовка ЕХЕ-файла.
― СЕГМЕНТ СТЕКА. В ЕХЕ-программе определяется сегмент стека, в то время как СОМ-программа генерирует стек автоматически. Таким образом, при создании ассемблерной программы, которая будет преобразована в СОМ-файл, стек должен быть опущен.
― СЕГМЕНТ ДАННЫХ. В ЕХЕ-программе обычно определяется сегмент данных, а регистр DS инициализируется адресом этого сегмента. В СОМ-программе все данные должны быть определены в сегменте кода.
― ИНИЦИАЛИЗАЦИЯ. В ЕХЕ-программе выполняется инициализация регистра DS. Так как в СОМ-программе стек и сегмент данных не определены, то эти шаги отсутствуют. Когда СОМ-программа начинает работать, все сегментные регистры содержат адрес PSP ― 256 байтовый блок, который резервируется операционной системой DOS непосредственно перед СОМ- или ЕХЕ-программой в памяти. Так как адресация начинается со смещения 100Н от начала PSP, то в программе необходимо указать директиву ORG 100H.
Процедурные типы
В стандартном Паскале процедуры и функции рассматриваются только как части программы, которые можно выполнять с помощью вызова процедуры или функции. В описании процедурного типа задаются параметры, а для функции – результат функции.
Приведем некоторые примеры описаний процедурного типа:
type
Proc = procedure;
SwapProc = procedure(var X, Y: Integer);
StrProc = procedure(S: String);
MathFunc = function(X: Real): Real;
DeviceFunc = function(var F: text): Integer;
MaxFunc = function(A, B: Real; F: MathFunc): Real;
Имена параметров в описании процедурного типа играют чисто декоративную роль ― на смысл описание они не влияют.
Процедурные значения
Переменной процедурного типа можно присвоить процедурное значение. Процедурные значения могут быть следующими:
* значениями nil;
* ссылкой на переменную процедурного типа;
* идентификатором процедуры или функции.
МЕТОДИЧЕСКИЕ УКАЗАНИЯ
В контексте процедурных значений описание процедуры или функции можно рассматривать как специальный вид описаний констант, когда значением константы является процедура или функция.
Рассмотрим, например, следующее описание:
var
P: SwapProc;
F: MathFunc;
procedure Swap(var A, B: Integer); far;
var
Temp: Integer;
begin
Temp:= A;
A:= B;
B:= Temp;
end;
function Tan(Angle: Real); far;
begin
Tan:= Sin(Angle) / Cos(Angle);
end;
Переменным P и F можно присвоить значения следующим образом:
P:= Swap;
F:= Tan;
а вызовы с помощью P и F можно выполнить так:
P(I, J); { эквивалентно Swap(I, J) }
X:= F(X); { эквивалентно X:= Tan(X) }
Использование процедурных переменных, которым в операторе вызова процедуры или функции присваивается значение nil, приводит к ошибке. Значение nil предназначено для указания того, что процедурная переменная не присвоена, где процедурная переменная может получить значение nil, участвующие в этой процедурной переменной вызовы процедур и функций следует подвергать проверке: if @P <> nil then P(I, J);
Обратите внимание на использование операции @ для указания того, что P проверяется, а не вызывается.
СОДЕРЖАНИЕ РАБОТЫ: Разработать программу определения значений функций а=0; 0,5; 1,0 с использованием параметров процедурного или функционального типа.
Вариант | Задание |
№1 | |
№2 | |
№3 | |
№4 | |
№5 | |
№6 | |
№7 | |
№8 | |
№9 | |
№10 | |
№11 | |
№12 | |
№13 | |
№14 | |
№15 | |
№16 |
ВОПРОСЫ ВЫХОДНОГО КОНТРОЛЯ:
1. Опишите структуру переменных процедурного типа.
2. Перечислите процедур и функций обработки прерываний.
ДОМАШНЕЕ ЗАДАНИЕ
Выучить возможности обработки с использованием прерываний BIOS и DOS, структуру объявления процедурного типа.