[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]