P.S. Обнаружил, что название "NedoForth" уже занято - поэтому пусть будет PDFORTH (Public Domain FORTH) т.к. по сути оно будет надстройкой над PDBLv1
PDFORTH = Public Domain FORTH для PIC16F87X
Moderator: Shaos
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
PDFORTH = Public Domain FORTH для PIC16F87X
Задумал Публик-Домайный Форт для пиков, причём не просто кросс-компилятор (которых есть уже), а настоящую интерактивную Форт-систему, работающую через COM-порт непосредственно на пике, который способен сам себя программировать, например PIC16F870 (и далее на любом PIC16F87x). Делать думаю настоящий шитый код как последовательность CALL-ов, 16-битные вычисления, минимальный, но достаточный набор слов Форта ну и возможность заводить свои слова, с непосредственной компиляцией и программированием прямо в пик! 
P.S. Обнаружил, что название "NedoForth" уже занято - поэтому пусть будет PDFORTH (Public Domain FORTH) т.к. по сути оно будет надстройкой над PDBLv1
P.S. Обнаружил, что название "NedoForth" уже занято - поэтому пусть будет PDFORTH (Public Domain FORTH) т.к. по сути оно будет надстройкой над PDBLv1
Last edited by Shaos on 07 Dec 2014 07:04, edited 4 times in total.
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
~
Регистр FSR будет указателем на стек (т.е. псевдорегистр INDF будет всегда ссылаться на вершину стека с младшим байтом двух-байтового слова), причём стек будет идти сверху-вниз (от старших адресов к младшим).
Чтобы положить слово на вершину стека, надо сделать декремент FSR, затем скопировать старший байт в INDF, потом снова сделать декремент FSR и скопировать младший байт в INDF, например нижеследующий код положит на вершину стека число 0x0102:
Чтобы сбросить со стека число не читая (т.е. реализовать фортовское слово DROP), надо просто дважды инкрементировать FSR:
Пока размышляю где держать имена откомпилированных фортовских слов - в EEPROM (которого всего 64 байта на PIC16F870) или прямо в коде - по два 7-битных символа в слове программной памяти:
Соответственно при компиляции просто программно ищем слова начиная с какого-то места в памяти после каждой инструкции RETURN (код 0x0008). Название слова будет всегда начинаться с количества символов в названии - это на всякий случай для проверки, скажем слова в нашей реализации Форта не смогут иметь названия длиннее 15 символов (что упаковывается в 8 пиковских слов).
P.S. Для упрощения декодирования можно ограничиться в названии фортовских слов только символами, цифрами и большими латинскими буквами - тогда каждую букву названия слова можно упаковать в 6 бит - при этом пиковское слово сможет иметь в младшем байте один символ как есть, а в старших 6 битах (напомню что тут пиковское словое - 14 битное) символ минус 0x20 (код пробела) - тогда сюда влезет ASCII диапазон 0x20...0x5F (т.е. без маленьких букв и символов `{|}~ что нас вполне устроит).
P.P.S. Ещё раз объясню процесс компиляции прямо на пике - чел вводит через терминал описание своего слова, которое компилируется прямо в память пика, при этом встречаемые слова (обычные, не специальные) ищутся по памяти и в коде заменяются вызовом соответствующих подрограмм - вобщем как-то так. А вот со специальными словами (CHAR IF REPEAT и т.д.) сложнее - тут компилятор должен их компилировать не CALL-ами...
Чтобы положить слово на вершину стека, надо сделать декремент FSR, затем скопировать старший байт в INDF, потом снова сделать декремент FSR и скопировать младший байт в INDF, например нижеследующий код положит на вершину стека число 0x0102:
Code: Select all
decf FSR,f
movlw 1
movwf INDF
decf FSR,f
movlw 2
movwf INDF
Code: Select all
incf FSR,f
incf FSR,f
Code: Select all
...
RETURN ; from previous subprogram
; subprogram for "DROP"
DATA 0x0244 ; (4<<7)|'D'
DATA 0x294F ; ('R'<<7)|'O'
DATA 0x2800 ; ('P'<<7)|0;
DROP:
INCF FSR,f
INCF FSR,f
RETURN
; next word subprogram...
P.S. Для упрощения декодирования можно ограничиться в названии фортовских слов только символами, цифрами и большими латинскими буквами - тогда каждую букву названия слова можно упаковать в 6 бит - при этом пиковское слово сможет иметь в младшем байте один символ как есть, а в старших 6 битах (напомню что тут пиковское словое - 14 битное) символ минус 0x20 (код пробела) - тогда сюда влезет ASCII диапазон 0x20...0x5F (т.е. без маленьких букв и символов `{|}~ что нас вполне устроит).
P.P.S. Ещё раз объясню процесс компиляции прямо на пике - чел вводит через терминал описание своего слова, которое компилируется прямо в память пика, при этом встречаемые слова (обычные, не специальные) ищутся по памяти и в коде заменяются вызовом соответствующих подрограмм - вобщем как-то так. А вот со специальными словами (CHAR IF REPEAT и т.д.) сложнее - тут компилятор должен их компилировать не CALL-ами...
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Например подпрограмма, кладующая на вершину фортовского 16-битного стека один байт, будет выглядеть так:
Тогда CHAR A может быть скомпилировано вот в такой код:
Числа меньше 256 могут также быть положены на стек с помощью той же подпрограммы PUTB, остальные же 16-битные числа (-32768...+32767) будут компилироваться в такую вот конструкцию:
Можно конечно это тоже спрятать в подпрограмму, но тогда придётся задействовать один из регистров, для передачи второй половины слова, т.к. одного W будет уже недостаточно...
P.S. Для начала можно лишь 16-ричные числа поддержать (режим HEX), а уже потом сделать десятичные (режим DECIMAL), т.к. для интерпретации десятичных чисел потребуется написать для пика достаточно нетривиальный код...
P.P.S. Форт у нас интерактивный, т.е. он должен позволять ввести интерактивно что-то и сразу же получить результат - в этом случае компиляции в память программ происходить не должно - придётся делать интерпретацию на лету, хотя для начала можно и компилировать - тогда просто пик быстрее из строя выйдет по причине изношенности флеша, но это уже не суть.
Code: Select all
; put byte W to stack
PUTB:
DECF FSR,F
CLRF INDF
DECF FSR,F
MOVWF INDF
RETURN
Code: Select all
MOVLW 65 ; 'A'
CALL PUTB
Code: Select all
DECF FSR,F
MOVLW higher-byte
MOVWF INDF
DECF FSR,F
MOVLW lower-byte
MOVWF INDF
P.S. Для начала можно лишь 16-ричные числа поддержать (режим HEX), а уже потом сделать десятичные (режим DECIMAL), т.к. для интерпретации десятичных чисел потребуется написать для пика достаточно нетривиальный код...
P.P.S. Форт у нас интерактивный, т.е. он должен позволять ввести интерактивно что-то и сразу же получить результат - в этом случае компиляции в память программ происходить не должно - придётся делать интерпретацию на лету, хотя для начала можно и компилировать - тогда просто пик быстрее из строя выйдет по причине изношенности флеша, но это уже не суть.
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
В EEPROM будет храниться указатель на память программ, с которого можно начинать компиляцию вводимых слов.
Если человек вводит : затем имя (скажем XXX) и потом последовательность слов заканчивающихся ; то это компилирует и добавляет в словарь слово XXX.
При вызове команды FORGET XXX будут "забываться" все откомпилированные слова, начиная с XXX, путём простого сдвигания этого самого указателя на начало откомпилированного слова XXX (если слов с именем XXX несколько, то будет браться последняя компиляция слова XXX).
Также можно реализовать поддержку команды MARKER XXX, которая будет добавлять в словарь слово XXX, запустив которое затем можно "забыть" всё, что делалось до него (т.е. аналог FORGET XXX).
Если же человек сразу начинает писать последовательность слов, то после нажатия Enter эта последовательность компилируется и запускается (не сдвигая при этом указатель из EEPROM). Пример:
При этом перед приглашением "ok" Форт печатает состояние стека (обычно включается командой SHOWSTACK и отключается NOSHOWSTACK), которое сохраняется после выполнения команды, т.е.
Как видим прибавив к вершине стека 5 мы получили A (шестнадцатиричное представление числа 10).
P.S. А вообще традиционно состояние стека в Форте печатается командой .S
Если человек вводит : затем имя (скажем XXX) и потом последовательность слов заканчивающихся ; то это компилирует и добавляет в словарь слово XXX.
При вызове команды FORGET XXX будут "забываться" все откомпилированные слова, начиная с XXX, путём простого сдвигания этого самого указателя на начало откомпилированного слова XXX (если слов с именем XXX несколько, то будет браться последняя компиляция слова XXX).
Также можно реализовать поддержку команды MARKER XXX, которая будет добавлять в словарь слово XXX, запустив которое затем можно "забыть" всё, что делалось до него (т.е. аналог FORGET XXX).
Если же человек сразу начинает писать последовательность слов, то после нажатия Enter эта последовательность компилируется и запускается (не сдвигая при этом указатель из EEPROM). Пример:
Code: Select all
2 3 +
5 ok
Code: Select all
5 +
A ok
P.S. А вообще традиционно состояние стека в Форте печатается командой .S
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Команда VARIABLE XXX добавляет в словарь слово XXX которое кладёт на вершину стека адрес новой переменной (счётчик адресов переменных наверное также придётся хранить в EEPROM, причём при откатывании словаря через FORGET нужно также освобождать память отведённую ранее для освобождаемых переменных).
Команда NNN VALUE XXX добавляет в словарь слово XXX, которое кладёт на вершину стека число NNN (тоже самое будет если слово VALUE заменить на CONSTANT с той лишь разницей, что слово, созданное с помощью CONSTANT не даст себя больше менять, а с VALUE - даст через команду TO).
Команда NNN VALUE XXX добавляет в словарь слово XXX, которое кладёт на вершину стека число NNN (тоже самое будет если слово VALUE заменить на CONSTANT с той лишь разницей, что слово, созданное с помощью CONSTANT не даст себя больше менять, а с VALUE - даст через команду TO).
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Без подпрограммы, кладущей 16-битное число на стек, по видимому таки не обойтись:Shaos wrote:...остальные же 16-битные числа (-32768...+32767) будут компилироваться в такую вот конструкцию:Можно конечно это тоже спрятать в подпрограмму, но тогда придётся задействовать один из регистров, для передачи второй половины слова, т.к. одного W будет уже недостаточно...Code: Select all
DECF FSR,F MOVLW higher-byte MOVWF INDF DECF FSR,F MOVLW lower-byte MOVWF INDF
Code: Select all
; put HI and W on stack
PUSH:
MOVWF LO ; copy W to LO
DECF FSR,F
MOVF HI
MOVWF INDF
DECF FSR,F
MOVF LO,0 ; copy LO to W
MOVWF INDF
RETURN
Code: Select all
XXX:
MOVLW high-byte-adr
MOVWF HI
MOVLW low-byte-adr
CALL PUSH
RETURN
Code: Select all
XXX:
DECF FSR,F
MOVLW higher-byte
MOVWF INDF
DECF FSR,F
MOVLW lower-byte
MOVWF INDF
RETURN
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Потом можно сделать, что если компилятор встречает слово, начинающееся с $, то он будет просто вставлять на этом месте инструкцию, шестнадцатиричный код которой будет идти непосредственно следом за $ в виде 4 шестнадцатиричных цифр, например $0170 при компиляции будет воспринят как пиковская команда BCF 070h,0 (очистить бит 0 регистра 0x70) - понятное дело таким хаком надо пользоватся с большой осторожностью (самое прикольное, что это в интерактивном режиме будет тоже работать ; )
P.S. 11 декабря решил, что $ будет логичнее нежели #
P.S. 11 декабря решил, что $ будет логичнее нежели #
Last edited by Shaos on 11 Dec 2014 00:41, edited 1 time in total.
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
DO ... LOOP как известно могут быть вложены - в этом случае внутренний цикл может взять значение счётчика через слово I, а J - это счётчик внешнего цикла. Надо как-то придумать имплементацию - DO должен где-то запоминать адрес возврата (причём не на стеке данных).
IF ... THEN и IF ... ELSE ... THEN при компиляции должны знать куда передавать управление в том или ином случае в момент IF - а при первом проходе это невозможно, т.к. такие конструкции придётся компилировать как минимум в 2 прохода - при первом IF ставится передача управления скажем на нулевой адрес, а уже при полной компиляции строки, когда все адреса известны, нам надо пройти сначала ещё раз, заменяя все нулевые переходы на нужные...
IF ... THEN и IF ... ELSE ... THEN при компиляции должны знать куда передавать управление в том или ином случае в момент IF - а при первом проходе это невозможно, т.к. такие конструкции придётся компилировать как минимум в 2 прохода - при первом IF ставится передача управления скажем на нулевой адрес, а уже при полной компиляции строки, когда все адреса известны, нам надо пройти сначала ещё раз, заменяя все нулевые переходы на нужные...
-
Lavr
- Supreme God
- Posts: 16803
- Joined: 21 Oct 2009 08:08
- Location: Россия
Да я его просто ненавижу. Сколько не брался - он мне напоминает об убогих стеково-ориентированных программируемых калькуляторах.Shaos wrote:Ну что - нету у нас тут любителей Форта?
Хотя я и попал на этот форум из-за Шурика и его Форта...
Конечно же из-за Шурика и его эпопеи со "Специалистом", но в тот день я искал простые реализации языка Форт.
Бывают у меня такие потуги... найду... почитаю... но резюме пока одинаковое: этот Форт - кал галимый!
(сугубо моё личное мнение)
iLavr
-
esl
- Writer
- Posts: 24
- Joined: 23 May 2006 13:40
ниче вы не понимаете в теплом ламповом фортеLavr wrote:Бывают у меня такие потуги... найду... почитаю... но резюме пока одинаковое: этот Форт - кал галимый!![]()
(сугубо моё личное мнение)
а почти по теме, вспомнил тут форт и это круто!
для Корвета ваяем модуль работы с SD
(а точнее чтоб на любом корвете, даже без дисковода можно подключить к разъему расширения и работать с образами дисков как с настоящими дисками)
собственно оно уже работает
так надо писать утиль MOUNT, писать ее на асме - та ну нафиг
и так на асме уже куча кода.
соавтор проекта - железячный маг с ником forth32
это скажу вам тот еще гиморой, ибо на 8080 есть только нативные асмы.
а я пробую тут написать на форте,
так скажу я вам - мне это доставляет прям удовольствие
а писать на K&R C - еще тот мазахизм.
-
esl
- Writer
- Posts: 24
- Joined: 23 May 2006 13:40
-
Shaos
- Admin
- Posts: 24414
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Вот чего нашёл:Shaos wrote:Ну что - нету у нас тут любителей Форта? Никто мне не скажет, что я просто должен взять книжку и по ней тупо повторить каноническое описание DO и IF с исользованием R>, GOES> и т.д.?
http://stackoverflow.com/questions/6949 ... itten-in-c
Советуют завести специальный стек для циклов - вполне разумно выглядит...
P.S. да я не спорю, что форт странен, но простота реализации компилятора таки завораживает
-
Lavr
- Supreme God
- Posts: 16803
- Joined: 21 Oct 2009 08:08
- Location: Россия
