Есть вариант, как небольшими усилиями соорудить Си компилятор для БЭСМ-6. Есть такой проект ELVM. Это универсальный компилятор Си на основе LLVM, но не для конкретных процессоров, а вообще. Он выдаёт код для некоторой абстрактной машины. И дальше строятся бекэнды для разнообразных от смешных типа Brainfuck или Conway's Life до реальных типа WebAssembly.
Для прикола народ скомпилировал простой компилятор Си на "машину" - скрипт для редактора VI. И оно работает! Хотя нешустро: компиляция "Hello World" в таком VI занимает двадцать минут: "C Compiler exists purely in VIM".
Идея аналогичная древнему компилятору BCPL, который позже превратился в B (предшественник Си). Выдаём код для абстрактной машины, и строим отдельные кодогенераторы, транслирующие абстрактный код в выполняемый бинарник для нужной архитектуры. Такой подход оказался успешным, и немало способствовал распространению BCPL пятьдесят лет назад.
Не вижу проблем повторить это дело для БЭСМ-6. Размер кодогенератора для архитектуры x86, к примеру - всего 309 строк.
Побробуем запустить классический пример "Hello World" через ELVM для архитектуры x86 под Линуксом.
Для прикола народ скомпилировал простой компилятор Си на "машину" - скрипт для редактора VI. И оно работает! Хотя нешустро: компиляция "Hello World" в таком VI занимает двадцать минут: "C Compiler exists purely in VIM".
Идея аналогичная древнему компилятору BCPL, который позже превратился в B (предшественник Си). Выдаём код для абстрактной машины, и строим отдельные кодогенераторы, транслирующие абстрактный код в выполняемый бинарник для нужной архитектуры. Такой подход оказался успешным, и немало способствовал распространению BCPL пятьдесят лет назад.
Не вижу проблем повторить это дело для БЭСМ-6. Размер кодогенератора для архитектуры x86, к примеру - всего 309 строк.
Побробуем запустить классический пример "Hello World" через ELVM для архитектуры x86 под Линуксом.
Собираем компилятор:
Результатом будут бинарники out/8cc (компилятор) и out/elc (кодогенератор). Возьмем простой вариант "Hello World":git clone https://github.com/shinh/elvm.git
cd elvm
git submodule update --init
make
Компилируем, получаем ассемблерный код абстрактной машины:int main()
{
const char* p = "Hello, world!\n";
for (; *p; p++)
putchar(*p);
return 0;
}
Превращаем в бинарник для x86:$ cd out
$ ./8cc -S hello.c
$ cat hello.s
.text
main:
#{push:main}
mov D, SP
add D, -1
store BP, D
mov SP, D
mov BP, SP
sub SP, 1
.file 1 "hello.c"
.loc 1 7 0
# }
.loc 1 4 0
# for (; *p; p++)
mov A, 0
mov B, SP
.data
.L3:
.string "Hello, world!\n"
.text
mov A, .L3
mov B, BP
add B, 16777215
store A, B
.loc 1 5 0
# putchar(*p);
.L0:
.loc 1 4 0
# for (; *p; p++)
mov B, BP
add B, 16777215
load A, B
mov B, A
load A, B
jeq .L4, A, 0
jmp .L5
.L4:
.loc 1 5 0
# putchar(*p);
jmp .L2
.L5:
.loc 1 4 0
# for (; *p; p++)
mov B, BP
add B, 16777215
load A, B
mov B, A
load A, B
mov D, SP
add D, -1
store A, D
mov SP, D
putc A
add SP, 1
.loc 1 5 0
# putchar(*p);
.L1:
.loc 1 4 0
# for (; *p; p++)
mov B, BP
add B, 16777215
load A, B
mov D, SP
add D, -1
store A, D
mov SP, D
add A, 1
mov B, BP
add B, 16777215
store A, B
load A, SP
add SP, 1
.loc 1 5 0
# putchar(*p);
jmp .L0
.L2:
.loc 1 7 0
# }
mov A, 0
mov B, A
#{pop:main}
exit
#{pop:main}
exit
Запускаем:$ ./elc -x86 hello.s > hello.elf
$ file hello.elf
hello.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, no section header
$ ./hello.elf
Hello, world!

no subject
Date: 2024-07-09 19:32 (UTC)no subject
Date: 2024-07-09 20:15 (UTC)no subject
Date: 2024-07-09 21:14 (UTC)no subject
Date: 2024-07-09 21:26 (UTC)no subject
Date: 2024-07-09 21:47 (UTC)no subject
Date: 2024-07-09 23:27 (UTC)https://www.nfitmivt.ru/content/people/detail.php?ELEMENT_ID=245
no subject
Date: 2024-07-10 06:49 (UTC)no subject
Date: 2024-07-10 08:41 (UTC)no subject
Date: 2024-07-10 01:10 (UTC)no subject
Date: 2024-07-10 04:35 (UTC)no subject
Date: 2024-07-10 15:12 (UTC)No bit operations
No floating point arithmetic
конечно, получится. Ради оптимизации можно взять бэкенд для фортрана и допинать в приемлемый для Форекса, или написать бэкенд в Паскаль.
Но это не то, о чём так долго говорили большевики. :)
no subject
Date: 2024-07-10 19:40 (UTC)static void emit_data_primtype(Type *ty, Node *val, int depth) { switch (ty->kind) { case KIND_FLOAT: { assert_float(); break; } case KIND_DOUBLE: assert_float(); break;Файл https://github.com/shinh/8cc/blob/master/gen.cno subject
Date: 2024-07-10 20:50 (UTC)int a, b; exch() { a = a ^ (b = b ^ (a = a ^ b)); }получается
1: int a, b; 2: exch() { 3: a = a ^ (b = b ^ (a = a ^ b)); ENT 0 IMM -137158648 PSH IMM -137158648 LI PSH IMM -137158644 PSH IMM -137158644 LI PSH IMM -137158648 PSH IMM -137158648 LI PSH IMM -137158644 LI XOR SI XOR SI XOR SI 4: } LEVа хочется, в конце концов, всего-навсего 7 команд
Так что для относительно быстрого результата - только хардкор в виде прихачивания сишного фронтенда к имеющемуся паскалевскому бэкенду.
no subject
Date: 2024-07-10 21:46 (UTC)