Страница 42 из 56
- 343,344 -
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
РАЗМЕР ДАННЫХ РАЗМЕР ПРОГРАММЫ
ННННННННННННННННННННННННННННННННННННННННННННННННННН
64К 1М
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
64К Крохотная(данные и програм-
ма перекрываются;
общий размер 64К)
Малая (не перекрываются; Средняя
общий размер 128К) (малые данные,большая
программа)
1М Компактная Большая
(большие данные,малая (большие данные и
программа) программы)
Огромные (аналогично
большой, только данные
больше 64К )
ННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Таблица 12.1. Модели памяти.
Важное замечание. Когда вы компилируете модуль (указывая ис-
ходный файл, содержащий несколько функций), результирующая прог-
рамма не может быть более 64К, т.к. все функции должны включаться
в один программный сегмент. Это верно, даже если вы используете
модели с большими программами (среднюю, большую и огромную). Если
ваш модуль больше величины одного программного сегмента (64К), то
вы должны разделить его на разные исходные программные файлы, от-
компилировать каждый файл в отдельности и затем объединить их
вместе. Проще говоря, хотя огромная модель и позволяет статичес-
ким данным занимать объем больше, чем 64К, в каждом модуле все
равно должно быть меньше, чем 64К.
- 345,346 -
Порядок программирования смешанных моделей памяти:
модификация типа адресации
-----------------------------------------------------------------
Турбо Си вводит семь новых ключевых слов, отсутствующих в
стандартном (Керниган и Ритчи или ANSI) Си: near, far, huge, _cs,
_ds, _es, _ss. С некоторыми ограничениями и предупреждениями они
могут использоваться как модификаторы указателей (в отдельных
случаях функций).
В Турбо Си вы можете модифицировать функции и указатели, ис-
пользуя ключевые слова near, far или huge. Ранее в этом разделе
мы объясняли суть near-, far- и huge- указателей к данным. Near-
функции вызываются ближними запросами и заканчиваются ближними
возвратами. Far-функции, соответственно, вызываются удаленно и
завершаются удаленными возвратами. Huge-функции подобны far-функ-
циям, но, в отличие от них, huge могут изменять содержимое ре-
гистра DS.
Есть также четыре специальных near-указателя к данным: _cs,
_ds, _es, _ss. Это 16-битные указатели, которые специфически свя-
заны с соответствующими сегментными регистрами. Например, если вы
объявите указатель
char _ss *p ;
то p будет содержать 16-битное смещение в стековом сегменте.
Функции и указатели в программе по умолчанию устанавливаются
near или far в зависимости от выбранной вами модели памяти. Если
функция или указатель near, то она автоматически связывается либо
с CS, либо с DS регистром.
Таблица 12.2 показывает, как это происходит. Заметим, что ве-
личина указателя соответствует или работе в рамках 64К (near,
внутри сегмента), или работе в адресном пространстве до 1М (far,
имеет свой собственный адрес сегмента)
- 347,348 -
НННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Модель памяти Указатель к функции Указатель к данным
НННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Крохотная near,_cs near,_ds
Малая near,_cs near,_ds
Компактная far near,_ds
Средняя near,_cs far
Большая far far
Огромная far far
НННННННННННННННННННННННННННННННННННННННННННННННННННННННННН
Таблица 12.2. Результирующие указатели
Объявление функций как NEAR или FAR
-----------------------------------------------------------------
Иногда вам может захотеть (или понадобиться) отменить тип
функции, принимаемый по умолчанию для вашей модели памяти, пока-
занной в таблице 12.1. Например, предположим, вы используете
большую модель памяти, но имеете в вашей программе рекурсивную
(самовызывающуюся) функцию, такую как
double power (double x, int exp)
{
if (exp <= 0)
return(0);
else
return(x*power(x,exp-1));
}
Power постоянно вызывает сама себя. Это делается с помощью
удаленного вызова, что требует большего размера стека и более
длительных циклов. Объявив power как near, вы снимете некоторые
расходы, заставляя все вызовы к этой функции быть ближними:
- 349,350 -
double near power (double x, int exp)
Такое описание гарантирует, что power будет вызываема только
из того программного сегмента, в котором она оттранслирована, и
все ее вызовы будут near.
Это означает, что если вы используете большую программную
модель (среднюю, большую или огромную), вы можете вызывать power
только в том модуле, где она определена. Другие модули имеют свои
собственные программные сегменты и, следовательно, не могут вызы-
вать near-функции в других модулях. Более того, near-функция
должна быть определена или объявлена до первого ее использования,
иначе компилятор не сможет понять, что необходимо генерировать
near-вызов.
Наоборот, объявление функции far означает, что и возврат бу-
дет far. В малых программных моделях far-функции должны быть объ-
явлены или определены до первого их использования, что обеспечи-
вает их запуск через far-вызов.
Вернемся к примеру с power. Теперь понятно также, что необ-
ходимо объявить power как статическую, т.к. она будет вызываться
только внутри текущего модуля. В этом случае, если она будет ста-
тической, ее имя станет недоступно любой функции, находящейся вне
модуля. Так как power всегда задействует фиксированное число ар-
гументов, вы можете еще больше ее оптимизировать, объявив ее как
pascal, а именно:
static double near pascal power (double x, int exp)
- 351,352 -