Язык Форт и его реализации

         

Работа с внешней памятью


В настоящее время в каждом языке программирования тем или иным способом решаются вопросы обмена с внешней памятью. Из-за огромного разнообразия внешних устройств и способов хранения информации на внешних носителях единый универсальный механизм обмена отсутствует. В каждом языке определяется своя, в известной мере универсальная файловая система, которая при реализации моделируется на реальной файловой системе конкретной операционной системы.

Поскольку в язык Форт легко включать новые слова-команды, то надобность в стандартных универсальных развитых средствах обмена отпадает. В каждой реализации можно ввести такие средства исходя из особенностей и возможностей применяемых для данной ЭВМ файловой системы и конкретных внешних устройств. Вместе с тем желательно иметь механизм, обеспечивающий по крайней мере перенос и хранение на машинном носителе программных текстов на языке Форт. Исходя из этого стандарт предусматривает элементарнейшую файловую систему, которая легко реализуется в любой конкретной файловой системе или непосредственно через драйверы внешних устройств (магнитных дисков).

В языке Форт применяется механизм виртуальной внешней памяти, состоящей из блоков по 1 Кбайт каждый. Блок идентифицируется номером — числом в диапазоне от 1 до 32767. В адресном пространстве форт-системы выделяется память под буферный пул, рассчитанный на одновременное хранение одного или более блоков. Каждый буфер помимо памяти для хранения собственно блока данных содержит номер блока и признак его измененности.

Слово BUFFER (буфер), получив номер блока, ищет свободный буфер в пуле и возвращает его адрес, записывая в служебную ячейку буфера переданный номер блока. Тем самым найденный буфер приписывается данному блоку, однако содержимое буферной памяти пока остается прежним. Если свободного буфера не оказалось, то аналогичным образом используется один из занятых. Если при этом в служебной ячейке буфера был установлен признак измененности, то данные из буферной памяти переписываются во внешнюю, они заменяют там прежнее содержимое соответствующего блока.


Слово BLOCK (блок) аналогично по использованию слову BUFFER за исключением того, что перепись данных из внешней памяти производится в приписанный данному блоку буфер. Разумеется, если данный блок уже находится в буферном пуле, то переписи данных не происходит, и слово BLOCK возвращает адрес этого буфера.

Наконец, слово UPDATE (изменить) устанавливает признак измененности последнего блока, к которому было адресовано обращение через слово BLOCK или BUFFER. Таким образом, впоследствии этот блок будет автоматически переписан во внешнюю память.

При реализации обмена с внешней памятью в качестве буферного пула обычно используется связный участок оперативный памяти. Пусть его начало задается константой FIRST, а конец — адрес байта, следующего за последним, — константой LIMIT. (Если пул располагается вплотную к концу адресного пространства, то этот следующий адрес равен нулю!) Буфера в пуле располагаются подряд, каждый начинается двухбайтной ячейкой, в которой записывается номер приписанного блока, причем старший разряд используется под признак измененности. Далее идет буферная память для блока размером 1024 байта, завершается буфер еще одной служебной ячейкой, в которой записан ноль (ее назначение указано в ). Пусть переменные PREV и USE указывают на текущий используемый буфер и следующий, который будет выдан при запросе на свободный буфер. Определим слово +BUF, которое вычисляет адрес буфера, следующего в пуле за переданным, и возвращает признак несовпадения его с текущим:

: +BUF ( A1 ---> A2,F ) 1024 + 4 + DUP LIMIT - IF DROP FIRST THEN DUP PREV @ - ;

Пусть служебные слова RBLK A,N --> и WBLK A,N --> выполняют чтение блока с указанным номером в заданную область оперативной памяти и запись из нее. Тогда с учетом принятых условий слова, выполняющие работу с внешней памятью, можно задать так:

: BUFFER ( N ---> A ПРИПИСАТЬ БЛОКУ N БУФЕР) USE @ DUP >R ( ВЕРНЕМ ЭТОТ БУФЕР) BEGIN +BUF UNTIL USE ! ( УСТАНАВЛ.СЛЕДУЮЩИЙ) R@ @ 0< ( ПРИЗНАК ИЗМЕНЕННОСТИ?) IF R@ 2+ R@ @ 32767 AND WBLK THEN R@ ! ( ПРИПИСАЛИ НОВОМУ БЛОКУ) R@ PREV ! R> 2+ ; : BLOCK ( N ---> A:АДРЕС БУФЕРА С ДАННЫМИ БЛОКА) >R PREV @ DUP R@ - DUP + ( ТЕКУЩИЙ - ТОТ ЖЕ?) IF ( НЕТ) BEGIN +BUF 0= IF DROP R@ BUFFER DUP R@ RBLK 2- THEN DUP @ R@ - DUP + 0= UNTIL DUP PREV ! THEN R> DROP 2+ ; : UPDATE ( ---> ) PREV @ @ 32768 OR PREV @ ! ;



Для записи всех измененных буферов во внешнюю память служит слово SAVE-BUFFERS (сохранить буфера):

: SAVE-BUFFERS ( ---> ) LIMIT FIRST DO I @ 32768 AND IF I @ 32767 AND DUP I ! I 2+ SWAP WBLK THEN 1028 +LOOP ;

При исполнении слова SAVE-BUFFERS все буфера остаются приписанными прежним блокам. Слово FLUSH (очистить) переписывает все исправленные блоки во внешнюю память и освобождает буфера. Многие реализации имеют слово EMPTY-BUFFERS (опустошить буфера), которое освобождает буферный пул, не переписывая исправленные блоки:

: EMPTY-BUFFERS ( ---> ) LIMIT FIRST DO 0 I @ ! 1028 +LOOP ; : FLUSH ( ---> ) SAVE-BUFFERS EMPTY-BUFFERS ;

Внешняя память форт-системы в основном используется для хранения форт-текстов. Блок внешней памяти с форт-текстом называется экраном и условно разбивается на 16 строк по 64 литеры в каждой. Такой формат экрана сложился традиционно и закреплен в стандарте.

Программист создает и исправляет экраны во внешней памяти, используя встроенный редактор форт-системы. Как и в случае встроенного ассемблера, стандарт не определяет конкретный вид и состав его команд, поскольку это в значительной степени определяется функциональными возможностями и характеристиками конкретных терминалов и средствами работы с ними. Обычно слова-команды текстового редактора составляют отдельный список слов с именем EDITOR (редактор), базирующийся на списке FORTH. Для распечатки редактируемого экрана на терминале чаще всего используют слово LIST (распечатать), которое, кроме того, сохраняет номер экрана в служебной переменной SCR:

: LIST ( N ---> ) DUP SCR ! CR ." ЭКРАН " DUP . BLOCK 16 0 DO DUP I 64 * + CR I 3 .R SPACE 64 TYPE LOOP DROP ;

Вначале печатается номер данного экрана, затем его строки. Перед каждой строкой печатается ее номер — число в диапазоне от 0 до 15. По завершении редактирования исправленные экраны можно записать во внешнюю память словом FLUSH.


Содержание раздела