vak: (бэсм-6)
Serge Vakulenko ([personal profile] vak) wrote2025-04-21 12:32 pm

Компилятор Би под Дубной

(Я послал этот текст в список рассылки БЭСМ-6, но сохраню и здесь для памяти.)

Раз уж у нас тут постепенно актуализировалась тема написания компиляторов, я тоже увлёкся и реализовал давнишнюю мечту: портонул Би с PDP-7 на БЭСМ-6.

Исходник компилятора: b-besm.b

Проект на Гитхабе: besm6/b-compiler

История вопроса следующая. В 1969 году Кен Томпсон создал язык Би для машины PDP-7. Компилятор порождал так называемый шитый код, который интерпретировался во время выполнения. Позже в 1971-м Деннис Ритчи портонул Би на машину Honeywell GE 645, но без всякого шитого кода, а уже с нормальной генерацией бинарного кода целевого процессора. А когда Ритчи взялся тащить Би на PDP-11, оказалось, что наличие байтовой адресации существенно меняет дело. Пришлось добавить в Би типы, и он быстро превратился в знакомый нам Си.

Исходники компилятора Би считались потерянными. Но девять лет назад Robert Swierczek чудесным образом сумел восстановить тексты Би из обрывков распечаток в рамках проекта pdp7-unix.

Я взял эти исходники и вместо выдачи шитого кода для PDP-7 вставил генерацию машинных команд БЭСМ-6 для ассемблера Madlen. Добавил минимальную рантайм библиотеку и запихнул в мониторную систему Дубна. Компилятор пишет ассемблерный текст на барабан и, если не случилось ошибок, выполняет как бы команду *READ:1. Дальше обычным образом стартует Мадлен и формирует объектные модули. Компилятор Би и рантайм библиотеку я поместил на отдельную ленту, её можно подключать командой *TAPE:7/B. Покажу пример на симуляторе dubna.

Вот скрипт с исходным текстом классического примера Hello World. Компилятор запускается с ленты командой *TRANS.
*name B compiler
*tape:7/b,40
*library:40
*trans-main:40020
main() {
printf("Hello, B!*n");
}
*execute
*end file
Запускаем. Я не стал убирать таблицу загрузки, чтобы вам было видно размер кода:
$ dubna hello.dub
...
*NAME B COMPILER
*TAPE:7/*,40
*LIBRARY:40
*TRANS-MAIN:40020
OVERLAY OT 20/04/25
B COMPILER FOR BESM-6, VERSION 04/2025
COMPILED 3 LINES OF CODE, FOUND 0 ERRORS

*NO LIST
*CALL BLOCKERR
*MADLEN
MAIN CP 0.0, ST 0.0, RT 1.0*
*READ OLD
*EXECUTE
*LIBRA:40 = B/DIV B/EQ B/GT B/LT B/MUL B/NE B/RET B/SAVE0 B/SAVE
B/TOUT B/TRUE CHAR PRINTD PRINTO PRINTF WRITE WRITEB OUT*CNT OUT*SHFT
OUT*BUFF FLUSH FOUT

MAIN 01000 PRINTD 01413 B/MUL 01757 ISOTCOSY 06002
PROGRAM E 01000 PRINTO 01466 B/GT 01766 ISOTCOS1 E 06053
B/SAVE0 01011 WRITE 01517 FOUT 01771 DRUMTAP* 06073
B/RET 01016 B/TRUE 01622 WRCARD 01772 CHKWORD* C 06124
PRINTF 01023 OUT*CNT 01623 WRWORD E 02014 PRINT8 06125
B/SAVE 01256 OUT*SHFT 01624 WBEGIN E 02033 STOP* 06306
CHAR 01263 OUT*BUFF 01625 WRIEND E 02042 EXIT E 06307
B/NE 01301 FLUSH 01654 B/TOUT 02075 CBOБOДHO 06335
B/EQ 01304 B/LT 01744 WRWORD/ C 04000
WRITEB 01307 B/DIV 01747 XWRITE/ C 06000

HELLO, B!
Вот ещё несколько примеров для Би из разных мест. Все они работают под Дубной:Мандельброт выглядит забавно: mandelbrot.txt

Выводы из всей этой затеи:
  • Би вполне был возможен на БЭСМ-6 уже тогда, в середине 70-х. Увы, никто из аксакалов-бэсмачей про него не знал.
  • Если бы Би тогда состоялся, он мог бы стать важным средством системной разработки. Не судьба. Позже язык ЯРМО пытался занять нишу.
  • Результат примерно соответствует мечте Игоря Григорьевича Пасынкова, когда в 1986 году он позвал меня в курчатник заниматься Си для Эльбруса-Б. Ему хотелось видеть Си не только под юниксом, но и в мониторке.
sab123: (Default)

[personal profile] sab123 2025-04-21 11:19 pm (UTC)(link)
В статье Кена Томпсона приводится пример кодогенерации с Би в шитый код на PDP-11. Но интересный фокус тут наверное в том, что даже для стековой машины на PDP-11 для большинства операций родные инструкции займут столько же места, как и шитый код - например, для сложения что-нибудь типа

ADD (R6)+, (R6)
lxe: (Default)

[personal profile] lxe 2025-04-22 06:37 am (UTC)(link)
Эта инструкция как раз машинное слово и занимает.
Только она еще стек разворачивает, это точно задуманный эффект? (R6 -- это SP.)
sab123: (Default)

[personal profile] sab123 2025-04-23 12:44 am (UTC)(link)
Ну да, именно об этом и речь: сложение двух верхних слов на стеке одной инструкцией размером в слово. Хотя, конечно, на самом деле стек данных будет отдельным от стека вызовов, другой регистр.
lxe: (Default)

[personal profile] lxe 2025-04-23 12:52 am (UTC)(link)
На PDP-11? Смотря какая конвенция вызова, конечно, но по той, которую я знаю, R6 = SP (и он общий), R5 = FP.
sab123: (Default)

[personal profile] sab123 2025-04-23 06:14 am (UTC)(link)
Ну я условно написал R6, чтобы было понятно, что стек.