Комментарии 45
А есть синтаксис где вместо MOV используется LD? =)
(В своё время так привык на Z80, что на целую букву больше писать было странно...)
или просто делаешь #DEFINE LD MOV?
Кстати, хороший вопрос что будет быстрее работать — один из вариантов шитого кода или ваш байткод.
Есть такой учебный проект Форта (Forthress) преподователя Igor Zhirkov из ITMO
"Low-Level Programming: C, Assembly, and Program Execution on Intel x86-64 Architecture".
сделанного на NASM.
P.S. И тоже вопрос, почему не FASM для реализации?
На FASM сделано ядро операционной системы KolibriOS (и Форт к ней тоже уже к ней портировали c базиса российской Форт-системы SPF4)
В теги к статье можно добавить "Forth" (Форт) "Ненормальное программирование" :)
Форт это прекрасно. Ждём новых статей.
[url=https://archive.org/search.php?query=subject%3A%22FORTH+%28Computer+program+language%29%22]Некоторый kнижный архив по Форт на webarxive[/url]
rigidus.ru
Ассемблер, это прекрасно! Ждем новых статей.
Хотя, выбор AS несколько смущает. Хоть в intel синтакс и на том спасибо. Но для полностью ассемблерных проектов все-таки FASM или NASM лучше будут. AS, скорее всего бакенд компиляторов. Для людей не очень удобный.
Упрощает и стековые, и арифметические операции, и добавляет скорости.
NEGATE neg RAX
SWAP xchg EAX, [ESP]
DROP mov [ESP], EAX; add ESP,4
и т.д.
Вообще, я пытался придумать, как держать несколько значений с вершины в регистрах… но несколько точно не стоит, слишком много движений при стековых операциях получается. Одно — может быть…
Может несколько уменьшиться количество обращений к памяти, а вот команд процессора — наверняка возрастет. Надо тестировать.
github.com/y-salnikov/kforth
Словарь формируется скриптом на python.
Ну это какое святотатство. Форт должен быть написан только на Форт.
Что бы можно было положить любое число, нужно 64 бита. Но, каждый раз команда будет занимать 5 байт, что бы положить одно число?
это будет байт-команда, за которой лежит параметр — адрес перехода 64 бита. Опять пять байтДевять же, а не пять?
mov ecx, offset msg_bye # указатель на выводимую строкуПовезло, что старшие 32 бита нули, но лучше ECX заменить на RCX (это копипаста 32-битного кода?)
Доступ к реальному железу, тоже не ограничивается.
Т.ч. смысл не понятен.
В составе моего мультиадатера www.forth.org.ru/news/stm32f105MultiAdapter#0
есть полноценная виртуальная Форт машина, используемая для целевой компиляции.
Требуется еще виртуальное адресное пространство.
К примеру, адрес msg_hello устанавливается линковщиком и может быть каким угодно.
Доступ к реальному адресному пространству и есть доступ к железу.
Насыщения на ассемблере. Борьба с тормозами виртуализации не может
быть целью этой виртуализации. Проблема совместимости на уровне
исходников Форта связана не с тем, что это трудно обеспечить.
А с тем, что нет стимула об этом заботится.
Шучу, сами понимаете. Респект, отличная работа (дочитал всё статьи до конца)! Особенно учитывая что делалось с абсолютного нуля, с hello world. Плюсую. Сейчас сам потихоньку дозреваю до написания своей форт-системы со строгой статической типизацией. А значит с контролем ошибок, отличной поддержкой IDE, мультидиспатчингом слов (как в julia) и прочими вкусностями. При сложности чуть-чуть бОльшей, чем обыкновенный форт.
Эх… Плюсануть не удалось… Период голосования истёк. Ладно, плюсую мысленно! :)))
дозреваю до написания своей форт-системы со строгой статической типизациейЕсть идеи, как в compile-time запретить вызов слова, если на стеке нет значения соответствующего типа?
Пишется стековая аннотация (тут она ОБЯЗАТЕЛЬНА, а не в качестве правила хорошего тона), и компилятор знает, что при вызове лежит на стеке. А дальше компилируя просто отслеживает стек времени исполнения. Точно так же будет работать поддержка автокомплита в IDE. Но там ещё будет учитываться порядок поиска в словарях. Самый серьёзный недостаток — система будет несовместима ни с чем существующим. Совершенно другая структура словаря. Так что в виде библиотеки это сделать не получится. На всякий случай предупреждаю, это пока очень и очень сырые мысли. Я ещё не написал ни строчки кода.
Сорри, немного нечётко. Короче, ВСЕ слова в системе снабжены стековыми аннотациями. Что на входе, и что на выходе. Тут это не комментарий, а неотъемлемый элемент языка. Например вот так:
: 2swap ( 2cell 2cell — 2cell 2cell ) overwrite swap
…
;
Тут во-первых вводится стековая аннотация. Откуда видно, что при вызове в стеке две двойных ячейки и на выходе тоже две двойных ячейки. Во-вторых говорится, что это слово замещает слово swap, если при вызове система определяет, что на стеке две двойных ячейки. Как 2swap оно тоже ищется. И поскольку ВСЕ слова снабжены такими аннотациями, во время компиляции состояние стека известно на каждом шаге.
Точно так же работает автокомплит. Начинаем набирать определение слова через двоеточие. Как только набрали стековую аннотацию, языковому серверу сразу ясно, что лежит на стеке в начале определения. И он ищет в подключенных словарях слова, с такой же сигнатурой параметров, предлагая их в списке автокомплита. На каждом шаге набора состояние стека отслеживается. И всегда для ввода предлагается что-то адекватное. Вот примерно так.
Например, если в программе есть цикл от 1 до N, внутри цикла кладём на стек int, то для
этого куска кода нужно написать вручную инварианты на входе и выходе, либо система сама сможет их вывести? Если второе, то очень похоже на решение проблемы останова и вообще анализа алгоритмов в общем виде.
А они не меняются, иначе типизация не будет статическойМеняются, если в ветке THEN кладём на стек один тип, а в ветке ELSE — другой тип.
Замаскированный вариант той же неопределённости — кладём на стек одно значение, а затем N значений другого типа, где N — не вычислимо не этапе компиляции.
Ой, сорьки. Я не на тот вопрос ответил. Пройти по всем вариантам исполнения кода можно. И довольно легко, слова обычно не длинные. Так что какие типы возвращаются — мы знаем. Если на стек кладётся значение одного типа, а затем N другого, слово всегда берёт со стека столько, сколько ему надо. И это записывается в стековой нотации. Компилятор это тоже проверяет. И ругается, если скажем при верхнем элементе стека равным 0 снимается 5 элементов, а при 1 снимается 10. Да, возможно это некое ограничение свободы. Но моё глубокое IMHO что за слова, берущие (возвращающие) разное число значений в зависимости от входа, программистам надо отрывать руки, причём по самые гланды. Вот как-то так… :)))
P.S. Я понимаю, что всё это накладные расходы. Но как бы это в режиме работы форт-системы. При целевой компиляции всё это уйдёт вместе со словарями и заголовками слов.
Так у нас программа может упасть в рантайме, если на нужной глубине стека не окажется значения указанного типа, но хотя бы это избавит от неопределённости типа на стеке после успешного выполнения слова.
С ROLL непонятно, что делать.
?DUP запретить, потому что оно меняет глубину стека в зависимости от входа.
Вчера вечером всё-таки начал. В качестве морской свинки взял этого таварисча www.softsynth.com/pforth/index.php. Тут в принципе без разницы с чего начинать, конечный продукт всё равно будет написан на самом себе, как SPF гражданина Черезова. Но для опытов лучше взять что-то готовое, написанное на С. Перенёс его в eclipse, нормально собрал и полночи фиксировал на бумаге (точнее в файле) тезисы. Вобщем огромное спасибо за обсуждение, наконец-то это сподвигло меня к действиям :))))
Когда будет что показывать, хоть минимально, обязательно на любимом хабре отпишусь :))
Байт-машина для форта (и не только) по-индейски