[an error occurred while processing this directive]

5.6 Управление динамической памятью

procedure release(address, bytes : integer);

function claim(bytes : integer) : integer;

function free : integer;

Эти функции и процедура позволяют программисту резервировать области хранения данных, размеры которых определяются во время выполнения программы и использовать их. Функция 'claim' использует в качестве параметра размер резервируемой области в байтах, а возвращает абсолютный адрес начала области.

Процедура 'release' использует два параметра: адрес освобождаемого блока и его длину.

Функция 'free' возвращает количество байт, свободных для использования в качестве динамических структур данных. Теоретически, она возвращает размер самой большой области, которая может быть зарезервирована, практически же, можно использовать только 75 процентов свободной области, так как ее часть используется как системный стек.

Ниже приведен пример программы имитирующей операции 'peek' и 'poke':

.сс

.ми0

{¤U-}
{ It is necessary to turn unassigned checking off in case
address &B8B8 is accessed as the address &B8B8 is the
'unassigned' pointer value. Thus when fudge.addr^ is attempted,
unassigned checking code will object. }

program peek_poke(input,output);

type
byte = 0..255;
word = 0..65535;
fudgerec =
packed record
case boolean of
false : (addr : ^byte);
true : (int : word)
end;

var
i : word;
pi : byte;

function peek(address : word) : byte;
var
fudge : fudgerec;
begin
fudge.int:=address;
peek:=fudge.addr^
end;

procedure poke(address : word; value : byte);
var
fudge : fudgerec;
begin
fudge.int:=address;
fudge.addr^:=value
end;

begin
for i := &8000 to &8100 do
begin
pi := peek(i);
write(~i, ~pi);
if pi > 31 then
writeln(chr(pi) : 4)
else
writeln
end
end.

.нф

Можно заметить, что для задания адреса используется поле 'int', а для задания содержимого адреса - косвенное обращение по полю 'addr'.

5.7 Функции связи объектных модулей

function code0(address, a, x, y : integer) :
integer;
function code1(address, a : integer; var variable : anyType) :
integer;

Эти функции позволяют использовать в программах на Паскале подрограммы в виде кодов процессора 6502. Первая функция дает возможность обращаться к подпрограмме по указанному адресу с передачей параметров через регистры процессора. Возврат из подпрограммы должен происходить командой RTS. Результат функции - целое число, четыре байта которого имеют значение &PYXA, т.е. самый младший байт содержит значение аккумулятора, следующий - значение регистра X, и т.д.

Функция 'code1' дает возможность передавать значение между программой Паскаля и машинной подпрограммой через значение переменной. Первые два параметра - это адрес вызываемой подпрограммы и значение, помещаемое в аккумулятор. Третий параметр может быть любого типа. Адерс начала переменной передается подпрограмме в регистрах X и Y (младший, старший байты соответственно). Форматы и размеры различных типов описаны в 8-й главе.

Главное назначение функций 'code' - использовать возможности операционной системы, недоступных через стандартные процедуры и функции Паскаля. Например функцию Бейсика GET на Паскале можно реализовать следующим образом:

.ми0

.сс

program fgetp(input,output);
const
cr = 13;
etx = 128;

type
byte = 0..&FF;

var
i : byte;

function fget  : byte;
const
{ OS get char function. Returns code in A }
{ A, X and Y on entry are immaterial }
osrdch = &FFE0;
begin
fget := code0(osrdch,0,0,0) mod &100
end;

begin
repeat
i := fget;
if i=cr then
writeln
else
vdu(i)
until i=etx
end.

.нф

Функция названа 'fget', для того, чтобы не произошоло переопределения стандартной процедуры Паскаля 'get' (хотя в нашем примере это не существенно).

Функция code1 используется, когда требуется передать подпрограмме ОС блок параметров. Например подпрограмма 'чтение шаблона символа' (osword 10). Программа ниже печатает увеличенное изображение символа:

.ми0

.сс

program big(input,output);
var
ch : char;

procedure printChar(ch : char);
const
{ A=10 for char. definition. XY points to par. block }
osword = &FFF1;
getPatt = 10;
width = 8;
height = 8;

type
byte = 0..&FF;
xCoord = 1..width;
yCoord = 1..height;
parBlk = packed
record
ch : char;
patt : packed array[yCoord] of byte
end;

var
block : parBlk;
row : yCoord;
col : xCoord;
thisByte : byte;
dummy : integer;

begin
block.ch := ch;
dummy := code1(osword, getPatt, block);
for row := 1 to height do
begin
thisByte := block.patt[row];
for col := 1 to width do
begin
if thisByte >= 128 then
write('*')
else
write(' ');
thisByte := thisByte mod &80 * 2
end;
writeln
end
end;

begin {main}
for ch := ' ' to '~' do
begin
printChar(ch);
writeln
end
end.

.нф

Обратите внимание, что надо быть предельно точным, используя запись в качестве блока параметров. Должно быть полное соответствие между струтурой записи и форматом блока, используемого конкретным вызовом операционной системы. Например, если массив в 'блоке' не будет упакован, его элементы будут занимать по четыре байта вместо ожидаемого одного. В главе 8 подробно описываются форматы различных упакованных и неупакованных типов данных.

5.8 Прочие функции

Последнее расширение относится к синтаксису оператора 'case'. Действие 'otherwise' выполняется в том случае, если значению параметра оператора 'case' не соответствует ни одна из констант из основного тела оператора. Это избавляет от необходимости предварительной проверки тестируемой переменной равенству какой либо из констант оператора 'case'. Синтаксис расширенного оператора 'case' наглядно иллюстрируется следующим примером:

.ми0

program trivial(input,output);
var
i:integer;
begin
for i:=1 to 5 do
case i of
1: writeln('One');
2: writeln('Two')
end
otherwise
writeln('Greater than two')
end.

.нф

'otherwise' стоит после слова 'end' оператора 'case'. После 'otherwise' стоит оператор, который выполняется в случае несоответствия значения переменной оператора 'case' ни одной из перечисленных констант. Результатом выполнения программы будут следующие сообщения:

One

Two

Greater than two

Greater than two

Greater than two

5.9 Шестнадцатиричные числа

Возможность использования шестнадцатиричных чисел в программе также является расширением по сравнению со стандартной версией языка Паскаль. Признаком того, что число шестнадцатиричное, служит символ '&'. Шестнадцатиричное число может состоять из символов '0'-'9','A'-'F' и 'a'-'f'. Например:

const
return = &0D
delete = &7F

Кроме того, в стандартных процедурах 'write' и 'writeln' можно с помощью символа '~' задавать вывод целых чисел в шестнадцатиричной форме, например:

write(~free, 'bytes free');

5.10 Символ подчерка

Если разрешено использование расширений, в именах идентификаторов наряду с цифрами и буквами можно использовать знак '_'. Заметьте, что в данной версии Паскаля нет ограничений на длину идентификаторов, и все символы являются значащими. Символ подчерка не может быть первым в идентификаторе.

5.11 Параметры упакованных переменных

Обычно, запрещается передавать элемент упакованного массива или записи процедуре или функции как переменный параметр. При использовании расширений это допускается делать при условии, если размер передаваемого элемента не изменяется при упаковке. Таким образом, передаваемый элемент может быть любого типа, кроме целого и диапазона целых. Рассмотри описание:

var pearl :
packed record
john : real;
pete : 0..26;
deb : integer
end;

Поле pearl.john может быть параметром процедуры или функции, а поля pearl.pete и pearl.deb нет.

.ст pascal.6

[an error occurred while processing this directive]