Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
BorlandPascal.doc
Скачиваний:
54
Добавлен:
17.03.2015
Размер:
2.83 Mб
Скачать

Переменная SelectorInc

Переменная SelectorInc модуля System содержит значение, ко-

торое должно прибавляться к селектору или вычитаться из него для

получения следующего или предыдущего селектора в таблице дескрип-

торов. SelectorInc полезно использовать при работе с большими

блоками памяти (превышающими 64К) и при доступе к псевдонимам

сегментов.

Для выделения блоков, превышающих 64К (такие блоки называют

также большими блоками памяти), можно использовать функции

GlobalAlloc и GlobalAllocPrt в модуле WinAPI. Большие блоки неп-

рерывны в физической памяти, но из-за 16-разрядной архитектуры

процессора прикладная программа не может получить к ним доступ

целиком. Для большого блока памяти администратор памяти выделяет

несколько непрерывных (следующих подряд) селекторов, каждый из

которых (кроме последнего) ссылается на часть большого блока па-

мяти размером 64К. Например, чтобы выделить блока памяти размером

в 220К, администратор памяти создает четыре селектора, при этом

первые три селектора ссылаются на блоки по 64К, а последний се-

лектор - на блок размером 28К. Прибавляя SelectorInc к селектору,

принадлежащему большому блоку, вы можете получить селектор для

следующего сегмента, а вычитая SelectorInc - для предыдущего.

При распределении большого блока функция GlobalAlloc всегда

возвращает описатель первого сегмента, а GlobalAllocPtr - указа-

тель на первый сегмент.

Приведенная ниже функция GetPtr воспринимает указатель боль-

шого блока (возвращаемый функцией GlobalAllocPtr) и 32-разрядное

смещение и возвращает указатель на заданное внутри блока смеще-

ние.

function GetPtr(P: Pointer; Offset: Longint): Pointer;

type

Long = record

Lo, Hi: Word;

end;

begin

GetPtr := Ptr(

Long(P).Hi + Long(Offset).Hi * SelectorInc,

Long(P).Lo + Long(Offset).Lo);

end;

Заметим, что старшее слово параметра Offset используется для

определения того, сколько раз нужно увеличить селекторную часть P

для получения корректного сегмента. Например, если Offset равно

$24000, то селекторная часть P будет увеличена на 2 *

SelectorInc, а смещение P - на $4000.

Следующая функция LoadFile загружает в блок памяти весь файл

и возвращает указатель на блок. Если файл превышает 64К, то выде-

ляется большой блок памяти.

function LoadFile(const FileName: string): Pointer;

var

Buffer: Pointer;

Size, Offset, Count: Longint;

F: file;

begin

Buffer := nil;

Assign(F, FileName);

Reset(F, 1);

Size := FileSize(F);

Buffer := GlobalAllocPtr(gmem_Moveable, Size);

if Buffer <> nil then

begin

Offset := 0;

while Offset < Size do

begin

Count := Size - Offset;

if Count > $8000 then Count := $8000;

BlockRead(F, GetPtr(Buffer, Offset)^, Count);

Inc(Offset, Count);

end;

end;

LoadFile := Buffer;

end;

Переменная SelectorInc определена также в версии модуля

System для реального режима. В реальном режиме она всегда содер-

жит значение $1000, которое при сложении его с сегментной частью

указателя реального режима увеличивает указатель на 64К.

Другим образом вы можете использовать переменную SelectorInс

только в программах DOS защищенного режима. Используйте перемен-

ную SelectorInc для доступа к псевдонимам сегментов, выделяемых

администратором этапа выполнения при загрузке прикладной програм-

мы. Для каждого сегмента кода прикладной программы администратор

этапа выполнения создает селектор-псевдоним, ссылающийся на тот

же сегмент, но имеющий полномочия селектора данных. Для сегментов

стека и данных селекторы-псевдонимы не создаются.

Чтобы получить доступ к селектору-псевдониму для конкретного

сегмента, добавьте к селектору сегмента SelectorInc. Предположим,

например, что P - это переменная типа Pointer, а Foo - процедура

или функция. Тогда присваивание вида:

P := Addr(Foo)

приводит к тому, что P будет указывать на выполняемую доступную

только по чтению точку входа Foo, а после оператора:

P := Ptr(Seg(Foo) + SelectorInc, Ofs(Foo));

P будет ссылаться на тот же адрес, но с полномочиями на чте-

ние/запись.

Соседние файлы в предмете Программирование на Pascal