Сначала я смотрел в сторону 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: Select all
Var
x,y : byte;
Begin
x := 6;
y := 2;
x := x + y;
y := y - 3;
End.
Code: Select all
;; 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