Forth http://fforum.winglion.ru/ |
|
Как разработать кросс-компилятор Форта для микроконтроллеров http://fforum.winglion.ru/viewtopic.php?f=39&t=2271 |
Страница 3 из 4 |
Автор: | chess [ Ср сен 09, 2009 09:21 ] |
Заголовок сообщения: | |
Хищник писал(а): 1 2 3 4 5 6 + - * AND OR
На 6 операндов вполне корректные 5 операций, т.е. выражение вообще корректно. Но каждое из 5 слов заберет с инструментального стека по 2 операнда! То есть уже AND не заберет ничего. еще раз - все числа(1 2 3 4 5 6 ) заберет с инструментального стека слово +, заберет и положит в целевой код, который при исполнении положит их на целевой стек. Остальные слова: - * AND OR ничего с инструментального стека не возьмут, потому, что на нем во время их работы уже ничего нет. |
Автор: | chess [ Ср сен 09, 2009 11:41 ] |
Заголовок сообщения: | |
Чтобы не возникало неверного впечатления приведу код бинарного файла для прошивки МК. Исходный текст программы: Код: : primer 1 2 3 4 5 + - and or ; main primer Код бинарного файла для прошивки: Код: 0000 8068 SJMP 006A \ переход к главному слову
0002 00 NOP 002F 00 NOP 0030 18 DEC R0 0031 A683 MOV @R0,DPH 0033 18 DEC R0 0034 A682 MOV @R0,DPL 0036 22 RET 0037 1130 ACALL 0030 0039 900000 MOV DPTR,#0000 003C 22 RET 003D E6 MOV A,@R0 \ - 003E 08 INC R0 \ 003F C3 CLR C \ 0040 9582 SUBB A,DPL \ 0042 F582 MOV DPL,A \ 0044 E6 MOV A,@R0 \ 0045 08 INC R0 \ 0046 9583 SUBB A,DPH \ 0048 F583 MOV DPH,A \ 004A 22 RET 004B E6 MOV A,@R0 \ + 004C 08 INC R0 \ 004D 2582 ADD A,DPL \ 004F F582 MOV DPL,A \ 0051 E6 MOV A,@R0 \ 0052 08 INC R0 \ 0053 3583 ADDC A,DPH \ 0055 F583 MOV DPH,A \ 0057 22 RET 0058 E6 MOV A,@R0 \ and 0059 08 INC R0 \ 005A 5282 ANL DPL,A \ 005C E6 MOV A,@R0 \ 005D 08 INC R0 \ 005E 5283 ANL DPH,A \ 0060 22 RET 0061 E6 MOV A,@R0 \ or 0062 08 INC R0 \ 0063 4282 ORL DPL,A \ 0065 E6 MOV A,@R0 \ 0066 08 INC R0 \ 0067 4283 ORL DPH,A \ 0069 22 RET 006A 1130 ACALL 0030 \ primer 006C 900001 MOV DPTR,#0001 \ 1 006F 1130 ACALL 0030 0071 900002 MOV DPTR,#0002 \ 2 0074 1130 ACALL 0030 0076 900003 MOV DPTR,#0003 \ 3 0079 1130 ACALL 0030 007B 900004 MOV DPTR,#0004 \ 4 007E 1130 ACALL 0030 0080 900005 MOV DPTR,#0005 \ 5 0083 114B ACALL 004B \ + 0085 113D ACALL 003D \ - 0087 1158 ACALL 0058 \ and 0089 1161 ACALL 0061 \ or 008B 00 NOP |
Автор: | Hishnik [ Ср сен 09, 2009 15:24 ] |
Заголовок сообщения: | |
chess писал(а): еще раз - все числа(1 2 3 4 5 6 ) заберет с инструментального стека слово +, заберет и положит в целевой код, который при исполнении положит их на целевой стек.
Остальные слова: - * AND OR ничего с инструментального стека не возьмут, потому, что на нем во время их работы уже ничего нет. Вот это уже более понятно. Да, в таком случае примеры формально корректны, однако все еще остается открытым вопрос - а что делать в случае, когда на инструментальном стеке уже что-то лежит, хотя бы даже до вызова кросс-компилятора. Представить это, кстати, не так уж и трудно - к примеру, перед кросс-компиляцией файла его handle кладется на стек для каких-то других целей, чтобы воспользоваться после кросс-компиляции. Однако первое же слово для целевой системы заберет все, что только было на стеке, а это чревато труднолокализуемыми ошибками. |
Автор: | chess [ Ср сен 09, 2009 20:26 ] |
Заголовок сообщения: | |
Хищник писал(а): Вот это уже более понятно. Да, в таком случае примеры формально корректны, однако все еще остается открытым вопрос - а что делать в случае, когда на инструментальном стеке уже что-то лежит, хотя бы даже до вызова кросс-компилятора. Представить это, кстати, не так уж и трудно - к примеру, перед кросс-компиляцией файла его handle кладется на стек для каких-то других целей, чтобы воспользоваться после кросс-компиляции. Однако первое же слово для целевой системы заберет все, что только было на стеке, а это чревато труднолокализуемыми ошибками.
Решение этих вопросов на самом деле не представляет собой каких-либо принципиальных затруднений, что было сделано еще четыре года назад, когда я еще только начинал осваивать форт. |
Автор: | Hishnik [ Ср сен 09, 2009 23:28 ] |
Заголовок сообщения: | |
chess писал(а): Решение этих вопросов на самом деле не представляет собой каких-либо принципиальных затруднений, что было сделано еще четыре года назад, когда я еще только начинал осваивать форт.
На самом деле эти вопросы просто не нужно ставить, о чем я и написал выше с разъяснением, как для этого можно организовать кросс-транслятор. |
Автор: | _Harry [ Чт сен 10, 2009 01:05 ] |
Заголовок сообщения: | |
Хищник писал(а): как для этого можно организовать кросс-транслятор.
На форке это решается примерно так Код: nums{ 1 2 3 ... тут все числа идут на стек контроллера ... }nums 5 6 ... тут как обычно на стек Код: nums{ - имя юнита который понимает числа Код: }nums - единственное слово в этом юните которое его и убирает из контекста
вобщем действительно проблем нет |
Автор: | chess [ Чт сен 10, 2009 08:17 ] |
Заголовок сообщения: | |
Хищник писал(а): На самом деле эти вопросы просто не нужно ставить, о чем я и написал выше с разъяснением, как для этого можно организовать кросс-транслятор.
Работа над компилятором - процесс эпизодический, а разработка ПО для аппаратуры процесс постоянный, поэтому из предметной области нужно по возможности исключать лишние сущности вроде преффиксов и операций типа #. Ну и кто кроме пользователя инструмента и разработчика этого инструмента это лучше сделает. |
Автор: | Hishnik [ Чт сен 10, 2009 10:37 ] |
Заголовок сообщения: | |
Обращу внимание на вектор DISPATCH-NUMBER, которое именно обработкой чисел для кросс-системы и занимается. При начале определения слова для кросс-системы в DISPATCH-NUMBER записывается адрес слова TC-LIT, , а при завершении определения опять возвращается NOOP. При таком подходе переход между инструментальной и целевой компиляцией получается незаметным, и ни префиксов, ни искусственных приемов вроде "переносим все числа, как только увидим слово" не требуется. |
Автор: | chess [ Чт сен 10, 2009 11:23 ] |
Заголовок сообщения: | |
Хищник писал(а): Обращу внимание на вектор DISPATCH-NUMBER, которое именно обработкой чисел для кросс-системы и занимается.
Понятно, что так формально более корректно. Но мой вариант не требует перегрузки вектора по концу определения. Этот момент я использовал для упрощения реализации макросов. Макрос пишется просто, например: Код: : name
здесь числа и фортМК-слова ; Как правило в теле макроса много ассемблерных команд(делается для ускорения исполнения кода). Затем просто делать инлайн-вставки через подстановку имен макросов. |
Автор: | Hishnik [ Чт сен 10, 2009 18:00 ] |
Заголовок сообщения: | |
chess писал(а): Понятно, что так формально более корректно. Но мой вариант не требует перегрузки вектора по концу определения. Этот момент я использовал для упрощения реализации макросов.
Вообще-то именно перегрузка вектора и является инструментом корректного распределения чисел между инструментальным и целевым стеками. Это никак не недостаток, а именно запланированный инструмент, о котором я и рассказал как о варианте. Макросы тут ни при чем, поскольку это обычные слова, которые можно использовать как для инструментальной, так и для целевой компиляции. Разумеется, можно несколько слов, занимающихся прямой подстановкой кодов команд, оформить в виде макроса, но числа, числа-то?! В том и смысл введенного в ядро DISPATCH-NUMBER, что оно позволяет совершенно управляемо распределять числа из входного потока между инструментальной и целевой системами. |
Автор: | chess [ Пт сен 11, 2009 07:36 ] |
Заголовок сообщения: | |
Хищник писал(а): Макросы тут ни при чем, поскольку это обычные слова, которые можно использовать как для инструментальной, так и для целевой компиляции.
Тут я не согласен, так как макросы для инструментальной системы могут быть макросами для целевой, а макросы для целевой системы могут и не быть макросами для инструментальной. В моем варианте макросы для целевой системы являются обычными словами инструментальной системы, определенными через двоеточие и никак не годятся на роль макросов для инструментальной системы. Насчет DISPATCH-NUMBER - аналогичное переключение осуществляют сами слова целевой системы, только каждое слово локально - принципиальной разницы нет, есть только отсутствие глобальной переменной-вектора . |
Автор: | Hishnik [ Пт сен 11, 2009 09:25 ] |
Заголовок сообщения: | |
chess писал(а): Тут я не согласен, так как макросы для инструментальной системы могут быть макросами для целевой, а макросы для целевой системы могут и не быть макросами для инструментальной. В моем варианте макросы для целевой системы являются обычными словами инструментальной системы, определенными через двоеточие и никак не годятся на роль макросов для инструментальной системы. Я не про назначение макросов, а про механизм их создания - это обычные слова Форта. chess писал(а): Насчет DISPATCH-NUMBER - аналогичное переключение
осуществляют сами слова целевой системы, только каждое слово локально - принципиальной разницы нет, есть только отсутствие глобальной переменной-вектора . Принципиальная разница как раз есть. Слово целевой системы забирает весь стек, а это некорректно. Надо как-то регулировать. Можно, кстати, запоминать DEPTH на момент переключения к целевой компиляции, это уже будет гораздо лучше. |
Автор: | oco [ Чт дек 01, 2011 18:32 ] |
Заголовок сообщения: | Re: Как разработать кросс-компилятор Форта для микроконтролл |
Уважаемый Хищник! Хотелось бы уяснить несколько вопросов, касающихся гарвардской архитектуры. Как реализовать определяющие слова, в частности CREATE и DOES> ? Возьмем например классические определения константы и переменной: Код: : CONSTANT CREATE , DOES> @ ; : VARIABLE CREATE 0 , DOES> ; Хочется, чтобы значение константы находилось в ПЗУ, а переменной в ОЗУ, соответственно слово "запятая" в каждом случае должно быть разным? И DOES> в константе ложит на стек адрес в ПЗУ, а в переменной - в ОЗУ, опять они должны быть разными? Потом, при прошивке ОЗУ ведь не прошивается, поэтому программа при старте должна данные для переменных из ПЗУ перекинуть в ОЗУ. То есть, начальные значения переменных таки сначала ложим в отдельную область ПЗУ, которую копируем в ОЗУ? Как это сделать, что-то я совсем запутался... |
Автор: | Hishnik [ Чт дек 01, 2011 22:56 ] |
Заголовок сообщения: | Re: Как разработать кросс-компилятор Форта для микроконтролл |
Если я правильно понимаю, в данном случае речь идет о системе с как минимум двумя областями памяти данных - в ПЗУ и ОЗУ. Что касается CREATE, оно всегда делает одно и то же - создает слово и добавляет ему код вида push <here> ret где <here> - первый свободный адрес на момент создания слова. Это означает, что такой адрес уже не изменится, поэтому само слово можно смело определять для ПЗУ. Вот дальше интереснее. Формально, даже gcc может перераспределять данные по разным областям. Для констант используется память read-only, что позволяет, в частности, использовать для их хранения ПЗУ, а компилятор будет следить, чтобы программист не пытался изменить значение константы далее по тексту программы. Можно поступить и так, завести для этого отдельный указатель. К примеру, если DP - переменная, хранящая указатель на свободное место в памяти данных (ОЗУ), то RODP - указатель на свободное место в Read-Only памяти. Соответственно, ROHERE положит этот адрес на стек, ROALLOT выделит память, а RO, скомпилирует число. Это подход в целом в стиле Форта. Альтернатива - не трогать существующие механизмы работы памяти. Для этого мы создаем в ПЗУ образ будущей памяти данных, а при старте форт-системы в микроконтроллере первым делом переносим весь этот массив в ОЗУ. |
Автор: | oco [ Пт дек 02, 2011 01:14 ] |
Заголовок сообщения: | Re: Как разработать кросс-компилятор Форта для микроконтролл |
Хищник писал(а): Если я правильно понимаю, в данном случае речь идет о системе с как минимум двумя областями памяти данных - в ПЗУ и ОЗУ Да, я это имел в виду Цитата: Что касается CREATE, оно всегда делает одно и то же - создает слово и добавляет ему код вида push <here> ret где <here> - первый свободный адрес на момент создания слова. Это означает, что такой адрес уже не изменится, поэтому само слово можно смело определять для ПЗУ. Вот дальше интереснее. Формально, даже gcc может перераспределять данные по разным областям. Для констант используется память read-only, что позволяет, в частности, использовать для их хранения ПЗУ, а компилятор будет следить, чтобы программист не пытался изменить значение константы далее по тексту программы. Можно поступить и так, завести для этого отдельный указатель. К примеру, если DP - переменная, хранящая указатель на свободное место в памяти данных (ОЗУ), то RODP - указатель на свободное место в Read-Only памяти. Соответственно, ROHERE положит этот адрес на стек, ROALLOT выделит память, а RO, скомпилирует число. Это подход в целом в стиле Форта. Альтернатива - не трогать существующие механизмы работы памяти. Для этого мы создаем в ПЗУ образ будущей памяти данных, а при старте форт-системы в микроконтроллере первым делом переносим весь этот массив в ОЗУ. Я так понимаю, что должно быть примерно так: : CONSTANT CREATE RO, DOES> RO@ ; : VARIABLE CREATE 0 , DOES> ; RO@ выбирает значение из ПЗУ Обычная запятая будет ложить значение в область данных ПЗУ, которая при запуске будет копироваться в ОЗУ. Но DOES> должен давать в этих случаях разные адреса. В первом случае - в ПЗУ, второй в ОЗУ. Заводить разные DOES> ? |
Страница 3 из 4 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |