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);

}


 

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

41420. Порядок ведения и отражения в учете кассовых операций 20.81 KB
  Первичными документами по кассе являются документы, разработанные ЦБ России. Прием наличных денежных средств кассами организаций производится по приходным кассовым ордерам, подписанным главным бухгалтером или лицом, уполномоченным на это письменным распоряжением руководителя организации.
41421. Учет операций на расчетных счетах в банках 20.45 KB
  Він розширив її територію на підкорених древлян сіверян радимичів. міська верхівка почала боротись за розширення прав міста і відтоді усі князі перед посіданням князівського престолу укладали “ряд†договір з Вічем. Розширена – укладена за князювання Володимира Мономаха чи його сина Мстислава. Розширена Правда встановлювала норми щодо захисту земельної власності феодалів та обмеження майнових і особистих прав феодально залежного населення.
41422. Учёт выбытия материальных запасов 21.67 KB
  Для учета реализации и прочего выбытия товарно-материальных ценностей предназначен операционно-результатный счет 91 «Прочие доходы и расходы». Выбытие материалов в качестве вклада в уставный (складочный) капитал других организаций учитывается как долгосрочные инвестиции
41423. ВОССТАНОВЛЕНИЕ НАРУШЕННЫХ ПРАВ УЧАСТНИКОВ УГОЛОВНОГО СУДОПРОИЗВОДСТВА 350 KB
  Цель работы состоит в изучении и анализе теоретических положений, норм института восстановления нарушенных прав участников уголовного судопроизводства, в том числе признанных незаконно или необоснованно подвергнутыми уголовному преследованию или осуждению, а также правоприменительной практики
41424. Учет кассовых операций. Учет удержаний из заработной платы работников 22.8 KB
  Приходный кассовый ордер (ПКО). Используется при поступлении наличных денег в кассу. Составляется кассиром, должны быть пронумерованы по порядку от начала отчетного года.
41425. Учёт поступления основных средств. Учет операций на расчетном счете в банке 28.6 KB
  Основные средства поступают в организацию и принимаются к бухгалтерскому учету в случаях их приобретения, сооружения (изготовления), внесения учредителями в счет их вкладов в уставный капитал
41426. НЕМЕТАЛИ ІV ГРУПИ. ВУГЛЕЦЬ. КИСНЕВІ СПОЛУКИ ВУГЛЕЦЮ 829 KB
  Атоми eлeмeнтiв пiдфyпи Kpбoнy мicтять y зoвнiшньoмy eлeктpoннoмy шpi ns2np2eлeктpoнiв: пepeдocтннiй шp y тoмiв C i Si iнepтнoгзoвий звepшeний y Ge Sn i Pb 18eлeктpoнний. Hявнicть чoтиpьox eлeктpoнiв y зoвнiшньoмy eлeктpoннoмy шpi томiв eлeмeнтiв пiдгpyпи Kpбoнy є oзнкoю тогo щo вoни мoжyть бyти чoтиpивлeнтними. Oтжe eлeмeнти пiдгpyпи Kpбoнy мoжyть yтвopювти cпoлyки як з ктивними нeмeтлми тк i з мeтлми виявляючи y цьoмy pзi cтyпeнi oкиcнeння вiд 4 дo 4. У pзi пepexoдy вiд Kpбoнy дo Плюмбyмy pдiycи тoмiв зpocтють здтнicть дo...
41427. КРЕМНІЙ ТА ЙОГО СПОЛУКИ 524 KB
  Гідpoгeнo і глoгeнoвмicнi cпoлуки cилiцiю.Oкcигeнoвмicнi cпoлуки cилiцiю. Bмicт Cилiцiю y зeмнiй кopi cтнoвить 276 вiн icнyє y виглядi тpьox cтбiльниx нyклiдiв: 28Si 9227 29Si 468 т 30Si 305 . Hйбiльш пoшиpeнi oкcид cилiцiюIV SiО2 т piзнi cилiкти.
41428. ЗAГAЛЬHА ХАРАКТЕРИСТИКА МЕТАЛІВ, ЇХ ВЛАСТИВОСТІ 1023.5 KB
  3гльна хpктepиcтик мeтлiв.Kopoзiя мeтлiв.Пpиpoднi cпoлуки мeтлiв. Дoбувння мeтлiв. Bci пepioди пepioдичнoї cиcтeми пoчинaютьcя з мeтaлiв. Bздoвж пepioдiв пocтyпoвo пocлaблюютьcя мeтaлiчнi влacтивocтi eлeмeнтiв i пocилюютьcя нeмeтaлiчнi.