Л.Н. ЖАРИКОВ (г. Ленинград)

О СТАТЬЕ «БОЛЬШИЕ ПРОГРАММЫ НА БК0010» (№3, 1989)

С трудом самостоятельно разобрался в работе опубликованной программы и устранил неточности. Прочитав в № 7 серии ВТ письмо П.И. Павлова и представив, сколько усилий потребуется любителям для запуска данной программы, хочу предложить несколько модифицированный вариант этой интересной программы с более подробным, чем у авторов статьи, описанием её работы. Эта модификация позволяет ускорить выполнение программы на 20% и снять некоторые ограничения, присущие оригиналу.

Предлагаю опубликовать модифицированную программу с целью обучения.

По примеру авторов программы COM.ASC программа COMM.ASC (см. таблицу) написана на БЕЙСИКе. Она загружается в память компьютера и запускается как любая программа на БЕЙСИКе БК-0010.01. При своей работе программа COMM.ASC создаёт программу в машинных кодах, начиная с адреса 37400 (здесь и далее все адреса представлены в восьмеричной системе счисления), и передаёт ей управление. В результате на экране пропадает курсор, и пользователь с клавиатуры может ввести произвольную последовательность команд БЕЙСИК-системы, разделяя их клавишей ввода (ВК).

Например,

NEW /ВК/
CLEAR 200,&O20000 /ВК/
LOAD «PROG1»/BK/
RUN /ВК/
NEW /ВК/
LOAD «PROG2» /ВК/
RUN /ВК/

Запуск введённой последовательности на исполнение осуществляется нажатием клавиши «:».

В примере выполняются последовательно две программы «PROG1» и «PROG2». Оператор CLEAR организует область памяти для возможной передачи данных из «PROG1» в «PROG2».

По окончании выполнения последовательности команд останется загруженной в память Бейсик-программа «PROG2» То есть точно так же, как если бы вы набирали и выполняли эти команды последовательно с клавиатуры в непосредственном режиме Бейсик-системы. Кроме того, останется резидентно в памяти и программа в кодах, сформированная программой COMM.ASC, если в «PROG1» или в «PROG2» не переопределялись функции пользователя USR0. Необходимо заметить, что команды NEW и CLEAR не переопределяют функции USR пользователя.

Этим последним обстоятельством можно воспользоваться для повторного запуска программы в кодах, оставшейся резидентно, командой A=USR(A), введённой в непосредственном режиме Бейсик-системы.

Полезно сохранить сформированную программой COMM.ASC программу в кодах на магнитной ленте командой BSAVE «СОМК», &О37400, &O37562. Записанная таким образом программа COMK.BIN в машинном коде занимает на МЛ существенно меньше места, чем COMM.ASC, следовательно, загружается быстрее и не требует компиляции.

Загрузить в память БК и запустить программу COMK.BIN можно, набрав команду BLOAD «СОМК», R. Кроме того, при запуске программы СОМК таким образом не требуется начальная команда NEW в серии команд Бейсик-системы для освобождения памяти под первую загружаемую программу.

Недостатком программы COM.ASC является то обстоятельство, что при наличии в загружаемых Бейсик-программах операторов INPUT и функций INKEY$ требующих ввода символов с клавиатуры, все необходимые программам данные нужно заносить в буфер, а это не всегда целесообразно.

Программа COMM.ASC в отличие от программы COM.ASC позволяет свободно использовать INPUT и INKEY$. Это достигается введением в загружаемые программы на БЕЙСИКе четырёх дополнительных строк:

Эти вставки восстанавливают и заменяют соответственно адрес стандартной программы обработки программного прерывания ЕМТ, хранящийся в ячейке с адресом 30, на адрес 37450 программы выбора символа из буфера, заполненного с клавиатуры пользователем.

Теперь коротко об отличиях программы СОММ.ASC от программы COM.ASC.

Для ускорения передачи символа из буфера Бейсик-системе восстановление адреса стандартной программы обработки прерывания ЕМТ переставлено в другой участок программы

С целью универсализации программы выброшены строки 54,55 программы COM.ASC, которые должны по замыслу авторов заносить в буфер программы самой первой команду NEW/ВК/, а не являются лишними, как считает тов. Павлов П.И. из г. Москвы. Такой подход при отладке приводил сразу к стиранию из памяти оригинала Бейсик-программы COM.ASC независимо от желания пользователя (а способ запуска резидентной программы, сохранившейся в памяти, авторы не указали). Об этой команде-невидимке NEW в статье не сказано ни слова, а расшифровка строк 54-55, опубликованных с ошибками в адресах, не даётся с лёта, особенно если работаешь в БЕЙСИКе, а не на АССЕМБЛЕРе. Кроме того, наличие скрытой от пользователя команды не является примером хорошего стиля программирования и занимает память.

Буфер программы в кодах подвинут вплотную к самой программе.

Рассмотрим теперь структуру программы COMK.BIN в кодах, которая будет сформирована программой СОММ. ASC

В программе СОМК работают четыре подпрограммы:

Графически структура программы COMK.BIN выглядит так:


 

Адрес начала

Наименование подпрограммы

Условное наименование

37400:

Заполнение буфера программы с клавиатуры, пока не будет нажата клавиша «:»

Подмена адреса подпрограммы обработки прерывания EMT

Заполнение

37440:

Подмена

37450:

Обработка программного прерывания ЕМТ 6 для выдачи символа из буфера в регистр R0

Обработка

37554:

Восстановление в ячейке 30 стандартного адреса подпрограммы обработки прерывания ЕМТ

Восстановление

Рассмотрим работу программы COMM.ASC и создаваемой ею программы COMK.BIN.

Операторы 1-58 создают программу в кодах COMK.BIN, начиная с адреса 37400. Оператор 59 определяет функцию пользователя USR0. Оператор 60 передаёт управление этой функции, т.е. программе в кодах СОМК.

Машинные команды, сформированные в строках 1-6, вызывают начальное заполнение адреса текущего свободного байта в буфере в ячейку с адресом 37564 и адреса текущего байта в буфере в ячейку с адресом 37566.

Команда, сформированная в строке 7, вызывает программное прерывание ЕМТ 6, по которому система ожидает ввода символа с клавиатуры. Этот символ заносится в регистр R0.

Следующая команда ЕМТ 16 вызывает прерывание для выдачи символа из регистра R0 на экран.

Строки 9-10 вызывают передачу символа из регистра R0 в текущий байт буфера, адрес которого находится в ячейке с адресом 37564.

Команда в строках 11-12 увеличивает на 1 содержимое ячейки с адресом 37564.

Команда в строках 13-14 сравнивает код только что переданного символа с кодом «:».

Команда в строке 15 в случае равенства переданного в буфер символа «:», т.е. когда пользователь ввёл уже в буфер то, что хотел, передаёт управление на команду, сформированную в строке 17. Иначе отработает команда из строки 16. Управление будет вследствие этого передано вновь на команду из строки 7, т.е. на ввод очередного символа с клавиатуры в регистр R0, а затем на передачу его в буфер программы. Заполнение буфера будет закончено только тогда, когда пользователь нажмёт клавишу «:».

В этом случае команда, сформированная в строке 17, подменяет адрес в ячейке 30 (адрес, сначала содержащийся в ней, равен 100112) на адрес 37450, который указывает на подпрограмму «Обработка».

Следующая команда, сформированная в строке 20, возвращает управление Бейсик-системе. Бейсик-система переходит в непосредственный режим выполнения, т.е. в режим ожидания ввода от клавиатуры по команде программного прерывания ЕМТ 6. Но адрес программы обработки прерывания, извлекаемый командой ЕМТ 6 из ячейки 30, уже был подменен нашей программой в кодах на адрес 37450, поэтому осуществляется переход не по обычному адресу 100112, а по указанному.

Программа COMK.BIN начиная с команды в строках 21-22, выполняет следующие действия:

Это делается на тот случай, если программное прерывание, вызвавшее переход на программу «Обработка», окажется не прерыванием ЕМТ 6, а каким-нибудь другим ЕМТ J. В этом случае переход на программу «Обработка», которая не может выполнить этих функций, является ошибкой. Поэтому нужно, временно восстановив обычный адрес программы обработки прерывания ЕМТ, ещё раз выполнить эту же команду ЕМТ J;

Анализ программы показывает, что её можно несколько сократить, если выделить подпрограммы. Например, вместо команды в строках 51-53 можно вставить вызов подпрограммы по адресу 37554, но при этом выполнение программы несколько замедлится.

Всем предложенная программа хороша. Одно плохо: отсутствие у большинства читателей магнитофонов с электронным управлением включения / выключения двигателя. Хотелось бы, чтобы читатели, имеющие доработанные магнитофоны, поделились своими находками. Интересно также было бы узнать, какие альтернативные варианты расширения оперативной памяти БК существуют у читателей, которые владеют ими, можно ли доработать БК для подключения к нему накопителя на гибких магнитных дисках?

Таблица
Программы COMM.ASC, COMK.BIN

Адрес

Машин-ный код

Ассемблер

Комментарии

Бейсик СОММ. ASC

1

2

3

4

5

37400

012737

    MOV #A+6, @#A

Засылка адреса начала буфера в ячейку, предназначенную для хранения адреса первого свободного байта в буфере

1.

POKE &O37400,&O12737

37402

037572

2.

POKE &O37402,&O37572

37404

037564

3.

POKE &O37404,&O37564

37406

012737

    MOV #A+6, @#A+2

Засылка адреса начала буфера в ячейку, предназначенную для хранения адреса текущего байта в буфере

4.

POKE &O37406,&O12737

37410

037572

5.

POKE &O37410,&O37572

37412

037566

6.

POKE &O37412,&O37566

37414

104006

M1: EMT 6

Ввод символа с клавиатуры в регистр R0

7.

POKE &O37414,&O104006

37416

104016

    EMT 16

Вывод символа из регистра R0 в текущую позицию экрана

8.

POKE &O37416,&O104016

37420

110077

    MOVB R0,@A

Пересылка символа из регистра R0 в текущий байт буфера

9.

POKE &O37420,&O110077

37422

000140

10.

POKE &O37422,&O140

37424

005237

    INC @#A

Увеличение на 1 адреса первого свободного байта в буфере

11.

POKE &O37424,&O5237

37426

037564

12.

POKE &O37426,&O37564

37430

020027

    CMP R0,#72

Сравнение содержимого

13.

POKE &O37430,&O20027

37432

000072

R0 с кодом символа «:»

14.

POKE &O37432,&O72

37434

001401

    BEQ M2

Переход к концу подпрограммы в случае равенства

15.

POKE &O37434,&O1401

37436

000766

    BR M1

Переход на ввод очередного символа с клавиатуры

16.

POKE &O37436,&O766

37440

012737

M2: MOV #M3,@#30

Засылка адреса подпрограммы «Обработка» в ячейку с адресом 30. Подмена адреса подпрограммы обработки прерывания ЕМТ

17.

POKE &O37440,&O12737

37442

037450

18.

POKE &O37442,&O37450

37444

000030

19.

POKE &O37444,&O30

37446

000207

    RTS PC

Возврат из подпрограммы

20.

POKE &O37446,&O207

37450

011637

M3: MOV (SP),@#A+4

Запоминание адреса команды, которую нужно выполнить при возврате

21.

POKE &O37450,&O11637

37452

037570

22.

POKE &O37452,&O37570

37454

005337

    DEC @#A+4

из прерывания Уменьшение предыдущего адреса на 2, чтобы определить адрес команды, которая вызвала программное прерывание ЕМТ

23.

POKE &O37454,&O5337

37456

037570

24.

POKE &O37456,&O37570

37460

005337

    DEC @#A+4

25.

POKE &O37460,&O5337

37462

037570

26.

POKE &O37462,&O37570

 

 

P=100112

Начальное присвоение адреса

 

 

37464

017737

    MOV @A+4,@#M4

Запись команды, которая вызвала прерывание, в программу на тот случай, если эта команда не ЕМТ 6

27.

POKE &O37464,&O17737

37466

000100

28.

POKE &O37466,&O100

37470

037510

29.

POKE &O37470,&O37510

37472

022737

    CMP #104006,@#M4

Сравнение кода команды, которая вызвала прерывание, с кодом команды ЕМТ 6

30.

POKE &O37472,&O22737

37474

104006

31.

POKE &O37474,&O104006

37476

037510

32.

POKE &O37476,&O37510

37500

001410

    BEQ M5

Переход на часть подпрограммы, передающей символ из буфера в регистр R0, в случае равенства

33.

POKE &O37500,&O1410

37502

012737

    MOV #P,@#30

Засылка обычного адреса подпрограммы обработки прерывания ЕМТ в ячейку с адресом 30

34.

POKE &O37502,&O12737

37504

100112

35.

POKE &O37504,&O100112

37506

000030

36.

POKE &O37506,&O30

37510

000000

M4: HALT

На место этой команды записывается команда, вызвавшая прерывание

37.

POKE &O37510,&O0

37512

012737

    MOV #M3,@#30

Повторная подмена адреса подпрограммы обработки прерывания ЕМТ

38.

POKE &O37512,&O12737

37514

037450

39.

POKE &O37514,&O37450

37516

000030

40.

POKE &O37516,&O30

37520

000002

    RTI

Возврат из прерывания

41.

POKE &O37520,&O2

37522

117700

M5: MOVB @A+2,R0

Пересылка байта из буфера в регистр R0

42.

POKE &O37522,&O117700

37524

000054

43.

POKE &O37524,&O54

37526

005237

    INC@#A+2

Увеличение адреса текущего байта в буфере

44.

POKE &O37526,&O5237

37530

037566

45.

POKE &O37530,&O37566

37532

023737

    CMP @#A,@#A+2

Сравнение адреса последнего байта буфера и текущего адреса в буфере (исчерпание буфера)

46.

POKE &O37532,&O23737

37534

037564

47.

POKE &O37534,&O37564

37536

037566

48.

POKE &O37536,&O37566

37540

001401

    BEQ M6

Если буфер исчерпан, то переход на конец подпрограммы

49.

POKE &O37540,&O1401

37542

000002

    RTI

Возврат из прерывания

50.

POKE &O37542,&O2

37544

012737

M6: MOV #P,@#30

Восстановление обычного адреса подпрограммы обработки программного прерывания ЕМТ в ячейке по адресу 30

51.

POKE &O37544,&O12737

37546

100112

52.

POKE &O37546,&O100112

37550

000030

53.

POKE &O37550,&O30

37552

000000

    HALT

Останов программы

54.

POKE &O37552,&O0

37554

012737

    MOV #P,@#30

Восстановление обычного адреса подпрограммы обработки программного прерывания ЕМТ в ячейке по адресу 30

55.

POKE &O37554,&O12737

37556

100112

56.

POKE &O37556,&O100112

37560

000030

57.

POKE &O37560,&O30

37562

000207

    RTS PC

Возврат из подпрограммы

58.

POKE &O37562,&O207

 

 

A:  HALT

Начало рабочей области

 

 

 

 

    END

Конец на ассемблере

59.

DEF USR=&O34700

 

 

 

Определение функции пользователя

60.

A=USR(A)

 

 

 

Вызов функции пользователя

 

 

 

Performed by © gid, 2012-2022.