![]() | Вы видите на рисунке карту памяти1 типичной Форт-системы для одного пользователя. Мультипрограммные системы, такие, как полиФорт, устроены намного сложнее, о чем пойдет речь позднее. А пока рассмотрим простой случай и последовательно изучим каждый район нашей карты.
Предварительно скомпилированное ядро Форта. В памяти с младшими адресами расположен единственный предварительно скомпилированный участок системы (уже скомпилированный в словарную форму). В одних системах коды этого участка хранятся на диске (как правило, блоки 1-8) и автоматически загружаются в память с произвольной выборкой во время запуска или восстановления вашего компьютера, в других - такой участок неизменно находится в программируемой постоянной памяти и становится доступным сразу, как только вы включаете компьютер. В предварительно скомпилированном участке обычно хранится большая часть математических операций и слов форматизации чисел одинарной длины, операции преобразования стека одинарной длины, команды редактирования, структуры управления, ассемблер, все определяющие слова, которые вам уже известны, и, конечно, интерпретаторы текста и адреса2. |
1Для начинающих. Здесь показано, каким образом распределяется намять компьютера в конкретной системе в зависимости от ее назначения Память разбита на участки по 1024 байта. Это число называется «К» (от слова «кило», означающего тысячу).
2 Для специалистов. Чтобы получить представление о том, как компактен Форт, вам достаточно знать, что весь предварительно скомпилированный участок полифорта занимает меньше 8К байтов памяти
Системные переменные. Следующий раздел памяти содержит системные переменные, которые созданы предварительно скомпилированным ядром Форта и используются всей системой. Они, как правило, не применяются пользователем.
Выборочные определения. Тот раздел Форт-системы, который не был предварительно скомпилирован, хранится на диске в виде исходного текста. Какую часть определений из этого раздела загружать, а какую - нет, вы можете решить сами, что улучшит управление использованием памяти вашего компьютера.
Блок загрузки для всех выборочных определений называется блоком выбора.
Словарь пользователя. Словарь расширяется в сторону увеличения адресов памяти по мере того, как вы добавляете ваши собственные определения в область памяти, называемую словарем пользователя. Его следующая доступная ячейка в любой момент времени определяется содержимым переменной с именем Н (или DP). Во время компиляции указатель Н, по мере того как очередной элемент добавляется к словарю, переходит с ячейки на ячейку (или с байта на байт). Таким образом, для компилятора указатель Н выступает в качестве закладки; он указывает то место в словаре, куда компилятор может компилировать следующий объект. Этот указатель также используется словом ALLOT, которое передвигает его на заданное число байтов. Например, выражение 10 ALLOT добавляет к нему 10 и, следовательно, компилятор зарезервирует память в словаре для массива, состоящего из 10 байтов (или пяти ячеек).
Родственным словом является и HERE, которое определяется весьма просто: : HERE ( -- текущий-адрес ) H @ ;
Оно помещает значение Н в стек. Слово , (запятая) помещает значение одинарной длины в следующую доступную ячейку словаря: : , ( n -- ) HERE ! 2 ALLOT ;
т. е. запоминает некоторое значение в HERE и продвигает указатель словаря на два байта, закрепляя память под это значение. С помощью HERE вы можете определить, какой объем памяти требуется для любого фрагмента вашей программы, для чего нужно сравнить HERE до компиляции и после нее. Например, выражение HERE 220 LOAD HERE SWAP - . 196 ok
показывает, что определения, загруженные блоком 220, заняли 196 байтов памяти словаря.
Рабочая область (PAD). На некотором удалении от HERE вы обнаружите в своем словаре небольшую область памяти, называемую рабочей областью. Наша рабочая область обычно служит для хранения строк символов в коде ASCII, которые подвергаются обработке перед выводом на терминал. Так, слова, осуществляющие форматирование чисел, используют рабочую область для обработки чисел в коде ASCII во время их перевода, прежде чем вывести эти числа с помощью TYPE,
Размер рабочей области не определен.
В большинстве систем расстояние между началом рабочей области и вершиной стека данных измеряется сотнями и даже тысячами байтов.
Поскольку адрес начала рабочей области определяется относительно последнего элемента словаря, он изменяется всякий раз при добавлении нового определения либо выполнении FORGET или EMPTY.
Подобная организация тем не менее гарантирует безопасность, так как рабочая область никогда не используется при выполнении перечисленных выше действий. Слово PAD вносит в вершину стека текущий адрес начала рабочей области. Оно имеет довольно простое определение:: PAD ( -- a) HERE 34 + ;
т.е. помещает в стек адрес, который отстоит на фиксированное число байтов от HERE (в действительности это число может меняться).
Стек данных. Намного выше рабочей области расположен участок, зарезервированный под стек данных. У вас может создаться впечатление, что значения где-то передвигаются вверх и вниз, как будто их кто-то «вталкивает» и «выталкивает», однако на самом деле ничего подобного не происходит. Единственное, что изменяется, - это указатель вершины стека.
Как вы увидите в дальнейшем, при занесении некоторого числа в стек фактически лишь уменьшается указатель (т. е. указывает на следующий участок в направлении к младшим адресам памяти), а затем число запоминается в том месте, куда показывает указатель. Когда вы удаляете число из стека, оно выбирается из участка, на который показывает указатель, после чего последний увеличивается.
Все числа, расположенные на карте памяти выше указателя стека, не имеют смысла.



|
Н или DP |
( -- а) |
Занесение в стек адреса указателя словаря. |
|
HERE |
( -- а) |
Занесение в стек адреса очередного доступного участка словаря. |
|
PAD |
( -- а) |
Занесение в стек адреса начала рабочей области, в которой хранятся строки символов в процессе промежуточной обработки. |
|
SP@ или 'S |
( -- а) |
Занесение в стек адреса вершины стека данных до того, как исполнено само слово SP@. |
|
S0 |
( -- а) |
Содержит адрес дна стека данных. |
|
TIB |
( -- a) |
Занесение в стек адреса начала буфера входного текста. |