CSeg : Word -- Содержимое регистра CS процессора

DSeg : Word -- Содержимое регистра DS процессора

SSeg : Word -- Содержимое регистра SS процессора

SPtr : Word -- Содержимое регистра SP процессора

При работе программы ее текущий исполнимый код находится в кодовом сегменте, что фиксируется в регистре CS, а статические переменные основного блока и типизированные константы располагаются в сегменте данных, который запоминается регистром DS. Локальные переменные и параметры процедур и функций при вычислениях располагаются в стеке, и сегмент стека содержится в регистре SS. Последний регистр – SP – содержит смещение указателя стека в сегменте SSeg.

<p>10.4. Тип Pointer</p>

В Турбо Паскале предопределен специальный адресный тип Pointer — указатель: можно объявлять переменные, значением которых будет адрес ячейки памяти:

VAR

Р : Pointer; { переменная-указатель }

Значения этого типа занимают 4 байта памяти и содержат адрес какой-либо ячейки памяти. Адрес хранится как два слова: одно из них определяет сегмент, а другое — смещение. Значение указателя не может быть в явном виде выведено на экран или печать. Его надо предварительно расшифровывать. Для работы с указателями

- 190 -

вводится специальный набор функций. Кроме того, указатели полностью совместимы со ссылочным типом и могут использоваться (с оговорками) как ссылки. Указатели могут обмениваться значениями через оператор присваивания (:=), и сравниваться операторами = и <>. Но сравнение их — весьма ненадежная операция. Так, когда два указателя содержат один и тот же адрес в памяти, но записанный в них разными способами, они считаются различными. Таким образом, два указателя считаются одинаковыми, если в них записаны одинаковые значения сегмента и смещения. Во всех остальных случаях они считаются неравными. Понятия «больше» и «меньше» к значениям типа Pointer неприменимы.

Если мы хотим указать в программе на значение по указанному в переменной типа Pointer адресу, то мы должны использовать символ «^» после имени указателя, например: Р^. Это есть операция разыменования. Подробно этот вопрос рассмотрен при описании работы со ссылками, а особенности разыменования указателей обсуждаются вместе с работой функции Ptr.

<p>10.5. Средства для работы с адресами</p>

В разд. 10.3 были рассмотрены средства анализа расположения частей работающей программы. Обсудим инструментарий, применимый к данным, используемых программой. Это операции достаточно низкого уровня, но некоторые из рассматриваемых здесь функций можно с успехом применять и на более высоком уровне, в частности при работе с ссылками и динамическими данными. Список таких функций приведен в табл. 10.2.

Таблица 10.2

Функция : Тип -- Возвращаемое значение

Addr(X) : Pointer -- Ссылка на начало объекта X в памяти

Seg(X) : Word -- Сегмент, в котором хранится объект X

Ofs(X) : Word -- Смещение в сегменте для объекта X

Prt(S, O : Word) : Pointer -- Ссылка на место в памяти, заданное значениями смещения O и сегмента S

SizeOf(X) : Word -- Размер объекта X в байтах

Операция @X : Pointer -- Возвращает ссылку на начало объекта X памяти (аналог функции Addr)

<p>10.5.1. Определение адреса переменных</p>

Функции Addr(X), Seg(X) и Ofs(X), а также оператор @ возвращают адрес объекта X или компоненты адреса. Под X можно понимать любой объект: переменные любых типов, объекты, процедуры и функции (но не константы).

Функция Addr(X) и оператор @ возвращают значение типа Pointer — адрес объекта X. Их действие одинаково:

VAR

X : String; p, q : Pointer;

...

р: = Addr( X );

q: = @X;

{Теперь p=q, и адреса равны; они указывают на один объект }

Значение типа Pointer не может быть выведено на экран. Но так как этот тип состоит из двух слов (Word), хранящих сегмент и смещение, можно вывести их в отдельности, используя функции Seg и Ofs (обе типа Word):

WriteLn( 'Сегмент ', Seg( р ), ' смещение ', Ofs( р ));

В то же время значения ссылок можно получить в режиме отладки. Они будут выводиться в окна наблюдения и модификации (Watch и Evaluate).

Может возникнуть вопрос — а зачем вообще нужна функция Addr, если есть Seg и Ofs, тем более что нельзя распечатать ее значение? Ответ: функция Addr и оператор @ нужны для привязывания ссылок, т.е. динамических переменных, к статическим данным, а также для работы с массивами данных в виде OBJ-файлов, связанных с выполнимым файлом на этапе компоновки. Пример компоновки внешних данных дан при описании работы с образом экрана на диске в разд. 20.4 «Работа с образом экрана на диске».

Заметим, что если P — ссылка, то Addr(P) или @P, а также Seg(P) и Ofs(P) вернут адрес или сегмент со смещением самой переменной-ссылки P в области статических данных, но Addr(P^) или @Р^ и Seg(P^) с Ofs(P^) возвратят содержимое ссылки P, т.е.

Р = Addr( Р^).

Перейти на страницу:

Поиск

Похожие книги