2812

Структура программы и модификаторы типа указателей в ОС MS-DOS

Лекция

Информатика, кибернетика и программирование

Лекция. Структура программы и модификаторы типа указателей в ОС MS-DOS В общем виде программа на языке C состоит из директив препроцессора, объявлений и определений объектов, команд, которые могут быть записаны как в одном, так и в нескольких моду...

Русский

2012-10-19

53.5 KB

4 чел.

Лекция 13

Структура программы и модификаторы типа указателей в ОС MS-DOS

В общем виде программа на языке C состоит из директив препроцессора, объявлений и определений объектов, команд, которые могут быть записаны как в одном, так и в нескольких модулях. В последнем случае при сборке программы создаётся файл проекта, в котором указываются имена всех входящих в проект файлов. Обязательно наличие одной и только одной функции main() в одном из файлов с исходными текстами. Функция main() задаёт точку входа в программу – с этой функции начинается и ей же заканчивается выполнение программы (в общем случае программа может быть завершена использованием системных функций завершения независимо от окончания функции main()).

Загрузочный модуль (типа .exe) ОС MS-DOS имеет структуру, показанную на рисунке 1.

Рис.1

Секция кода – содержит код программы (функции программиста и библиотечные функции).

Секция данных – содержит инициализируемые данные (глобальные и статические переменные) и неинициализируемые данные (константы).

Стек – используется для хранения автоматических объектов, передачи параметров и сохранения адреса возврата при вызове функции.

Ближняя куча (near heap) –динамически выделенная память.

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

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

Регистр процессора – это ячейка памяти внутри процессора. Процессоры x86 для адресации в реальном режиме работы используют 4 сегментных регистра: CS (регистр кода, по нему происходит адресация кода программы), DS (регистр данных, по нему происходит адресация данных), SS (регистр стека, по нему производится адресация стека) и ES (дополнительный регистр, как правило дублирует регистр данных). Регистр указывает на определённый адрес в памяти, из которого можно обращаться к 64K (размер одного сегмента) ячейкам памяти по смещению относительно сегментного регистра (чтобы адресоваться к ячейкам памяти, лежащим за пределами доступных 64K, необходимо изменять значение сегментного регистра, что при программировании на языке C явно делать крайне нежелательно). Указатель называется ближним (near), если он содержит только значение смещения (сегментный адрес берётся из соответствующего сегментного регистра), данный указатель может адресоваться к 64K ячейкам памяти. Указатель называется дальним (far), если он содержит и сегментный адрес, и смещение относительно сегментного адреса, данный указатель может адресоваться к 1M ячейкам памяти. Указатель может быть указателем типа huge. Отличие указателей типа far от указателей типа huge состоит в том, что при выполнении арифметических операций с указателем типа far изменяется только смещение, сегментная часть остается постоянной, и указатель типа far может адресоваться только к 64K ячейкам памяти, чтобы его сместить, необходимо в программе явно изменять сегментную часть (проводить нормализацию), а при выполнении арифметических операций с указателями типа huge изменяться также будет и сегментная часть, поэтому можно адресоваться к любой ячейке в пределах 1M, такой указатель хранится в памяти в нормализованном виде.

Длину указателя определяет специальный модификатор (near, far или huge), используемый при объявлении указателя.

Следует учитывать, что одна ячейка памяти – это один байт. Если указатель указывает на объект, размер которого отличен от 1 байта, то в пределах одного сегмента указатель может обращаться не к 64K элементам, а к 64K/(размер типа) элементам. Например, указатель типа float в пределах сегмента будет обращаться к 64K/4=16K элементам, которые будут занимать 64K ячеек памяти.

Пример 1

float near *f;

int far *i;

char huge *c;

Модели памяти.

Особенности операционной системы MS-DOS требуют дополнительных уточнений относительно распределения памяти ЭВМ. Для этого определяются 6 моделей памяти.

Модель TINY.

Общий объём памяти для кода, данных и стека – 64K. Все указатели – ближние.

Модель SMALL.

Общий объём памяти для кода – 64K, для данных и стека – 64K. Все указатели по умолчанию – ближние, но для данных могут использоваться и дальние указатели. Начиная с этой модели в программе появляется возможность использования дальней кучи (far heap) для динамического использования памяти. К дальней куче могут обращаться только дальние указатели.

Модель MEDIUM.

Рекомендуется для больших программ с малым количеством статических данных. Общий объём памяти для кода каждого модуля – 64K, для данных и стека – 64K. Указатели данных по умолчанию – ближние, указатели функций по умолчанию – дальние.

Модель COMPACT.

Рекомендуется в случае с малым объёмом кода, но большим объёмом данных. Общий объём памяти для кода – 64K, для данных – 64K, для стека – 64K. Указатели данных по умолчанию – дальние, указатели функций по умолчанию – ближние. Начиная с этой модели отсутствует ближняя куча.

Модель LARGE.

Общий объём памяти для кода каждого модуля – 64K, для данных – 64K, для стека – 64K. Все указатели – дальние.

Модель HUGE.

Общий объём памяти для кода каждого модуля – 64K, для данных каждого модуля – 64K, для стека – 64K. Все указатели – дальние.

Данные модели памяти используются в среде Borland C++ 3.1 для ОС MS-DOS. Установка модели осуществляется в диалоговом окне Code Generation, вызываемом командой меню Options>Compiler>Code Generation.

Динамическое распределение памяти

Динамическое распределение памяти используется для выделения памяти для хранения данных в процессе работы программы, когда общий объём данных и сами данные на этапе написания программы не известны, а становятся известны лишь на этапе выполнения программы. Динамическое распределение памяти позволяет получить необходимый объём памяти для ближней или дальней кучи, в зависимости от типа указателя и модели памяти. Для этого существуют специальные библиотечные функции, описанные в файле alloc.h.

Процесс работы с динамической памятью:

  •  получение динамической памяти заданного объёма;
  •  работа с данными, распределяемыми в динамической памяти (если необходимо, то возможно перераспределение выделенного объёма памяти с сохранением находящихся в нём данных);
  •  освобождение динамической памяти по окончании работы с данными.

Для получения блока динамической памяти используются функции malloc() и calloc(). Прототипы функций:

void* malloc(size_t size);

void* calloc(size_t nitems, size_t size);

Функция malloc() в качестве аргумента принимает размер запрашиваемого блока в байтах. Функция calloc() в качестве первого аргумента принимает число элементов, под которые необходимо выделить память, в качестве второго аргумента – размер одного элемента в байтах. Тип size_t аналогичен типу unsigned int. Функции в случае успешного выделения возвращают указатель на тип void, содержащий адрес выделенного блока, который нужно явно преобразовать к указателю на необходимый тип данных. В случае ошибки (как правило связанной с тем, что такого объёма свободной памяти нет) функции возвращают значение NULL. NULL – это стандартная константа языка C, которая обозначает нулевой указатель. После выполнения динамического распределения памяти необходимо обязательно проверять, какое значение возвратили функции. Если значения указателя – NULL, то работа с памятью невозможна (в большинстве случаев следует завершить программу).

Для перераспределения уже выделенного объёма памяти используется функция realloc(). Прототип функции:

void* realloc(void* block, size_t size);

Функция изменяет размер ранее выделенного блока, сохраняя его содержимое. В качестве первого аргумента функция принимает адрес ранее выделенного блока, в качестве второго аргумента – новый размер блока, при этом новый блок может оказаться в другом месте кучи. Функция в случае успешного выделения возвращает указатель на тип void, содержащий адрес нового блока, который нужно явно преобразовать к указателю на необходимый тип данных. Функция возвращает NULL, если размер нового блока больше размера старого блока, и в памяти нет свободного места для размещения нового блока.

Для освобождения блока динамической памяти используется функция free(). Прототип функции:

void free(void* block);

Функция выполняет освобождение блока памяти, адрес которого принимает в качестве аргумента. Все блоки динамической памяти должны быть освобождены по окончании работы с ними, иначе они так и останутся занятыми по окончании работы программы до перезагрузки системы, что приведёт к утечке оперативной памяти.

В среде Borland C++ 3.1 для работы с дальней кучей необходимо использовать дальние указатели и соответствующие функции, но с приставкой far.

Пример 2

#include <stdio.h>

#include <alloc.h>

#include <stdlib.h>

void main(void)

{

int n,m;

printf("Input string number\n");

scanf("%d",&n);

printf("Input column number\n");

scanf("%d",&m);

float *f,sum=0;

if((f=(float*)malloc(n*m*sizeof(float)))==NULL)

{

 printf("System do not have free memory\n");

 exit(1);

}

printf("Input matrix");

for(int i=0;i<n;i++)

 for(int j=0;j<m;j++)

 {

  printf("\nmatrix[%d][%d]=",i,j);

  scanf("%f",(f+i*m+j));

 }

if((f=(float*)realloc(f,(n+1)*m*sizeof(float)))==NULL)

{

 printf("System do not have free memory\n");

 exit(1);

}

for(int t=0;t<m;t++,sum=0)

{

 for(int j=0;j<n;j++)

  sum+=*(f+j*m+t);

 *(f+n*m+t)=sum;

}

for(int k=0;k<n+1;k++)

{

 printf("\n");

 for(int j=0;j<m;j++)

  printf("%f\t",*(f+k*m+j));

}

free(f);

}


 

А также другие работы, которые могут Вас заинтересовать

48541. ЗАРОЖДЕНИЕ ЭКОНОМИЧЕСКОЙ НАУКИ 57 KB
  Они считали что приумножение богатства требует протекционистских мер по регулированию внешней торговли того чтобы поощрялся экспорт сдерживался импорт и всемерно поддерживалась национальная промышленность. Источником богатства меркантилисты считали неэквивалентный обмен в результате торговых взаимоотношений с другими государствами. Его труд посвящался проблеме преобразований в российской экономике направленных на преодоление бедности и преумножение богатства. Он считал что труд является источником богатства и в промышленности и в...
48542. Элементы автоматических устройств электрических систем 5.83 MB
  Сравнивает ток реле и ток уставки: Iр Iуст. Элемент воздействия выходные реле. ТЕМА: РЕЛЕ Реле элемент сравнивающий входную величину с заданной уставкой. Элементарное реле имеет одну входную величину и может принимать два значения: 0 и1.
48543. МЕТАДАННЫЕ 608.79 KB
  Метаданные — это данные о данных, которые описывают характеристики объектов-носителей данных, способствуют обнаружению, идентификации, оценке и управлению этими данными, включают определения объектов, относящихся к данным, разработчикам, пользователям и средствам взаимодействия.
48544. Методи вимірювання теплоємності і тепловмісту 6.86 MB
  Вимірювання ентальпії методом змішування. Вимірювання теплоємності. Прилади які використовуються для вимірювання ентальпії або теплоємності називаються калориметрами а методика вимірювання калориметрією.
48545. ГЕОГРАФИЧЕСКИЕ ИНФОРМАЦИОННЫЕ СИСТЕМЫ И БД 2.06 MB
  Сергей Щербина Общие сведения о ГИС Большинство используемых данных с которыми работают информационные системы имеют пространственную привязку географические координаты т. Сервисы Google Mps и Google Erths фактически представляющие собой базовую инфраструктуру геоданных продемонстрировали потенциал уже завоевавших популярность географических информационных систем ГИС. Простота ввода и агрегации данных с помощью сервиса Google Erth позволяет видеть в нем прообраз ГИС будущего простых в использовании открытых сред.
48546. БАЗЫ ДАННЫХ КАК ОСНОВА ДЛЯ ПОДДЕРЖКИ РЕШЕНИЙ 524.21 KB
  Сферы Воздух Вода Земля Био Количественные сведения о состоянии природной среды Наблюдения Диагноз Прогноз Климат После явления Сведения об объекте Перечень воздействий ЛПР Качественные сведения о ситуации время года климатический район тип объекта уровень принятия решений ЭММ Перечень рекомендаций Объект Оперативные Тактические Стратегические XII. БАЗЫ ДАННЫХ КАК ОСНОВА ДЛЯ ПОДДЕРЖКИ РЕШЕНИЙ Проблемы поддержки решений в современных условиях Роль информации при принятии решений Принципы создания СППР Выявление знаний Примеры...
48547. Перспективы развития БД 3.17 MB
  Перспективы развития БД Развитие компьютерной техники Развитие ядра СУБД Развитие внешнего окружения Развитие средств работы с БД Развитие моделей данных Сенсорные сети Технологии обслуживания нового поколения Развитие компьютерной техники За последние 25 лет тактовая частота процессоров возросла с МГц до ГГц оперативная память с нескольких сотен Кбайт до Гигабайт а память на дисках со 100 Мбайт до Тбайт и более. Рабочая нагрузка типового компьютера будущего потребует обработки Тбайт данных и производительности на терафлопном уровне....
48548. Базы данных. Модели данных 1.19 MB
  В настоящее время, а тем более в будущем, в условиях широкой информатизации общества все большее распространение будут получать справочные системы, системы информационной поддержки деятельности учреждений, системы поддержки принятия решений, системы автоматизированного учета и контроля, системы автоматизированного проектирования и множество других систем на базе средств информационных и коммуникационных технологий.
48549. Старажытныя цывілізацыі 650 KB
  Крыніцы вывучэння гісторыі Беларусі. Гісторыя Беларусі вывучаецца на аснове разнастайных гістарычных крыніц. Першымі на тэрыторыю Беларусі прыйшлі фінаугорскія плямены якія раней жылі за Уралам. Больш глыбокія вынінікі для Беларусі і Еўропы мела перасяленне індаеўрапейцаў.