Мощь бейсика BBC Micro




Наткнулся на упоминание компьютера BBC Micro 1981 года выпуска и немного почитав википедии удивился одной его мощной черте.
Первые версии машин были реализованы на MOS 6502 работавшем на 2 МГц. ОЗУ от 16 до 32 Кб (версии A и B соответственно). ПЗУ — 32 Кб, причём они лежали в верхней части адресного пространства и нижние 16 Кб заранее делались с поддержкой маппинга, на внешние схемы расширения.
И вот верхние 16 Кб ПЗУ содержали ОС «Acorn MOS», где было много полезных базовых функций, а встроенные 16 Кб нижнего ПЗУ содержали по привычной для того времени схеме интерпретатор BASIC — собственно «BBC Micro Basic».
И вот он был весьма забавным зверем для своего времени и платформы.
Большинство других популярных 8-биток либо имели один из многочисленных, но очень похожих вариантов/производных Microsoft Basic (как, например, Apple II или Commodore 64), либо что-то кастомное, но в сильной степени заимствующее основные черты Microsoft Basic (как в ZX Spectrum).
Это были всё классические бейсики 1.x, как я еще их называю «неструктурированные бейсики».
Программирование на них во многом по духу напоминало программирование на ассемблере процессоров как раз типа MOS 6502.

По сравнению с современностью ярко выраженные черты такого программирования это:
  1. отсутствие локальных переменных
  2. подпрограммы можно вызывать оператором GOSUB и можно из них возвращаться оператором RETURN, но из-за (а) параметры передаются в глобальных переменных и ими же возвращаются (причём даже по сравнению с ассемблером был регресс, т.к. вместо внятного имени указывался лишь номер строки программы куда происходит переход)
  3. из инструкций передачи управления только IF/THEN (чаще всего без ELSE), FOR/NEXT и GOTO. Важно заметить, что многострочность поддерживалась только в FOR. Оператор IF же обрывался на конце строки, поэтому чтобы не плодить сверхдлинную лапшу из операторов в одной строке разделенных двоеточием GOTO множились без конца.
  4. определение функций оператором DEF FN по сути было только способом сокращать использование часто используемых формул в выражениях, ибо могли задавать только одно выражение с параметрами и опять таки в одну строку, без операторов.

Все эти особенности очень сильно подрывали удобство программирования и поэтому Бейсик в BBC Micro был поистине передовым для своего времени и платформы.

Во первых — в нём был ELSE в IF-ах и управляющая конструкция REPEAT/UNTIL.

Во вторых — он поддерживал создание полноценных процедур с параметрами оператором DEF PROC. Причём у процедур были и имена (всегда должны начинаться на 'PROC') и параметры и они могли быть многострочными (завершались оператором ENDPROC). То же самое касалось и функций определяемых привычными DEF FN.
Однако с этим была связана одна забавная особенность, видимо экономия на спичках — если однострочные процедуры или функции можно было размещать в любом месте программы, то многострочные страдали немного от одного упрощения — встретив DEF PROC в начале или середине программы интерпретатор бейсика автоматически отбрасывал только эту самую строку с DEF FN и ни разу не пытался пропускать следующие строки до встречи ENDPROC — то есть просто начинал выполнять следующие строки многострочных процедур или функций как основную программу. Это скорее всего означало сбой. Поэтому многострочные процедуры следовало всегда размещать в последних строках программы и не доводить до них поток выполнения никак иначе кроме как их вызовами. В процедурах можно было даже делать локальные переменные оператором LOCAL! При этом для совместимости с MS-like диалектами поддерживались конечно и GOSUB со всей их неприглядностью.
Для наглядности приведу пример как это примерно выглядело:

10 REM PROC demo
20 PROC_ScreenSetup("Hello!")
30 INPUT A$
40 PROC_ScreenSetup(A$)
50 END
60 DEF PROC_ScreenSetup(msg$)
70 CLS
80 PRINT TAB(2);msg$
90 ENDPROC


Во третьих — он поддерживал самый настоящий встроенный ассемблер! Это уже почти за гранью, но написав символ [ интерпретатор переходил в режим компиляции ассемблера 6502 (что заканчивалось при встрече символа ] ) и начинал собирать код, который потом можно было вызывать или функцией совместимой с MS-like диалектами USR или оператором CALL.
Забавно то куда происходила компиляция и как происходила интеграция с таким асмокодом.
Во первых — помимо произвольного количества вещественных или строковых переменных бейсик BBC Micro содержал жёстко прошитые целочисленные переменные с однобуквенными именами от A% до Z% (знак % в конце как раз означал целочисленность). Во первых — они были заметно быстрее по сравнению с вещественными переменными без префиксов. Лежали по фиксированным адресам и даже не стирались при запуске программы начисто оператором RUN. Во вторых — часть из них в некоторых ситуациях начинала играть особую роль.
Так при встрече [ из переменной P% брался адрес в который сейчас надо компилить последующий асмокод (аналог инструкции ORG в асмах вообще).
Кроме того при вызове асмокода через CALL в 8-битные регистры A, X и Y процессора MOS 6502 записывались нижние байты из переменных A%, X% и Y%.
Забавно как именно выбирался адрес для P% куда компилить код.
У оператора аллокации массивов DIM A(size) была особая форма — DIM A size (без круглых скобок).
Она приводила к тому, что в свободной памяти резервировалось size байт, а в переменную A записывался адрес начала этого куска байт. То есть практически malloc!
Нужно было еще вычислять минимально необходимый размер этой области для куска асмокода, увы вручную, но сама аллокация и запись нужного значения в P% перед асмокодом было уже вещью тривиальной.
Хотя можно было и просто писать по фиксированному адресу, ограничив область бейсика, как это тоже было принято в тех компьютерах.
Выглядело всё это примерно так:

10 PRINT "THIS IS BASIC"
20 DIM GAP% 20
30 P%=GAP%
40 [
50 JSR &FFE7
60 RTS
70 ]
80 CALL GAP%


Разное видел и про многое читал, но про бейсик со встроенным ассемблером, да еще и на 8 битах слышу впервые! :)

10 комментариев

avatar
кстати, проработка впечатляет
  • VBI
  • 0
avatar
Тащемта все бейсики тех времён разной степени паршивости ерундень. Теоретически можно было упихать в 16k нормальный структурный интерпретатор, без номеров строк, с независимыми процедурами, локальными переменными итд. Но инерция и цейтнот у наёмных разработчиков не позволили.
avatar
Тут дело наверное даже не в инерции, а в том, что такие ПК всегда целились на рынок школьных компьютеров, ведь тот же самый BBC Micro из статьи выиграл конкурс на то, чтобы стать общеобразовательным компьютером в Англии. Поэтому имидж бейсика как образовательного языка для начала обучения очень твёрдо закрепил его на пьедестале стараниями Microsoft. Для меня вот было открытием, что изначально бейсик был разработан как компилируемый язык.
avatar
Для образовательных целей объективно лучше подходил Лого, который, собственно, и был для этого разработан. Но почему-то воспринимался как игрушка для самых маленьких, хотя на деле был куда удобнее, выразительнее, мощнее и ближе к нормальному языку, чем любой бейсик. Вот такая несправедливость.
avatar
Спасибо за интересную информацию, действительно очень мощная версия Бейсика. Неудивительно, что значительная часть самой первой Элиты была написана на нём. Ассемблерные вставки, встроенные прямо в Бейсик-программу, я вообще встречаю первый раз.
  • Weiv
  • 0
avatar
У Энтерпрайза тоже мощный Бейсик по возможностям.
Вставки на ассемблере, правда, не умеет (позволяет вставлять только чистый машкод), но зато почти все хардварные особенности компьютера были доступны из Бейсика через стандартные операторы. И поэтому нумерация строк программы на Бейсике в основном нужна только для редактирования программы (ну и оператора «DATA»). Всякие GOSUB, GOTO и т.п. оставлены только для «совместимости» и упрощения переноса Бейсик-программ с других компьютеров.
Локальные переменные, объявление новых функций и подпрограмм, обработка прерываний и нештатных ситуаций (catch/try), работа со стереозвуком — всё есть из коробки. Единственным минусом, ИМХО, является не очень высокая скорость интерпретатора.
avatar
Посмотрел вики — на Enterprise тоже было 32Кб ПЗУ, так что мощный бейсик тоже вполне объясним. Кроме того там paging памяти был сразу сделан с заделом на будущее и был более рациональным.
avatar
32КБ ПЗУ занимает только ОСь (EXOS). А Бейсик весит 16КБ и он живёт в отдельном картридже.
avatar
Ааа, точно. Тогда тем более.
avatar
Обратите внимание на бейсик у Commodore 128 (и Commodore 16 до кучи).
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.