|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
|
Page 1 of 1
|
[ 13 posts ] |
|
Компилятор Pascal для i8048 (msc-48)
Author |
Message |
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Рано или поздно всплывает на форумах вопрос, почему нет компилятора языка высокого уровня для MSC-48? Отвечают практически всегда одно и то-же - мол, мало памяти, стек не прозрачный и тд. Но мне кажется, что некий "упрощенный" вариант Паскаля/Си реализовать можно. Сначала я смотрел в сторону SDCC - Small Device C Compiler. Но немного повтыкав в сорцы кодогенератора для 8051 удалил их, поняв что я ничего не понимаю. Может для кого-то он конечно и "easy portable to another architecture", но явно не для меня. А потом вспомнил, что я, давным давно, читал замечательную статью Let's Build a Compiler, by Jack Crenshaw, она же, внезапно на русском в PDF. А потом вдобавок ко всему нашел еще и сорцы некого Power Pascal for OS/2. Эта вещь написана явно под влиянием вышеупомянутой статьи. Генерирует ASM-листинг для x86. Собирается хоть Turbo Pascal, хоть FreePascal с небольшими правками, и что удивительно, в принципе работает. Тем более Паскаль как бы мне более "родной", чем Си (хотя в последнее время пишу почти всегда на Си, но не суть). Итак, Паскаль. Конечно, памяти маловато. На классическом 8048 имеем два банка 8-битных регистров R0 - R7 (16 байт), восьмиуровневый 16-битный стек (16 байт), остальные 32 байта на пользовательские переменные. В контроллере есть внешнее прерывание и таймер. И вектора обработчиков от них по адресам .org 3 и .org 7. Поэтому решено сделать пока так - в основной программе работаем только с первым банком регистров R0 - R7, не трогая второй банк. Второй банк регистров использовать только в обработчиках прерываний. Таким образом не нужно морочиться с сохранением/восстановлением текущих регистров в обработчиках прерываний. Дальше, A - акуумулятор, в него помещается текущее значение с которым работаем. R0 - операнд. R1 - для временного хранения аккумулятора, если с ним производятся логические действия. С R2 по R7 находятся значения в "стеке". Если "стека" из регистров не хватит, писать в пользовательскую память, если там есть место. Переменные хранятся в памяти начиная с адреса .org 32. Всего 32 байта. Ну и первый простой тест на операции сложения/вычитания: Дает такой вот листинг: | | | | Code: ;; MSC-48 PASCAL ;; Tronix (c) 2017
.org 0 ; reset vector dis i jmp MAIN
.org 3 ; external interrupt vector--trap retr
.org 7 ; timer interrupt vector retr MAIN: mov a,6 ; load const mov r0,_X ; store variable mov @r0,a mov a,2 ; load const mov r0,_Y ; store variable mov @r0,a mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov r0,_Y ; load variable mov a,@r0 mov r1,a ; save V0->V1, get V0 from stack mov a,r2 add a,r1 ; make addiction mov r0,_X ; store variable mov @r0,a mov r0,_Y ; load variable mov a,@r0 mov r2,a ; push to stack mov a,3 ; load const mov r1,a ; save V0->V1, get V0 from stack mov a,r2 xch a,r1 ; make substraction cpl a inc a add a,r1 mov r0,_Y ; store variable mov @r0,a _PEND: jmp _PEND ; end program ; ***** Library Code ***** ; ***** Library Ends ***** ; Variable Area .equ _Y 32 .equ _X 33 ; String constants
| | | | |
Немного подзастрял пока на логических операциях. Но думаю, победим мы его.
|
13 May 2017 23:35 |
|
|
jdigreze
God
Joined: 02 Jan 2006 02:28 Posts: 1390 Location: Abakan
|
Здорово! Книжку на досуге почитаю.
|
14 May 2017 00:53 |
|
|
angry_troll
Doomed
Joined: 08 Apr 2013 04:04 Posts: 449 Location: 213.247.249.139
|
готов потестить на своей платке. Кроссплатформенная версия будет или wanacryptor-only? да, так обычно и делают, причем во 2 наборе 1 рег убивается сразу и навсегда для схоронения в него А во время входа. Еще есть такая жопа, что из прерывания моюно только проецедуры первых 2к вызывать, вторые 2к недоступны вообще (от момента входа до выполнения retr)
_________________ привет засранцу лавру :)
|
14 May 2017 01:03 |
|
|
angry_troll
Doomed
Joined: 08 Apr 2013 04:04 Posts: 449 Location: 213.247.249.139
|
вычитание в интеловом аппноте рекомендуют делать так:
_________________ привет засранцу лавру :)
|
14 May 2017 01:10 |
|
|
angry_troll
Doomed
Joined: 08 Apr 2013 04:04 Posts: 449 Location: 213.247.249.139
|
А еще кстати, прерывания от таймера и внешние независимо запрещаются. Чтобы запретить все, надо 2 команды:
_________________ привет засранцу лавру :)
|
14 May 2017 01:17 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Что за апноут? Я читаю какой-то, там так: Но ваше решение попроще, попробую. UPD: Попробовал, работает. Спасибо. Насчет таймера - где-то вроде видел что по умолчанию он выключен. Но можно конечно dis tcnti воткнуть.
|
14 May 2017 01:57 |
|
|
angry_troll
Doomed
Joined: 08 Apr 2013 04:04 Posts: 449 Location: 213.247.249.139
|
Мды, с аппноутом я погорячился. Сейчас посмотрел, вот тут https://github.com/AngryTroll/i8048_board/blob/master/pdf/mcs48/1980_MCS-48_Users_Manual.pdf на странице 133, например, упоминается. Ну и вообще моя подборка док: https://github.com/AngryTroll/i8048_board/tree/master/pdf/mcs48Ну и внешнее прерывание после ресета тоже выключено. Я рассуждаю так -- если вдруг придётся программно рестартовать контрольник переходом на 0, то тогда смысл запрещать ВСЕ прерывания есть.
_________________ привет засранцу лавру :)
|
14 May 2017 02:40 |
|
|
Lavr
Supreme God
Joined: 21 Oct 2009 08:08 Posts: 7777 Location: Россия
|
Что-то мне на взгляд кажется, что дополнение до двух (TWO'S COMPLEMENT) теряется... Нет ошибки на единицу?
_________________ iLavr
|
14 May 2017 02:48 |
|
|
Tronix
Doomed
Joined: 18 Nov 2013 02:38 Posts: 662 Location: Москва
|
Да не, нормально. Чуть разобрался с условиями < > =. Правда пока не сделал <= и >=. Прикрутил основные циклы (for/while/repeat). Набросал небольшой тест. Внутренняя процедура Debug(N) просто выставляет число N в порт 1 и уходит на бесконечный цикл. Кодогенерация: | | | | Code: ;; MSC-48 PASCAL ;; Tronix (c) 2017
.org 0 ; reset vector dis i jmp MAIN
.org 3 ; external interrupt vector--trap retr
.org 7 ; timer interrupt vector retr MAIN: dis tcnti mov a,2 ; load const mov r0,_X ; store variable mov @r0,a mov a,253 ; load const mov r0,_Y ; store variable mov @r0,a mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov r0,_Y ; load variable mov a,@r0 mov r1,a ; save R0->R1, get R0 from stack mov a,r2 add a,r1 ; make addiction mov r2,a ; push to stack mov a,255 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jnz L0 ; if NOT jump to mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov r0,_Y ; load variable mov a,@r0 mov r1,a ; save R0->R1, get R0 from stack mov a,r2 add a,r1 ; make addiction mov r2,a ; push to stack mov a,255 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L2 ; if jump to mov a,1 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L2: L3: mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov r0,_Y ; load variable mov a,@r0 mov r1,a ; save R0->R1, get R0 from stack mov a,r2 add a,r1 ; make addiction mov r2,a ; push to stack mov a,255 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L4 ; logical less jnc L4 mov a,2 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L4: L5: mov r0,_Y ; load variable mov a,@r0 mov r2,a ; push to stack mov a,1 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a mov r0,_Y ; store variable mov @r0,a mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov r0,_Y ; load variable mov a,@r0 mov r1,a ; save R0->R1, get R0 from stack mov a,r2 add a,r1 ; make addiction mov r2,a ; push to stack mov a,254 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L6 ; logical greater jc L6 mov a,3 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L6: L7: jmp L1 L0: mov a,4 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L1: mov a,0 ; load const mov r0,_X ; store variable mov @r0,a mov a,1 ; load const mov r0,_I ; store variable mov @r0,a mov a,200 ; load const mov r0,Lim_I ; store variable mov @r0,a L8: mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,1 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 add a,r1 ; make addiction mov r0,_X ; store variable mov @r0,a mov r0,_I ; load variable mov a,@r0 mov r2,a ; push to stack mov r0,Lim_I ; load variable mov a,@r0 mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L9 ; logical less jnc L9 mov r0,_I ; increase var by 1 mov a,@r0 inc a mov @r0,a jmp L8 L9: mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,200 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L10 ; if jump to mov a,10 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L10: L11: L12: mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,1 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L13 ; if jump to mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,1 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a mov r0,_X ; store variable mov @r0,a jmp L12 L13: mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,1 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L14 ; if jump to mov a,11 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L14: L15: mov a,0 ; load const mov r0,_X ; store variable mov @r0,a L16: mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,1 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 add a,r1 ; make addiction mov r0,_X ; store variable mov @r0,a mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,123 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jnz L16 ; if NOT jump to mov r0,_X ; load variable mov a,@r0 mov r2,a ; push to stack mov a,123 ; load const mov r1,a ; save R0->R1, get R0 from stack mov a,r2 cpl a ; make substraction A-R1 add a,r1 cpl a jz L17 ; if jump to mov a,12 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND L17: L18: mov a,90 ; load const outl p1,a ; !!! DEBUG. Set P1 and forever loop !!! jmp _PEND _PEND: jmp _PEND ; end program ; ***** Library Code ***** ; ***** Library Ends ***** ; Variable Area .equ _Y 32 .equ _X 33 .equ _I 34 .equ Lim_I 35 ; String constants
| | | | |
Без оптимизации 309 байт. Однако. Вот думаю, какой-бы реальный простенький пример можно реализовать.. Не знаю, число ПИ там вычислить или еще чего. Есть идеи? С ПИ немного сложно, потому что пока нет 16-битных чисел. 8 бит онли.
|
14 May 2017 07:33 |
|
|
Annett
Senior
Joined: 30 Mar 2017 00:55 Posts: 137
|
Уххх! Tronix, спасибо за ссылку на книжку! Там как раз под 68К !!
|
15 May 2017 15:12 |
|
|
Mixa64
Doomed
Joined: 25 Aug 2009 07:02 Posts: 461 Location: Москва
|
У меня к сочетанию Паскаль и М68К какое-то недоверие и настороженность. Зимой развлекался дизассемблированием ПЗУшки процессора с телефонной станции AXE-10, там уж очень симпатичная керамическая с золотом PGAшная микросхема системного контроллера, дизассемблировал на тему ее реверс-инжиниринга с прицелом применить в своих целях, уж больно красива, в сочетании с PGAшным же TMP68HC000. По результатам работы - к большому сожалению, микросхема сильно заточена на специфику архитектуры AXE, в системе общего назначения неприменима. Но более всего я намучился разбирать логику кода, который, по признакам передачи параметров и еще каким-то, как я понял, был сгенерен с Паскаля. Получился ассемблерный ужос, все как-то неоптимально, медленно, куча лишних назначений, пересылок и т.п. Сочетание M68K и C выглядело гораздо лучше, тоже был опыт.
|
15 May 2017 15:57 |
|
|
Annett
Senior
Joined: 30 Mar 2017 00:55 Posts: 137
|
Ничего страшного. Всё хорошо. Ассемблер 68-го, к которому у меня очень особенное и близкое отношение, никуда же не делся Во-многом из-за его удобства я и выбрала этот процессор для нашей "левой" системы Но вариант с языком - тоже интересен, пусть даже там куча лишнего кода, да еще наверное пересылки в стеке и всё такое... Есть же всякие применения, где это уместно. Например, какой-нибудь редактор паттернов в секвенсоре или что-то подобное интерактивное - удобней закодить на языке. А вот отрисовка графики и генерация MIDI в достаточно жестком реальном времени - пусть себе крутится на асме по прерываниям, а частично даже хардварно в плисах. И всё будет замечательно:) Mixa, да наверное эти специализированные чипы лучше просто оставить "в музее" и не мучиться с ними...Пусть лежат в ящичке, как фетиш А вот сам PGAшный 68К -это уже прикольно (извиняюсь за оффтоп):)
|
15 May 2017 17:03 |
|
|
Lavr
Supreme God
Joined: 21 Oct 2009 08:08 Posts: 7777 Location: Россия
|
А я вот тут призадумался - не реализовать ли более интересную штуку, раз уж ты взялся, с учетом ограниченности ресурсов MSC-48. Короче, был давно такой "якобы BASIC", который назывался ASIC... Ко мне он попал довольно поздно и пользы от него я уже не поимел, поскольку программировать научился уже совершенно по-другому. Но суть следующая (в общем-то идея напоминает немного С ): это язык программирования, который сочетает простоту и синтаксис BASIC с возможностью прямого использования ассемблерного кода, где это надо, причем генерит (как говорят) весьма хороший код! Примерно так: То есть ASIC удачно сочетает конструкции языка высокого уровня с ассемблерным синтаксисом. Я полистал интернет, что про ASIC на сей день известно... на русском - практически ничего. Есть вот такие ссылки которые еще не протухли: https://en.wikipedia.org/wiki/ASIC_programming_languagehttp://www.atarimagazines.com/compute/issue126/64_Basic_is_back.phpЯ на что намекаю - может и в твоем "микро-Паскале_48" реализовать похожий подход?
_________________ iLavr
|
16 May 2017 09:25 |
|
|
|
Page 1 of 1
|
[ 13 posts ] |
|
Who is online |
Users browsing this forum: No registered users and 5 guests |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|