Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LektsiiS.doc
Скачиваний:
81
Добавлен:
13.04.2015
Размер:
815.1 Кб
Скачать

21.3 Спецификация указателей

Размер указателей определяется выбранной моделью памяти, однако, независимо от модели, можно специфицировать указатели при помощи ключевых слов near, far и huge. Например,

Int near* var_name;

З а м е ч а н и е. Если поместить модификатор между "*" и именем переменной

Int* near var_name;

он повлияет на расположение указателя, а не на его размер.

Указатели huge отличаются от указателей far тем, что с ними можно делать арифметические операции, не опасаясь выйти за границу сегмента. Для DOS-программ смещение huge-указателя никогда не будет превышать 15. В среде Windows способ нормализации определяется опцией компилятора -h.

21.4 Макросы для указателей

Заголовочный файл DOS.H определяет три макроса, облегчающих работу с указателями на платформе DOS.

Unsigned FP_OFF(void far *p) — возвращает смещение указателя p;

unsigned FP_SEG(void far *p) — возвращает сегмент указателя p;

void far *MK_FP(unsigned seg, unsigned ofs) — создает указатель из значений сегмента и смещения.

Макросы FP_OFF и FP_SEG применимы и к адресным выражениям.

Сегментное значение, используемое компилятором при разыменовании ближнего указателя, зависит от указываемого объекта: для указателя на данные это регистр DS, для указателя на функции — регистр CS. Можно явно задать сегментный регистр для короткого указателя при помощи спецификаторов: __cs, __ds, __es, __ss. При этом программист должен позаботиться о содержимом соответствующих регистров.

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

21.5 Модификаторы переменных

Все модели памяти, кроме huge, выделяют один сегмент для всех глобальных данных. С помощью модификатора far переменную можно ра местить в дальнем сегменте данных. Если компилятором выдается сообщение "Слишком много глобальных данных", опишите несколько больших переменных с модификатором far.

Модификатор huge , кроме этого, преодолевает ограничение на размер переменной, связанное с размером сегмента. Например, можно определить большой массив:

char huge x[0x1FFFF];

З а м е ч а н и е. Все переменные с модификатором far или huge должны быть глобальными.

П р и м е р.

char huge m[70000L];

void main()

{

// не работает, m кажется транслятору ближним указателем

m[69999L] = 5;

// вариант 1 — работает

char far *h = m;

h[69999L] = 5;

// вариант 2 — работает

((char far *)m)[69999L] = 6;

}

21.6 Модификаторы функций

Как и указатели данных, функции и указатели на функции являются ближними или дальними в зависимости от модели памяти. Подразумеваемый размер указателя можно изменить модификаторами near и far, например

void far farFun(int i);

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

Функции-обработчики прерываний DOS, написанные на С, должны иметь модификатор interrupt, например

void interrupt newHandler(void);

Это приводит к генерации кода, который:

— сохраняет и восстанавливает регистры при входе и выходе из функции;

— заносит в регистр DS адрес сегмента данных по умолчанию, предоставляя доступ к глобальным переменным программы;

— завершает выполнение функции инструкцией IRET.

Сохранение и восстановление всех регистров обеспечивается модификатором _saveregs. Это бывает полезно, если ваша функция вызывается из программы, написанной на ассемблере.

Модификаторы _loadds и _export при входе в функцию загружает в регистр DS значение сегмента данных, а при выходе восстанавливает его прежнее значение.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]