|
|
Строка 1: |
Строка 1: |
| {{ДИ}}
| | '''Материал удален по требованию автора.''' |
| {{TOCright}}
| |
| | |
| <pre>
| |
| 6.1. Использование подпрограмм в кодах при работе на Бейсике
| |
| | |
| Одним из приемов увеличения возможностей программы на Бейсике
| |
| является использование подпрограмм в кодах. Правда, этот путь
| |
| несколько половинчатый - почему бы сразу не писать всю программу на
| |
| ассемблере ? Поскольку Бейсик по-прежнему занимает много памяти, то и
| |
| эффективность этого способа сомнительна. Использовать подпрограммы в
| |
| кодах в Бейсике, пожалуй, целесообразно только при отсутствии
| |
| описанных в гл.5 инструментальных средств, а также в тех случаях,
| |
| когда Вы не хотите или не умеете писать программы в кодах, а улучшить
| |
| свою программу на Бейсике хочется. В последнем случае можно
| |
| использовать чьи-либо готовые подпрограммы в кодах.
| |
| Для подготовки подпрограммы в кодах с помощью Бейсика часто
| |
| используется такой прием: коды команд записываются в операторе DATA,
| |
| из которого затем в цикле читаются оператором READ и заносятся в
| |
| память оператором POKE.
| |
| Для того, чтобы зарезервировать достаточно места в памяти для
| |
| размещения подпрограмм, необходимо перед началом работы дать команду
| |
| CLEAR в непосредственном режиме Бейсика:
| |
| | |
| CLEAR B,A
| |
| где
| |
| B - количество байт, отводимых под символьные переменные;
| |
| A - адрес верхней границы памяти, отведенной для программы на
| |
| Бейсике.
| |
| | |
| Например, если начальный адрес подпрограммы в кодах равен 30000, то
| |
| можно ввести оператор CLEAR 250,&O30000 . После исполнения этого
| |
| оператора транслятор с языка Бейсик использует только область ОЗУ,
| |
| расположенную до адреса 30000. А с адреса 30000 могут быть расположены
| |
| подпрограммы в машинных кодах.
| |
| Две команды Бейсика позволяют записывать и читать с магнитофона
| |
| участки ОЗУ, в которых могут размещаться подпрограммы в кодах или
| |
| таблицы изображений (спрайтов).
| |
| | |
| BSAVE"имя",начало,конец
| |
| | |
| По этой команде область ОЗУ с указанным начальным и конечным
| |
| адресом записывается на магнитофон в виде файла.
| |
| Программа с МЛ может быть загружена в ОЗУ и запущена на выполнение
| |
| командой Бейсика:
| |
| BLOAD"имя",R,адрес
| |
| Если в данной команде отсутствует первая запятая с буквой "R", то
| |
| произойдет только загрузка программы в ОЗУ с указанного адреса.
| |
| Обычно, чтобы не возиться с загрузкой множества файлов,
| |
| подпрограмму в кодах не записывают отдельно, а так и хранят в
| |
| программе на Бейсике в операторе DATA. При выполнении программы коды
| |
| переписываются в ОЗУ, потом задается адрес запуска подпрограммы и она
| |
| вызывается в любом нужном месте программы на Бейсике.
| |
| Здесь будут рассмотрены два примера использования в программах на
| |
| языке Бейсик подпрограмм в машинных кодах.
| |
| | |
| Пример 1. Вывод спрайта и управление его движением.
| |
| Этот пример аналогичен второму примеру из п.5.3.3. Для вывода и
| |
| стирания спрайта используются подпрограммы в кодах, а управление
| |
| движением спрайта осуществляется программой на Бейсике.
| |
| Подпрограммы вывода и стирания спрайта аналогичны приведенным в
| |
| п.5.3.3:
| |
| | |
| ; вывод спрайта на экран
| |
| 035000 012700 MOV #MEN,R0
| |
| 035002 035070
| |
| 035004 011501 MOV (R5),R1 ;адрес вывода спрайта
| |
| 035006 012002 MOV (R0)+,R2
| |
| 035010 012003 MOV (R0)+,R3
| |
| 035012 010204 A: MOV R2,R4
| |
| 035014 010146 MOV R1,-(SP)
| |
| 035016 112021 B: MOVB (R0)+,(R1)+
| |
| 035020 077402 SOB R4,B
| |
| 035022 012601 MOV (SP)+,R1
| |
| 035024 062701 ADD #100,R1
| |
| 035026 000100
| |
| 035030 077310 SOB R3,A
| |
| 035032 000207 RTS PC ;выход из подпрограммы
| |
| ; чистка спрайта на экране
| |
| 035034 012700 MOV #MEN,R0
| |
| 035036 035070
| |
| 035040 011501 MOV (R5),R1 ;адрес стирания спрайта
| |
| 035042 012002 MOV (R0)+,R2
| |
| 035044 012003 MOV (R0)+,R3
| |
| 035046 010204 C: MOV R2,R4
| |
| 035050 010146 MOV R1,-(SP)
| |
| 035052 105021 D: CLRB (R1)+
| |
| 035054 077402 SOB R4,D
| |
| 035056 012601 MOV (SP)+,R1
| |
| 035060 062701 ADD #100,R1
| |
| 035062 000100
| |
| 035064 077310 SOB R3,C
| |
| 035066 000207 RTS PC ;выход из подпрограммы
| |
| ; спрайт, закодированный в формате ГРЕД
| |
| 035070 MEN: .#2.#12.#1640.#1700.#140300.#37774.#1703
| |
| .#1700.#1700.#6060.#6060
| |
| 035116 .#36074
| |
| | |
| В отличие от примера п.5.3.3, где операции вывода и стирания
| |
| спрайта были встроены в программу, здесь они оформлены в виде
| |
| подпрограмм, которые можно вызывать функцией Бейсика USR. Выход из
| |
| подпрограммы осуществляется, как обычно, командой RTS PC.
| |
| Одновременно в программе могут быть определены 10 различных функций
| |
| USR0..USR9. В данном примере мы используем только две подпрограммы
| |
| (соответственно, функции USR0 и USR1).
| |
| Функция USR позволяет передать подпрограмме в кодах один параметр и
| |
| вернуть одно значение того же типа. Функция USR помещает в R5 адрес
| |
| передаваемого параметра, а в R3 - его тип (единица в 15-м разряде
| |
| означает символьную строку, информация о других типах хранится в
| |
| младшем байте R3: -1 - целый, 0 - вещественный двойной точности, 1 -
| |
| вещественный одинарной точности; если аргумент - символьная строка, то
| |
| в качестве аргумента передаются два слова - длина и адрес строки). В
| |
| данном примере мы передаем подпрограммам адрес ОЗУ экрана, куда нужно
| |
| вывести (или где стереть) спрайт. Поскольку адрес будет размещаться в
| |
| переменной целого типа, анализировать R3 нет нужды.
| |
| Отметим также, что в п.5.3.3 "по ходу действия" в R5 сохранялось
| |
| значение R1, здесь же мы R1 сохраним в стеке, чтобы не испортить адрес
| |
| аргумента.
| |
| Подпрограммы и закодированный спрайт мы разместим с адреса 35000.
| |
| Тогда перед набором программы (или загрузкой ее с магнитной ленты)
| |
| необходимо выполнение оператора CLEAR ,&О35000. Этот оператор можно
| |
| вставить первой строкой в программу, чтобы он выполнялся
| |
| автоматически, но вот беда - не все экземпляры БК-0010-01 отработают
| |
| его правильно. Это связано с различиями версий Бейсика в ПЗУ БК разных
| |
| лет выпуска.
| |
| Для того, чтобы автоматизировать ввод подпрограмм, их коды мы
| |
| разместим в операторе DATA, откуда потом в цикле будем читать и
| |
| переписывать по адресам ОЗУ, начиная с 35000.
| |
| | |
| 10 DATA &O012700,&O035070,&O011501,&O012002,&O012003,&O010204,&O010146
| |
| 15 DATA &O112021,&O077402,&O012601,&O062701,&O100,&O077310,&O207
| |
| 20 DATA &O012700,&O035070,&O011501,&O012002,&O012003,&O010204,&O010146
| |
| 25 DATA &O105021,&O077402,&O012601,&O062701,&O100,&O077310,&O207
| |
| 30 DATA 2,&O12,&O1640,&O1700,&O140300,&O37774,&O1703
| |
| 35 DATA &O1700,&O1700,&O6060,&O6060,&O36074
| |
| 40 ?CHR$(140);CHR$(140) 'инициализируем экран
| |
| 50 FOR A%=&O35000 TO &O35116 STEP 2% 'записываем подпрограммы в ОЗУ
| |
| 60 READ D%
| |
| 70 POKE A%,D%
| |
| 80 NEXT A%
| |
| 90 DEF USR0=&O35000 'задаем адрес подпрограммы вывода спрайта
| |
| 95 DEF USR1=&O35034 'задаем адрес подпрограммы стирания спрайта
| |
| 100 S%=&O56036 'начальный адрес ОЗУ, где располагается спрайт
| |
| 110 L%=USR0(S%) 'выводим спрайт
| |
| 115 FOR L%=0% TO 150% 'задержка
| |
| 116 NEXT
| |
| 117 L%=USR1(S%) 'стираем спрайт
| |
| 120 I%=PEEK(&O177662) 'смотрим, какая клавиша была нажата
| |
| 130 IF I%=&O10 THEN IF S% MOD 64% <> 0% THEN S%=S%-1% 'влево
| |
| 140 IF I%=&O31 THEN IF S% MOD 64% < &O76 THEN S%=S%+1% 'вправо
| |
| 150 IF I%=&O32 THEN IF S%>&O43000 THEN S%=S%-&O200 'вверх
| |
| 160 IF I%=&O33 THEN IF S%<&O76000 THEN S%=S%+&O200 'вниз
| |
| 170 GOTO 110
| |
| | |
| Строки 50 - 80 производят загрузку команд и данных в область памяти
| |
| с адреса 35000 по 35116.
| |
| Оператор DEF (строки 90-95) определяет подпрограммы в машинных
| |
| кодах под именем USR0 и USR1 и задает их начальный адрес.
| |
| Текущее значение адреса спрайта в ОЗУ экрана хранится в целой
| |
| переменной S%.
| |
| В строке 120 переменной I% присваивается код нажатой клавиши, в
| |
| зависимости от которого в строках 130 - 160 изменяется адрес спрайта
| |
| S%.
| |
| Начальная установка экрана (строка 40) необходима для того, чтобы
| |
| привести экран в исходное состояние, когда верхний левый угол экрана
| |
| соответствует адресу 40000.
| |
| | |
| Пример 2:
| |
| | |
| 10 DATA &O13701,&O35102,&O12737,&O100,&O177716,&O13700,&O35100
| |
| 12 DATA &O77001,&O12737,0,&O177716,&O13700,&O35100,&O77001,&O77115
| |
| 14 DATA &O12702,&O400,&O77201,&O207
| |
| 20 FOR A%=&O35000 TO &O35044 STEP 2
| |
| 30 READ B%
| |
| 40 POKE A%,B%
| |
| 50 NEXT A%
| |
| 60 DEF USR0=&O35000
| |
| 70 DATA 128,128,112,128,99,640,128,128,112,128,99,128,128,128
| |
| 75 DATA 94,128,99,128,128,256,112,128,99,128,112,640
| |
| 80 FOR C%=1 TO 13
| |
| 90 READ T%,D%
| |
| 100 POKE &O35100,T%
| |
| 110 POKE &O35102,D%
| |
| 120 I%=USR0(I%)
| |
| 130 NEXT C%
| |
| | |
| Программа на Бейсике, приведенная в этом примере, использует
| |
| подпрограмму в машинных кодах для получения мелодии.
| |
| Строки 10-60 подготавливают в памяти, начиная с адреса 35000,
| |
| подпрограмму в машинных кодах.
| |
| Вся мелодия состоит из звуков. Количество звуков равно количеству
| |
| пар чисел, перечисленных в строках 70-75. В каждой паре чисел первое
| |
| число задает тональность, а второе - длительность звука.
| |
| Строки 80-130 "исполняют" мелодию.
| |
| | |
| 6.2. Использование вещественной арифметики Бейсика
| |
| при программировании в кодах
| |
| | |
| Вы уже знаете, что в системе команд процессора БК нет команд работы
| |
| с вещественными (действительными) числами. Как в Бейсике, так и в
| |
| Фокале работа с вещественными числами организуется чисто программно. В
| |
| таком случае, почему бы не использовать записанные в ПЗУ БК
| |
| подпрограммы, если надо производить какие-либо вычисления ?
| |
| Использование подпрограмм вещественной арифметики Фокала описано в
| |
| [15]. Здесь мы опишем использование арифметики Бейсика [8]. Сразу же
| |
| заметим, что формат вещественного числа в Бейсике и Фокале различен.
| |
| Учтите также, что применение описываемого здесь метода сделает
| |
| программу непереносимой - она уже не сможет работать на БК-0010 с
| |
| Фокалом или на БК-0010-01 при включенном блоке МСТД (равно как и
| |
| программы, использующие Фокал, не будут работать с Бейсиком). Хорошим
| |
| выходом было бы использование стандартных подпрограмм (из программного
| |
| обеспечения Электроники-60) или эмуляторов вещественной арифметики, но
| |
| это доступно, пожалуй, только профессиональным программстам,
| |
| использующим ЭВМ более высокого класса в качестве инструментальной.
| |
| Что же касается использования подпрограмм Бейсика, то платой за это
| |
| будет 2К памяти, так как область ОЗУ ниже адреса 4000 используется
| |
| Бейсиком для своих рабочих переменных и стека.
| |
| Все расчеты в Бейсике производятся с вещественными числами двойной
| |
| точности. Если в программе на Бейсике используются числа одинарной
| |
| точности, то перед вычислениями они все равно преобразуются к двойной.
| |
| Каков же формат вещественного числа в Бейсике ?
| |
| Числа двойной точности занимают в памяти 4 слова (8 байт). При этом
| |
| старший разряд 1-го слова (63-ий разряд числа) - знак числа, разряды
| |
| 7-14 (разряды 55-62 числа) - порядок (p), а остальные 6 разрядов 1-го
| |
| слова и 2-ое, 3-е, 4-е слова (разряды 0-54 числа) - мантисса (М)
| |
| (рис.26).
| |
| Тогда значение числа N определяется по формуле:
| |
| | |
| p-201 -1 -2 -3 -54 -55 p-201
| |
| N=(M+1) 2 =(1+2 a +2 a +2 a + ... +2 a +2 а ) 2 ,
| |
| 54 53 52 1 0
| |
| | |
| где a - значение i - го бита числа (0 или 1).
| |
| i
| |
| | |
| Число 201 -восьмеричное, остальные - десятичные.
| |
| | |
| │ X (адрес числа) │ X+2 │ X+10
| |
| │ │ │
| |
| │63 р а з р я д ы │ ч и с л а 0│
| |
| ├─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─ - - - ───┬─┬─┬─┬─┬─┤
| |
| │ порядок (p) │ м а н т и с с а (M) │
| |
| ├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┼─┴─┴─┴─┴─┴─ - - - ───┴─┴─┴─┴─┴─┤
| |
| │15 разряды слова 2 1 0│ │
| |
| │ 1-ое слово (2 байта) │ 2-ое, 3-е и 4-ое слова(6 байт)│
| |
| | |
| Рис.26. Представление числа двойной точности
| |
| | |
| Как же перевести число из привычного для нас десятичного вида в
| |
| двоичное представление числа двойной точности ?
| |
| Для этого берется исходное число и делится на 2 до тех пор, пока
| |
| его целая часть не будет равна 1.
| |
| Если исходное число меньше 1, то вместо деления производится
| |
| умножение на 2 до тех пор, пока целая часть не станет равна 1. Затем
| |
| дробная часть числа переводится в двоичный код - мантисса готова. 201
| |
| (восьмеричное) плюс (или минус, если производилось умножение)
| |
| количество делений или умножений на 2 - получим порядок числа.
| |
| Осталось "скомпоновать" число: последовательно слева направо
| |
| записываются знак (0 - для знака "+", 1 - для знака "-"), порядок,
| |
| мантисса. Остальные биты мантиссы заполняются нулями или мантисса
| |
| укорачивается справа так, чтобы общая длина числа равнялась 64 битам.
| |
| Рассмотрим несколько примеров перевода десятичных чисел в двоичные
| |
| числа двойной точности:
| |
| | |
| Пример 1: Исходное число: 9.5 . Делим на 2:
| |
| | |
| 9.5
| |
| 4.75 - результат после 1-го деления:
| |
| 2.375 - после 2-го деления;
| |
| 1.1875 - после 3-го деления.
| |
| | |
| Дробная часть числа, равная 0.1875 переводится в двоичный код
| |
| посредством последовательного умножения на 2. При этом если после
| |
| умножения число стало больше 1, то целая 1 отбрасывается.
| |
| | |
| 0.1875 - умножается на 2;
| |
| 0.375 - умножается на 2;
| |
| 0.75 - умножается на 2:
| |
| 1.5 - отбрасывается 1 и умножается на 2:
| |
| 1 - все.
| |
| | |
| Тогда двоичный код мантиссы - 0011 (последовательно сверху вниз
| |
| переписывается первый столбец цифр, кроме первого 0). Было произведено
| |
| 3 деления на 2, поэтому порядок числа равен 201 + 3 = 204 (числа
| |
| восмеричные) или 10000100 (двоичное). Осталось "скомпоновать" число:
| |
| так как число положительное, то 63-ий бит равен 0, тогда число имеет
| |
| следующий вид в двоичном коде:
| |
| | |
| 0 10000100 0011 000000000000000000000000000000000000000000000000000.
| |
| | |
| Если X - адрес числа, то код этого числа сохраняется по словам памяти
| |
| следующим образом:
| |
| | |
| Адреса: Содержимое:
| |
| X 41030 (восьмеричное)
| |
| X+2 0
| |
| X+4 0
| |
| X+6 0
| |
| | |
| Пример 2: Исходное число: -13.25. Отмечаем, что оно отрицательное,
| |
| и все остальные операции проделываем с его абсолютным значением. Делим
| |
| на 2:
| |
| 13.25
| |
| 6.625
| |
| 3.3125
| |
| 1.65625
| |
| | |
| Берем дробную часть числа 0.65625 и переводим в двоичный код:
| |
| | |
| 0.65625
| |
| 1.3125
| |
| 0.625
| |
| 1.25
| |
| 0.5
| |
| 1
| |
| | |
| Получаем 10101. Порядок равен 201+3=204 (10000100).
| |
| Тогда число в двоичном коде будет равно:
| |
| | |
| 1100001001010100000000000000000000000000000000000000000000000000
| |
| | |
| или четыре слова: 141124,0,0,0 в восьмеричном виде.
| |
| | |
| Пример 3: Исходное число: 0.0234375. Умножаем на 2:
| |
| | |
| 0.0234375
| |
| 0.046875
| |
| 0.09375
| |
| 0.1875
| |
| 0.375
| |
| 0.75
| |
| 1.5
| |
| | |
| Переводим дробную часть числа 1.5 равную 0.5 в двоичный код: это будет
| |
| 1. Порядок равен 201-6=173 (числа восьмеричные). Знак - 0 ("+"). Вид
| |
| числа в двоичном коде:
| |
| | |
| 0011110111000000000000000000000000000000000000000000000000000000
| |
| | |
| или четыре слова: 36700,0,0,0 в восьмеричном виде.
| |
| | |
| Как же теперь использовать наши умения ? Сначала надо поближе
| |
| познакомиться с тем, как Бейсик транслирует свою программу.
| |
| Исходная программа на Бейсике после ее запуска командой RUN
| |
| преобразуется в последовтельность адресов подпрограмм, реализующих
| |
| соответствующие операторы Бейсика, и исходных данных: констант,
| |
| адресов переменных и так далее [8]. Эти подпрограммы, как и сам
| |
| транслятор, делающий такое преобразование, зашиты (записаны) в ПЗУ.
| |
| После того, как указанная последовтельность (ее называют "шитым
| |
| кодом") получена в ОЗУ, в регистр R4 помещается адрес начала
| |
| последовательности, и командой "JMP @(R4)+" начинается обращение к
| |
| подпрограмме, адрес начала которой записан в указанной
| |
| последовательности первым. Передача управления от одной подпрограммы к
| |
| другой осуществляется также по команде "JMP @(R4)+" , содержащейся в
| |
| конце каждой подпрограммы.
| |
| Если в программе на языке ассемблера программисту необходимо
| |
| получить значение какой-либо функции (или арифметической операции), то
| |
| он может организовать обращение к готовым подпрограммам, зашитым в
| |
| ПЗУ. Далее под словом "операция" подразумевается арифметическая
| |
| операция или функция, а под словом "операнд" - операнд арифметической
| |
| операции или аргумент функции.
| |
| В таблице 19 приводится список адресов подпрограмм, при обращении к
| |
| которым вычисляется результат соответствующей функции (или
| |
| арифметической операции).
| |
| Операнды и результаты операций - числа двойной точности.
| |
| | |
| Таблица 19. Адреса подпрограмм Бейсика
| |
| ┌─────────────────────────┬───────────────┬───────────────┐
| |
| │ Арифметические операции │ Адреса │ Количество │
| |
| │ и функции │ подпрограмм │ операндов │
| |
| ├─────────────────────────┼───────────────┼───────────────┤
| |
| │ + (сложение) │ 167144 │ 2 │
| |
| │ - (вычитание) │ 167124 │ 2 │
| |
| │ / (деление) │ 170776 │ 2 │
| |
| │ * (умножение) │ 170210 │ 2 │
| |
| │ SQR │ 171350 │ 1 │
| |
| │ SIN │ 173614 │ 1 │
| |
| │ COS │ 173566 │ 1 │
| |
| │ TAN │ 174306 │ 1 │
| |
| │ ATN │ 174434 │ 1 │
| |
| │ EXP │ 171762 │ 1 │
| |
| │ LOG │ 173052 │ 1 │
| |
| │ FIX │ 176212 │ 1 │
| |
| │ INT │ 176340 │ 1 │
| |
| │ RND │ 175176 │ 1 │
| |
| │ подпрограмма преобразо- │ 166760 │ 1 │
| |
| │ вания результата в │ │ │
| |
| │ целый тип │ │ │
| |
| └─────────────────────────┴───────────────┴───────────────┘
| |
| | |
| Необходимо помнить, что для нормальной работы подпрограмм,
| |
| указанных в таблице 19, область памяти с адресами от 2000 до 4000
| |
| должна быть свободной (эта область - область системных переменных
| |
| Бейсика).
| |
| Предлагаем Вашему вниманию небольшую подпрограмму, которая может
| |
| облегчить Вам вызов нужных подпрограмм Бейсика.
| |
| Для вызова нужной подпрограммы в регистрах должны быть подготовлены
| |
| следующие данные:
| |
| R0 - число операндов (1 или 2);
| |
| R1 - адрес первого операнда;
| |
| R2 - адрес второго операнда (для операций с двумя операндами.
| |
| При операциях с одним операндом значение несущественно);
| |
| R3 - адрес подпрограммы операции (из табл.19);
| |
| R5 - адрес результата.
| |
| Эта вспомогательная подпрограмма работает аналогично транслятору с
| |
| Бейсика после команды RUN - формирует требуемый для вызова нужной
| |
| подпрограммы шитый код и передает ему управление.
| |
| Последовательность адресов подпрогрмм и данных (шитый код)
| |
| начинается с адреса A.
| |
| | |
| FUN: MOV R0,-(SP) ; сохранение
| |
| MOV R1,-(SP) ; содержимого
| |
| MOV R2,-(SP) ; регистров
| |
| MOV R3,-(SP) ; в стеке;
| |
| MOV R4,-(SP) ;
| |
| MOV R5,-(SP) ;
| |
| MOV #A,R4 ; последовательность адресов
| |
| ; начинается с адреса А;
| |
| MOV #156170,(R4)+ ; адрес подпрограммы пересылки в стек;
| |
| MOV R1,(R4)+ ; адрес первого операнда;
| |
| CMP R0,#1 ; если операция с одним операндом,
| |
| BEQ C ; то идти на метку C;
| |
| MOV #156170,(R4)+ ; засылка в стек второго операнда;
| |
| MOV R2,(R4)+ ; адрес второго операнда;
| |
| C: MOV R3,(R4)+ ; адрес нужной подпрогрммы записы-
| |
| ; вается в последовательность адресов;
| |
| CMP R3,#166760 ; если это не подпрограмма перевода
| |
| BNE G ; вещественного в целое, идти на G;
| |
| MOV #156350,(R4)+ ; подпрограмма пересылки слова из стека
| |
| BR D ; (результат целого типа);
| |
| G: MOV #156334,(R4)+ ; либо пересылка вещественного числа
| |
| D: MOV R5,(R4)+ ; из стека по адресу, указанному в R5;
| |
| MOV #B,(R4)+ ; организовать выход из шитого кода;
| |
| MOV #A,R4 ; запустить шитый код на выполнение;
| |
| JMP @(R4)+ ;
| |
| B: MOV (SP)+,R5 ; восстановление
| |
| MOV (SP)+,R4 ; содержимого
| |
| MOV (SP)+,R3 ; регистров
| |
| MOV (SP)+,R2 ; из стека
| |
| MOV (SP)+,R1 ;
| |
| MOV (SP)+,R0 ;
| |
| RTS PC ; возврат из подпрограммы
| |
| A: .+22
| |
| | |
| По команде "MOV #156170,(R4)+" в эту последовательность
| |
| записывается адрес подпрограммы, производящей пересылку значения
| |
| переменной в стек, а по команде "MOV R1,(R4)+" - адрес самой
| |
| переменной, указанный в R1.
| |
| Аналогично засылается в стек второй операнд, если нужен.
| |
| После выполнения любой арифметической подпрограммы результат
| |
| получается в стеке. Его необходимо оттуда извлечь и переслать по
| |
| адресу, заданному в R5. Для этого используется подпрограмма 156334,
| |
| пересылающая вещественное число (4 слова), либо 156350, пересылающая
| |
| одно слово, если результат целый.
| |
| Пример цепочечных вычислений:
| |
| | |
| ; Вычисляем выражение (4+7)*3.0625-1.25
| |
| MOV #2,R0 ;двухоперандная команда
| |
| MOV #AR1,R1 ;первое слагаемое
| |
| MOV #AR2,R2 ;второе слагаемое
| |
| MOV #167144,R3 ;адрес подпрограммы сложения
| |
| MOV #REZ,R5 ;адрес результата
| |
| JSR PC,FUN ; складываем
| |
| MOV R5,R1 ;результат используем
| |
| ;как первый сомножитель
| |
| MOV #AR3,R2 ;второй сомножитель
| |
| MOV #170210,R3 ;адрес подпрограммы умножения
| |
| JSR PC,FUN ; умножаем (результат там же - в REZ)
| |
| MOV R5,R1 ;результат используем как уменьшаемое
| |
| MOV #AR4,R2 ;вычитаемое
| |
| MOV #167124,R3 ;адрес подпрограммы вычитания
| |
| JSR PC,FUN ; вычитаем
| |
| ; Печатаем полученный результат на дисплей
| |
| ADD #10,R5 ;засылаем результат в стек;
| |
| MOV -(R5),-(SP)
| |
| MOV -(R5),-(SP)
| |
| MOV -(R5),-(SP)
| |
| MOV -(R5),-(SP)
| |
| JSR PC,@#164710 ;вызываем подпрограмму перевода
| |
| ;числа в символьную строку;
| |
| ADD #4,SP ;восстанавливаем стек;
| |
| MOV #3027,R1 ;адрес символьной строки
| |
| MOV #20000,R2 ;ограничитель строки - пробел
| |
| EMT 20 ;печатаем сформированную строку
| |
| ; Аргументы:
| |
| AR1: .#40600.#0.#0.#0 ;4.0
| |
| AR2: .#40740.#0.#0.#0 ;7.0
| |
| AR3: .#40504.#0.#0.#0 ;3.0625
| |
| AR4: .#40240.#0.#0.#0 ;1.25
| |
| REZ: .#0.#0.#0.#0 ;результат
| |
| | |
| 6.3. Использование системных переменных МОНИТОРа БК
| |
| | |
| Область ОЗУ в диапазоне адресов от 0 до 377 МОНИТОР БК использует
| |
| для хранения своих рабочих переменных (используются те адреса, которые
| |
| не заняты векторами прерывания, см.п.4.4.3). В этих переменных
| |
| указываются текущие режимы работы устройств, например, режимы работы
| |
| дисплея. Зная о назначении тех или иных переменных, можно добиться
| |
| таких эффектов, которые невозможны при "штатном" использовании
| |
| системного программного обеспечения.
| |
| Рассмотрим несколько примеров использования системных ячеек.
| |
| Примеры даны на Бейсике и на языке ассемблера.
| |
| | |
| Таблица 20. Системные переменные
| |
| ┌─────┬─────┬─────────────────────────────────────────────────┐
| |
| │Адрес│Длина│ Назначение │
| |
| │ │байт │ │
| |
| ├─────┼─────┼─────────────────────────────────────────────────┤
| |
| │ 040 │ 1 │ Режим 32/64 (0 - режим "64", 377 - режим "32") │
| |
| │ 041 │ 1 │ Инверсия экрана (0 - выкл., 377 - вкл.) │
| |
| │ 042 │ 1 │ Режим расширенной памяти (0 - выкл., 377 - вкл.)│
| |
| │ 043 │ 1 │ Регистр (0 - LAT, 200 - РУС ) │
| |
| │ 044 │ 1 │ Подчеркивание (0 - выкл., 377 - вкл.) │
| |
| │ 045 │ 1 │ Инверсия символа (0 - выкл., 377 - вкл.) │
| |
| │ 046 │ 1 │ Режим ИСУ (0 - выкл., 377 - вкл.) │
| |
| │ 047 │ 1 │ Режим БЛР (0 - выкл., 377 - вкл.) │
| |
| │ 050 │ 1 │ Режим ГРАФ (0 - выкл., 377 - вкл.) │
| |
| │ 051 │ 1 │ Режим ЗАП (0 - выкл., 377 - вкл.) │
| |
| │ 052 │ 1 │ Режим СТИР (0 - выкл., 377 - вкл.) │
| |
| │ 053 │ 1 │ Режим 32/64 в служебной строке (0-"64",377-"32")│
| |
| │ 054 │ 1 │ Подчеркивание в служ. строке (0-выкл., 377-вкл.)│
| |
| │ 055 │ 1 │ Инверсия служ. строки (0 - выкл., 377 - вкл.) │
| |
| │ 056 │ 1 │ Гашение курсора (0 - выкл., 377 - вкл.) │
| |
| │ 104 │ 1 │ Код последнего введенного символа │
| |
| │ 112 │ 10 │ Положения табуляторов (побитно при режиме "64") │
| |
| │ 126 │ 2 │ Адрес буфера программируемого ключа К10 │
| |
| │ 130 │ 2 │ Адрес буфера программируемого ключа К1 │
| |
| │ 132 │ 2 │ Адрес буфера программируемого ключа К2 │
| |
| │ 134 │ 2 │ Адрес буфера программируемого ключа К3 │
| |
| │ 136 │ 2 │ Адрес буфера программируемого ключа К4 │
| |
| │ 140 │ 2 │ Адрес буфера программируемого ключа К5 │
| |
| │ 142 │ 2 │ Адрес буфера программируемого ключа К6 │
| |
| │ 144 │ 2 │ Адрес буфера программируемого ключа К7 │
| |
| │ 146 │ 2 │ Адрес буфера программируемого ключа К8 │
| |
| │ 150 │ 2 │ Адрес буфера программируемого ключа К9 │
| |
| │ 153 │ 1 │ Тип операции в режиме ГРАФ (0 - СТИР, 1 - ЗАП) │
| |
| │ 154 │ 2 │ Унитарный код положения графического курсора │
| |
| │ 160 │ 2 │ Абсолютный адрес курсора в ОЗУ экрана │
| |
| │ 162 │ 2 │ Константа смещения одного алфавитно-цифрового │
| |
| │ │ │ символа относительно другого │
| |
| │ 164 │ 2 │ Длина ОЗУ экрана в символах │
| |
| │ 176 │ 2 │ Координата Х последней графической точки │
| |
| │ 200 │ 2 │ Координата Y последней графической точки │
| |
| │ 202 │ 2 │ Начальный адрес ОЗУ экрана │
| |
| │ 204 │ 2 │ Адрес начала информационной части экрана │
| |
| │ │ │ минус 40000 │
| |
| │ 206 │ 2 │ Длина ОЗУ экрана в байтах │
| |
| │ 210 │ 2 │ Длина информационной части экрана │
| |
| │ 212 │ 2 │ Код цвета фона на экране │
| |
| │ 214 │ 2 │ Код цвета символа на экране │
| |
| │ 216 │ 2 │ Код цвета фона в служебной строке │
| |
| │ 220 │ 2 │ Код цвета символа в служебной строке │
| |
| │ 260 │ 2 │ Адрес подпрограммы, выполняемой при прерывании │
| |
| │ │ │ по вектору 60. Если 0, то ничего не выполняется │
| |
| │ 262 │ 2 │ Если 0, то код клавиши "ВК" равен 12, иначе 15 │
| |
| │ 264 │ 2 │ Начальный адрес загруженной программы │
| |
| │ 266 │ 2 │ Длина загруженной программы │
| |
| └─────┴─────┴─────────────────────────────────────────────────┘
| |
| Примечание: В буфере программируемого ключа записана длина
| |
| соответствующего ключа (в символах), далее - сами символы.
| |
| | |
| Пример 1. Печать красными буквами на синем фоне:
| |
| | |
| 10 POKE &O214,-1 MOV #177777,@#214 ;красный цвет;
| |
| 20 POKE &O212,&O52525 MOV #52525,@#212 ;синий фон;
| |
| 30 ?"Приветик!" MOV #TXT,R1 ;печатаем
| |
| CLR R2 ;текст
| |
| EMT 20 ;
| |
| HALT
| |
| TXT: .A:Приветик!
| |
| | |
| Пример 2. Запись символов в служебную строку:
| |
| | |
| 10 POKE &O160,PEEK(&O204)+&O36100 MOV @#204,@#160
| |
| ADD #36100,@#160
| |
| 20 ? "текст" MOV #TXT,R1
| |
| CLR R2
| |
| EMT 20
| |
| HALT
| |
| TXT: .A:текст
| |
| | |
| Примечание: эта последовательность проходит только в программе;
| |
| если попытаться проделать ее в непосредственном режиме, то после
| |
| оператора POKE ... Бейсик напишет "Ок" в служебной строке и курсор
| |
| вернется на свое прежнее место.
| |
| | |
| Пример 3. Печать "в столбик":
| |
| | |
| 10 X=PEEK(&O162) MOV @#162,R3 ;запомнить старый режим
| |
| 20 POKE &O162,&O100 MOV #100,@#162
| |
| 30 ?"текст" MOV #TXT,R1
| |
| CLR R2
| |
| EMT 20
| |
| 40 POKE &O162,X MOV R3,@#162 ;восстановить режим
| |
| HALT
| |
| TXT: .A:текст
| |
| | |
| </pre>
| |
|
| |
|
| [[Категория:Программирование на БК-0010-01]] | | [[Категория:Программирование на БК-0010-01]] |