русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Основные понятия


Дата добавления: 2015-09-15; просмотров: 873; Нарушение авторских прав


Динамические переменные

В IBM- совместимых компьютерах память условно разделена на сегменты: перенумерованные блоки памяти по 64 Кбайта. Сегмент может начинаться с любого физического адреса оперативной памяти. Положение места объекта в памяти определяется с помощью номера сегмента и его смещением в сегменте, то есть номером байта от начала сегмента.

Длина адресов сегмента и смещения – 16 бит, поэтому размер сегмента не может превышать 216 байт (64 Кбайт). При вычислении адреса байта в оперативной памяти адрес сегмента сдвигается на четыре двоичных разряда влево и к нему прибавляется смещение. Таким образом, длина адреса составляет 20 бит, с его помощью можно адресовать память объёмом 220 байт (1Мбайт).

Схема вычисления адреса

Компилятор Паскаля формирует сегмент кода, в котором хранится программа в виде машинных команд, сегмент данных, в котором выделяется память под глобальные переменные, и сегмент стека, предназначенный для размещения локальных переменных во время выполнения программы.

Адреса сегментов хранятся во время выполнения программы в сегментных регистрах: CS - адрес сегмента кода, DS - адрес сегмента данных, SS - адрес сегмента стека.

Глобальными называются переменные, описанные в главной программе. Переменные, которые не были инициализированы явным образом (речь идет о типизированных константах), перед началом выполнения программы обнуляются. Напомним, что время жизни глобальных переменных - с начала программы и до её завершения.

Внутри подпрограмм описываются локальные переменные. Они располагаются в сегменте стека, причем распределение памяти происходит в момент вызова подпрограммы, а её освобождение – по завершении подпрограммы. Таким образом, время жизни локальных переменных - с начала работы подпрограммы и до её окончания. Значения локальных переменных между двумя вызовами одной и той же подпрограммы не сохраняются, и эти переменные предварительно не обнуляются, то есть в соответствующих ячейках памяти находятся произвольные значения.



    Структура исполняемой программы в оперативной памяти

Ниже представлена общая схема EXE-файла, полученного после компиляции некоторой программы на языке Turbo Pascal. Схема составлена по аналогии с рисунком из фирменной документации по системе Turbo Pascal. Адреса оперативной памяти на этой схеме увеличиваются снизу вверх.

В начале программы операционная система формирует так называемый PSP(Program Segment Prefix –Префикс Сегмента Программы) – область размером 256 байт с информацией о программе.

Сегментный адрес PSP и, следовательно, адрес начала программы содержится в системной переменной PrefixSeg модуля System. Отметим, что программа при загрузке в память всегда начинается с границы параграфа и занимает целое число параграфов (непрерывных участков памяти размером в 16 байт).

Далее следуют компоненты кода, загруженные непосредственно из EXE- файла программы. Структура этой части, в общем, соответствует структуре исходного текста программы. Каждый модуль (главная программа и все используемые модули) образует свой кодовый сегмент. Главная программа занимает первый от младших адресов кодовый сегмент. Далее следуют кодовые сегменты модулей в порядке, обратном тому, как они следовали в uses- спецификации. Последний кодовый сегмент занимает образ модуля System (этот модуль по умолчанию подключается к каждой программе). Модуль System по традиции, идущей от «больших» компьютеров, иногда называют библиотекой времени выполнения (Runtime library).

 

Размер одного кодового сегмента не может превышать 64 Кбайт, но общий размер кода ограничен только имеющейся оперативной памятью.

После сегмента модуля System располагаются значения типизированных констант, собранные из всех описаний программы, независимо от их уровня вложенности. Область после типизированных констант отводится для хранения глобальных переменных (описанных во внешнем блоке). Таким образом, видно, что память под эти объекты отводится статически, на основе подсчёта суммарного объёма, необходимого для хранения.

Типизированные константы и глобальные переменные образуют сегмент данных программы, который адресуется посредством регистра DS (Data Segment - Сегмент Данных). Значение этого регистра во время выполнения программы не изменяется. Содержимое регистра DS может быть получено с помощью стандартной функции (без параметров) DSeg. Размер сегмента данных не может превышать 64 Кбайт.

Вслед за сегментом данных находится сегмент стека, используемый для управления локальными переменными подпрограмм. Стековый механизм поддерживается аппаратурой центрального процессора: сегмент стека адресуется специальным регистром SS (Stack Segment - Сегмент Стека), значение которого также не изменяется во время выполнения программы. Его можно получить обращением к стандартной функции (без параметров) SSeg. Другой регистр процессора – SP (Stack Pointer – Указатель Стека) всегда адресует начала свободной части сегмента стека (вершину стека). В процессе вызова подпрограмм и выходов из них значение регистра SP изменяется (вершина стека «передвигается» в пределах сегмента стека). Текущее значение регистра SP можно получить обращением к стандартной функции (без параметров) SPtr (смещение SP относительно SS). Отметим, что стек всегда начинается («растёт») с конца области памяти, выделенной под сегмент стека, к его началу, адресуемому SP.

Размером памяти, выделяемой для стека, можно управлять директивой $M.

{$M, stacksize, heapmin, heapmax} – задание размеров памяти.

С помощью этого ключа задаются размеры элементов памяти: stacksize - размер стека (от 1024 до 65520 байт), heapmin - минимальный размер динамической памяти (от 0 до 655360 байт), heapmax - максимальный размер динамической памяти (от heapmin до 655360 байт). По умолчанию задаются размеры: {$M16384, 0, 655360}. Ключ является глобальным и эквивалентен меню Options| Memory sizes.

Этот размер не может превышать 64Кбайт. Рамер по умолчанию –16 Кбайт, минимально возможный размер – 1Кбайт. Последний часто используется в примерах, когда необходимо минимизировать общий размер программы при выполнении. Стек заполняется от верхней границы к нижней границе. Для установки контроля за переполнением стека используется директива {$S}.

{$S+/-} – проверка стека.

Если используется ключ {$S+}, при каждом обращении к подпрограмме проверяется наличие достаточного места в стеке для локальных параметров. Если такого места нет, программа прекращает работу и выдаётся сообщение об ошибке. В случае ключа {$S-} эта ситуация приведёт к фатальной ошибке в работе системы. Ключ является локальным. По умолчанию используется ключ {$S+}.Эквивалент меню - Options| Compiler| Stack checking.

Если в процессе выполнения программы стек будет полон, попытка

разместить в нём значения при вызове очередной подпрограммы вызовет ошибку этапа выполнения программы:

202 Stack overflow (переполнение стека).

Выше стека может находиться буфер оверлеев, который предназначен для обеспечения выполнения оверлейных структур. Буфер используется для временной подкачки кодов модулей из оверлейного файла данной программы. Его размер по умолчанию соответствует размеру наибольшего оверлейного модуля в программе. Если в программе нет оверлеев, то размер буфера равен 0 (то есть буфер отсутствует).

Организация буфера оверлеев и работа с ним обеспечивается средствами системного модуля Overlay. Размер буфера определяется динамически, в процессе выполнения программы, с помощью собственных средств модуля Overlay (процедуры OvSetBuf). Важно отметить, что память под данный буфер отводится за счёт размера динамической памяти кучи, выделяемой программе. В этом случае её размер соответственно уменьшается. Сегментные адреса начала и конца буфера оверлеев определяются типизированными константами модуля System: OvrHeapOrg и OvrHeapEnd.

Оставшаяся часть памяти, выделяемой программе, используется для динамической памяти (кучи), которая хранит переменные, образуемые вызовами стандартных процедур New и GetMem. Размер кучи определяется минимально допустимым и максимальным значениями. Они также устанавливаются директивой $M. Размер кучи никогда не будет меньше минимального значения и не превысит максимального. Фактический размер динамической памяти зависит также от реального объёма свободной памяти перед запуском программы. Куча может иметь размер в 0 байт, то есть отсутствовать, или занимать всю оставшуюся свободную память. Максимальный её размер составляет 640 Кбайт. По умолчанию предполагается директива {$M16384, 0, 655360}. Все значения задаются в десятичной или шестнадцатеричной системе счисления. Две следующие директивы идентичны: {$M16384, 0, 655360} – в десятичной системе счисления, и {$M$4000, $0, $A000} – в шестнадцатеричной системе. Управление динамической памятью осуществляется специальным монитором, который входит в состав библиотеки времени выполнения, то есть модуля System.

Кратко опишем назначение системных указателей по динамической памяти. Куча организована по стековому принципу и используется, начиная от нижних адресов памяти. Сегментный адрес нижней границы («начала») кучи хранится в системной переменной HeapOrg, а её «вершина» (или, одновременно, нижняя граница свободной памяти) содержится в системной переменной HeapPtr. При каждом выделении памяти для динамической переменной указатель HeapPtr передвигается вверх на размер этой переменной. Верхняя граница кучи (и всей программы) всегда находится по адресу, хранящемуся в системной переменной HeapEnd.

 



<== предыдущая лекция | следующая лекция ==>
Утилита nslookup. | Статические и динамические переменные


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.005 сек.