Автор работы: Пользователь скрыл имя, 16 Сентября 2009 в 13:41, Не определен
Учебник по программированию
Все глобальные
переменные и типизированные
константы размещаются в одной
непрерывной области
Длина сегмента определяется архитектурой процессора 8086 и составляет 64 Килобайта (65536 байт), что может вызвать определённые трудности при описании и обработке больших массивов данных.
С
другой стороны объём стандартной памяти
- 640 Килобайт. Выход - использовать динамическую
память.
Динамическая память - это оперативная
память ЭВМ, предоставляемая Турбо-Паскалевой
программе при её работе, за вычетом сегмента
данных (64 К), стека (обычно 16 К) и собственно
тела программы.
По умолчанию размер динамической памяти
определяется всей доступной памятью
ЭВМ и, как правило, составляет не менее
200 - 300 Кбайт.
Динамическую память обычно используют при:
Размещение
статических переменных в памяти
осуществляется компилятором в процессе
компиляции.
Динамические переменные - размещаются в памяти непосредственно в процессе работы программы.
При динамическом размещении заранее неизвестны ни тип, ни количество размещаемых данных, к ним нельзя обращаться по именам, как к статическим переменным.
Турбо-Паскаль
представляет средство управления динамической
памятью: указатели.
Указатель - это переменная,
которая в хранит качестве своего значения
адрес байта памяти.
В 8086 адреса задаются совокупностью двух шестнадцатиразрядных слов - сегмента и смещения.
Сегмент - участок памяти, имеющий максимальную длину 64 К и начинающийся к физического адреса, кратного 16 (то есть 0, 16, 32, 48 и т.д.).
Смещение - указывает, сколько байт от начала сегмента нужно пропустить, чтобы обратиться по нужному адресу.
Фрагмент памяти в 16 байт называется параграфом.
Сегмент
адресует память с точностью до параграфа,
а смещение - с точностью до байта.
Каждому сегменту соответствует непрерывная
и отдельно адресуемая область памяти.
Сегменты могут следовать в памяти один
за другим, или с некоторыми интервалами,
или, наконец, перекрывать друг друга.
Таким
образом любой указатель по своей
внутренней структуре представляет
собой совокупность двух слов (типа
Word), трактуемых как сегмент и
смещение. Указатель адресует лишь
первый байт типа данных.
Справка: процессор 8086.
8086 имеет 16 - битовые регистры, всего 14
штук, из них:
Регистры данных и адресов делятся на три группы:
Процессор
8086 всегда генерирует 20-ти бытовые адреса
за счёт добавления 16-ти битового смещения
к содержимому регистра, умноженному
на 16:
физический адрес = смещение + 16 * регистр
сегмента.
Вместо
умножения на 16 содержимое регистра
сегмента используется так, как если бы
оно имело четыре дополнительных нулевых
бита:
пусть:
смещение = 10H
регистр сегмента = 2000H
тогда:
0000 0000 0001 0000 (смещение)
0010 0000 0000 0000 (0000) (номер блока)
0010 0000 0000 0001 0000 (физический адрес)
физический адрес = 20010H
У 8086 адрес ячейки задаётся номером блока и смещением, что обусловлено тем, что команды 8086 и её данные должны располагаться в разных частях памяти (в разных сегментах).
Если требуется адресоваться к данным, то потребуется адресация блока памяти, с которого начинается сегмент данных (из регистра сегмента данных) и позиция желаемой ячейки в этом сегменте (смещение).
В дополнение к области памяти 1 Мбайт, 8086 может адресоваться к внешним устройствам через 65536 (64 К) портов ввода-вывода. Имеются специальные команды ввода-вывода, позволяющие иметь непосредственный доступ к первым 256 (от 0 до 255) портам. Другие команды позволяют получить косвенный доступ к порту с помощью занесения идентифицирующего его номера (0 - 65535) в определенный регистр данных. Подобно ячейке памяти любой порт может быть 8 или 16- битовым.
Существуют 2 вида прерываний - одни можно игнорировать, другие обязательно обслужить как можно скорее.
(Операционная система MS - DOS все адресуемое пространство делит на сегменты.
Сегмент - это участок памяти размером 64 К байт.
Для
задания адреса необходимо определить
адрес начала сегмента и смещение
относительно начала сегмента.)
В TURBO PASCAL определен адресный тип Pointer - указатель.
Переменные типа Pointer
var
p: Pointer;
содержат
адрес какого - либо элемента программы
и занимают 4 байта, при этом адрес хранится
как два слова, одно из них определяет
сегмент, второе - смещение.
Переменную типа указатель можно описать другим способом.
type NameType= ^T;
var p: NameType;
Здесь p - переменная типа указатель, связанная с типом Т с помощью имени типа NameType.
Описать
переменную типа указатель можно
непосредственно в разделе
var
p: ^T;
Необходимо различать переменную типа указатель и переменную, на которую этот указатель ссылается.
Например если p - ссылка на переменную типа Т, то p^ - обозначение этой самой переменной.
Для переменных типа указатель введено стандартное значение NIL, которое означает, что указатель не ссылается ни к какому объекту. Константа NIL используется для любых указателей.
Над указателями не определено никаких операций, кроме проверки на равенство и неравенство.
Переменные
типа указатель могут быть записаны
в левой части оператора
Переменные типа указатель не могут быть элементами списка ввода - вывода.
Статической переменной (статически размещенной) называется описанная явным образом в программе переменная, обращение к ней осуществляется по имени.
Место в памяти для размещения
статических переменных
В отличие от таких статических переменных в программах, написанных на языке ПАСКАЛЬ, могут быть созданы динамические переменные.
Основное свойство динамических переменных заключается в том, что они создаются и память для них выделяется во время выполнения программы.
Размещаются динамические переменные в динамической области памяти (heap - области).
Динамическая переменная не указывается явно в описаниях переменных и к ней нельзя обратиться по имени.
Доступ
к таким переменным
осуществляется с
помощью указателей
и ссылок.
См. разд мат-л 1.
// Работа с динамической областью памяти в TURBO PASCAL реализуется с помощью процедур и функций New, Dispose, GetMem, FreeMem, Mark, Release, MaxAvail, MemAvail, SizeOf.
Процедура New( var p: Pointer ) выделяет место в динамической области памяти для размещения динамической переменной p^ и ее адрес присваивает указателю p.
Процедура Dispose( var p: Pointer ) освобождает участок памяти, выделенный для размещения динамической переменной процедурой New, и значение указателя p становится неопределенным.
Проуедура GetMem( var p: Pointer; size: Word ) выделяет участок памяти в heap - области, присваивает адрес его начала указателю p, размер участка в байтах задается параметром size.
Процедура FreeMem( var p: Pointer; size: Word ) освобождает участок памяти, адрес начала которого определен указателем p, а размер - параметром size. Значение указателя p становится неопределенным.
Процедура Mark( var p: Pointer ) записывает в указатель p адрес начала участка свободной динамической памяти на момент ее вызова.
Процедура Release( var p: Pointer ) освобождает участок динамической памяти, начиная с адреса, записанного в указатель p процедурой Mark, то-есть, очищает ту динамическую память, которая была занята после вызова процедуры Mark.
Функция MaxAvail: Longint возвращает длину в байтах самого длинного свободного участка динамической памяти.
Функция MemAvail: Longint полный объем свободной динамической памяти в байтах.
Вспомогательная функция SizeOf( X ): Word возвращает объем в байтах, занимаемый X, причем X может быть либо именем переменной любого типа, либо именем типа.
//
Рассмотрим некоторые примеры работы с указателями.
var
p1, p2: ^Integer;
Здесь p1 и p2 - указатели или пременные ссылочного типа.
p1:=NIL; p2:=NIL;
После
выполнения этих операторов
присваивания указатели p1
и p2 не будут ссылаться
ни на какой конкретный
объект.
New(p1); New(p2);
Процедура New(p1) выполняет следующие действия:
Аналогично, процедура New(p2) обеспечит выделение участка памяти, адрес которого будет записан в p2:
После выполнения операторов присваивания
p1^:=2; p2^:=4;
в
выделенные участки
памяти будут записаны
значения 2 и 4 соответственно:
В результате выполнения оператора присваивания
p1^:=p2^;
в
участок памяти, на который ссылается
указатель p1, будет записано значение
4: