ZX-Ревю 1993 №1-2 1992 г.

Форум - русификация резидентной процедурой.


FORUM

Русификация резидентной процедурой

Тема русификации это, пожалуй, вечная тема для "Спектрума". Пока что не существует способ (и будет ли когда-нибудь существовать), который бы был достаточно универсален и хорош для всех. Многие программисты ломают голову над решением этой проблемы. В этот раз интересное письмо пришло к нам от Александра Еременко из Свердловска. Он прислал программу в машинных кодах, позволяющую переключать символьный набор одновременным нажатием двух клавиш (SYMBOL SHIFT)+(ENTER). При первом нажатии включается загруженный в ОЗУ символьный набор, а при повторном нажатии - опять символьный набор из ПЗУ. Самое главное, что такое переключение можно сделать в любой момент как пишет Александр, неважно, где Вы работаете, в режиме редактирования Бейсик-строк или в программе, все равно можно производить переключение шрифта.

Нам понравилась идея уважаемого корреспондента и мы даем ее всем читателям, снабдив собственными комментариями и постаравшись немного ее развить.

Вот эта программа:

CD7C

3ECB

LD

A,#CB

CD7E

2120CD

LD

HL, #CD20

CD81

36CD

LD

(HL),#CD

CD83

2B

DEC

HL

CD84

BC

CP

H

CD85

20FA

JR

NZ,#CD81

CD87

3ECC

LD

A,#CC

CD89

ED47

LD

I,A

CD8B

F3

DI

CD8C

ED5E

IM

2

CD8E

FB

EI

CD8F

C9

RET

CD90

C5

PUSH

BC

CD91

D5

PUSH

DE

CD92

E5

PUSH

HL

CD93

F5

PUSH

AF

CD94

3E7F

LD

A,#7F

CD96

DBFE

IN

A,(#FE)

CD98

FEFD

CP

#FD

CD9A

202A

JR

NZ,#CDC6

CD9C

3EBF

LD

A,#BF

CD9E

DBFE

IN

A,(#FE)

CDA0

FEFE

CP

#FE

CDA2

2022

JR

NZ,#CDC6

CDA4

3A10CD

LD

A,(#CD10)

CDA7

3C

INC

A

CDA8

3210CD

LD

(#CD10),A

CDAB

CB47

BIT

0,A

CDAD

2805

JR

Z,#CDB4

CDAF

01003C

LD

BC,#3C00

CDB2

1803

JR

#CDB7

CDB4

01D0CC

LD

BC,#CCD0

CDB7

21365C

LD

HL, #5C36

CDBA

71

LD

(HL),C

CDBB

23

INC

HL

CDBC

70

LD

(HL),B

CDBD

219701

LD

HL,#0197

CDCO

116400

LD

DE, #0064

CDC3

CDB503

CALL

#03B5

CDC6

F1

POP

AF

CDC7

E1

POP

HL

CDC8 D1

CDC9 C1

CDCA C33800

CDCD C39OCD

CDD0 ......

POP DE POP BC JP #0038 JP #CD90 символьный набор

Как видим, принцип действия этой программы основан на использовании прерываний второго рода IM 2. Подробнее о прерываниях Вы можете прочитать в нашей книге, посвященной программированию в машинных кодах. Там мы рассказывали, что на использовании прерывания первого рода основан основной режим работы "Спектрума". В этом режиме (если он разрешен командой EI) всегда в ответ на прерывание, поступающее по шине INT (а это происходит 50 раз в секунду), выполняется обращение по адресу 0038H. Процедура, расположенная с этого адреса, обеспечивает сканирование клавиатуры в поисках нажатой клавиши.

Теперь о прерывании второго рода. В компьютерах иных систем, собранных на базе процессора Z-80, для программиста существует возможность самому задать адрес, по которому будет происходить обработка этого прерывания. Он определяется следующим образом. Старший байт поступает из регистра I процессора (он так и называется "вектор прерываний"), а младший байт должно выдавать периферийное устройство, от которого получено прерывание. В паре ячеек, адрес которых определен таким образом, хранится адрес процедуры, обслуживающей прерывание. Программ, обслуживающих такое прерывание может быть 128, так как старший байт определен регистром I, а младший байт -это 256 ячеек, в которых можно записать 128 двухбайтных адресов. В "Спектруме" режим прерываний второго рода не используется для взаимодействия с периферийными устройствами, поэтому появляется возможность использовать этот режим в своих целях.

Теперь конкретно о предложенной программе. Вначале выполняется инициализирующая процедура. Она запускается с адреса загрузки, то есть CD7CH (52604). При этом происходит следующее. Область, начиная с СС00Н, и кончая адресом CD20H заполняется кодом CD. Затем в регистре I процессора задается старший байт адреса ячейки памяти, в которой хранится адрес обслуживающей процедуры CC. Далее происходит включение режима прерываний второго рода и выполняется возврат в вызывающую программу.

Что же происходит при получении сигнала на прерывание, (который, как мы помним, приходит 50 раз в секунду) Несмотря на то что неопределен младший байт ячейки с адресом обслуживающей программы, обратившись по любому адресу со старшим байтом CC (то есть начиная СС00Н и кончая CCFFH), получим один и тот же адрес обслуживавшей программы CDCDH, так как вся эта область заполнена кодом CD.

По адресу CDCDH (см. листинг программы) видим безусловный переход на адрес СD90Н. Это и есть начало программы, обслуживающей полученное прерывание. Перед началом выполнения каких либо действий, на стеке запоминается содержимое всех регистров процессора, которые могут быть изменены при работе обслуживающей процедуры. Затем выполняется сканирование двух полурядов клавиатуры (о том, как производится опрос клавиш, Вы также можете прочитать в нашей книге, посвященной программированию в машинных кодах). Вначале проверяется нажатие клавиши SYMBOL SHIFT и, если она не нажата, то сразу переход на завершение процедуры обработки прерывания. Если SYMBOL SHIFT нажата, то проверяется факт нажатия ENTER. Если нет, то также переход на завершение процедуры, а если и эта клавиша нажата, то происходит дальнейшая работа.

Проверяется содержимое ячейки, определяющей включение одного или другого символьного набора это ячейка CD10H. От значения младшего бита этой ячейки (четное число или нечетное) зависит выбор одного из двух символьных наборов, при этом происходит увеличение на единицу содержимого этой ячейки (то есть подготовка к включению в следующий раз противоположного символьного набора). Соответствующее значение системной переменной CHARS пересылается при помощи регистра ВС, в область системных переменных, в ячейку 5С36Н. Далее происходит вызов подпрограммы BEEPER из

ПЗУ (параметры: тон и длительность звукового сигнала задаются в регистрах HL и DE). Звуковой сигнал свидетельствует о произошедшем переключении символьного набора.

Далее выполняется финишная процедура: восстановление со стека прежних значений регистров процессора и безусловный, переход на адрес 0038H. Как это должно быть в случае обработки прерываний первого рода, с этого места работа компьютера совпадает с традиционной.

При реализации этого метода следует помнить, что символьный набор располагается сразу же за самой программой, с адреса CDD0H (52688). При этом системная переменная CHARS равна CCD0H. Но Вы можете расположить символьной набор там, где это Вам удобно, изменив значение CHARS в ячейках CDB5H и CDB6H. Кроме того, оба переключаемых символьных набора могут находиться в ОЗУ, и Вы можете поочередно переводить на любой из них. Для этого значение системной переменной chars для второго символьного набора должно быть задано в ячейках CDB0H и CDB1H. Следует также помнить, что для работы программы необходима область кодов с адреса СС00Н (52224), то есть перед стартом инициализирующей процедуры (RANDOMIZE U5R 52604) надо зарезервировать это место, изменив RAMTOP командой CLEAR 52223.

Следует также учитывать тот факт, что раз уж мы работаем с прерываниями второго рода, призванными обслуживать периферийные устройства, то работа с последними, например с дисководом, после инициализации блока кодов будет невозможна. Для работы с периферией необходимо восстановить традиционный порядок работы. Об этом еще будет разговор ниже.

Вообще нам очень понравилась идея, заложенная в этой программе и тот изящный способ, при помощи которого эта идея реализуется. Для того, чтобы поглубже "прочувствовать" действие этой программы, наберите простую демонстрационную программку на Бейсике:

1 GO TO 100

2 CLEAR 52223: LOAD "rus"CODE 52604: LOAD "cbr" CODE 52688

3 RANDOMIZE USR 52604

4 RUN

100 PRINT "Press <S.S.>+<ENTER> for control"": PAUSE 0

200 FOR a=32 TO 127; PRINT CHR$ a;: PAUSE 1: NEXT a: GO TO 200

После набора запустите её с первой строки командой RUN и внимательно понаблюдайте за реакцией компьютера. Хотя ничего неожиданного сейчас произойти не должно (компьютер не подпрыгнет, он по-прежнему останется на своем месте), но все-таки остановимся на происходящем подробнее. Сразу после старта на экране появится надпись: "нажмите <S.S.>+<ENTER> для управления" и программа остановится на PAUSE 0, ожидая нажатия клавиши. Попробуйте нажать указанную комбинацию клавиш. Пауза прервется (SYMBOL SHIFT здесь ни при чем, сработало нажатие ENTER) и начнется распечатка символьного набора из ПЗУ. Когда заполнится весь экран, появится привычный запрос: "scroll?". Попробуйте опять нажать SYMBOL SHIFT + ENTER. Вывод символов на экран будет продолжен.

Теперь остановите программу нажатием BREAK и запустите ее со второй строки (с которой должен происходить автостарт) RUN 2. При этом загрузите (заготовленные за ранее) исследуемый блок кодов "rus" и любой имеющийся у Вас символьный набор "chr" (лучше "утолщенный" или стилизованный, так будет нагляднее). После загрузки произойдет инициализация программы в кодах, после чего Бейсик программа запустится с начала, как это делали Вы командой RUN. Сравните реакцию компьютера. После появления надписи в верхней строке, нажмите SYMBOL SHIFT + ENTER. Вы услышите короткий звуковой сигнал, свидетельствующий о нажатии на клавиши, но больше ничего на экране не изменилось: пауза не прервалась, как раньше. То есть, указанная комбинация клавиш теперь не влияет никаким образом на работу Бейсик-программы. Теперь она воспринимается именно как SYMBOL SHIFT + ENTER, а не как просто ENTER. Прервите паузу нажатием на любую клавишу, и Вы увидите, что на экран выводится новый символьный набор, то есть произошло переключение. Пока экран заполняется, можете попробовать несколько раз нажать SYMBOL SHIFT + ENTER и убедиться в том, что происходит переключение символьных наборов. Когда экран будет заполнен и появится запрос "scroll?", опять нажмите комбинацию клавиш. Кроме звукового сигнала, свидетельствующего о переключении символьных наборов, ничего не происходит. Для продолжения работы надо нажать, например, просто ENTER. Можно, таким образом, сделать вывод: приведенный блок кодов не оказывает никакого вмешательства в работу интерпретатора Бейсика, он только исправно выполняет то, что ему предписано - переключает символьные наборы.

Продолжаем наше исследование. Вызовите на редактирование 100 строку Бейсик-программы. Попробуем в кавычках напечатать текст, состоящий из символов разных символьных наборов. Для этого, находясь в середине текста, нажмите SYMBOL SHIFT + ENTER. Звуковой сигнал - переключение произошло, но на экране ничего не меняется до того момента, пока Вы не нажмете какую-нибудь клавишу. А происходит следующее. Весь текст редактируемой строки перерисовывается заново, причем символами нового символьного набора, отсюда второй вывод: нельзя при помощи этого блока кодов решить задачу совмещения символов разный символьных наборов внутри одного оператора PRINT, действительно, чудес ведь не бывает. Кодовый блок только переключает символьный набор, а текст, подлежащий выводу на экран, никак не изменяется, то есть каким было кодовое выражение строки текста, таким оно и осталось, таким и выводится на экран, только в новом символьном наборе. То же относится и к оператору INPUT. Нельзя при вводе текстовых выражений совместить русские и английские буквы.

И еще один вывод. Переключение символьного набора таким способом происходит только "вручную", то есть, если по алгоритму выполнения программы должно произойти переключение символьного набора, то оно должно быть выполнено, как обычно, изменением CHARS при помощи РОКЕ. Так что же, новый изящный метод переключения шрифтов не вносит ничего нового по существу проблемы? Видимо, такое заключение преждевременно. Существуют ситуации, где изложенный способ сможет оказать действительно неоценимую пользу. Например, программа "МОЗАИКА", которая опубликована в этом выпуске ZX-РЕВЮ на с. 1. Там переключение из текстового в графический режим происходит включением регистра CAPS LOCK, из-за чего существует ограниченное число псевдографических символов, только по числу малых букв латинского символьного набора - 26. Если переключать символьные наборы новым способом, то во сколько раз можно расширить графические возможности, а следовательно и привлекательность этой программы! Ведь все до одного 96 символов нового символьного набора можно отдать графическим образам, да и захватить еще часть первого символьного набора, как это сделано в "МОЗАИКЕ".

Другой пример. Вы набираете программу, в которой заведомо будет только русский текст (какой-нибудь тест или обучающая программа). И естественно, хотите для придания программе большей привлекательности, использовать русские заглавные и строчные буквы, используя загружаемый только русский символьный набор. При этом, если Вы набиваете текст программы, используя стандартный символьный набор ПЗУ, то легко можете допустить ошибки при наборе русского текста в операторах PRINT, так как набор ведется практически "вслепую". Если же Вы переключитесь на русский символьный набор, то сама Бейсик-программа, токены, имена переменных - все это станет "нечитаемым". Применение изложенного в этой статье приема позволит вам при наборе и отладке программы без труда переключаться с одного на другой символьные наборы в зависимости от того, что Вы в данный момент предпочитаете видеть.

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

что у нас получилось.

FBF4

3EFB

LD

A, #FB

FBF6

ED47

LD

I, A

FBF8

ED5E

IM

2

FBFA

C9

RET

FBFB

00

NOP

FBFC

ED56

IM

1

FBFE

C9

RET

FBFF

01FC

DEFB

#FTO1

FC01

C5

PUSH

BC

FC02

D5

PUSH

DE

FC03

E5

PUSH

HL

FC04

F5

PUSH

AF

FC05

3E7F

LD

A, #7F

FC07

DBFE

IN

A, (#FE)

FC09

FEFD

CP

#FD

FC0B

202D

JR

NZ,#FC3A

FC0D

3EBF

LD

A, #BF

FC0F

DBFE

IN

A, (#FE)

FC11

FEFE

CP

#FE

FC13

2025

JR

NZ,#FC3A

FC15

2132FC

LD

HL,#FC32

FC18

CB7E

BIT

7,(HL)

FC1A

2807

JR

Z, #FC23

FC1C

11003C

LD

DE, #3C00

FC1F

CBBE

RES

7,(HL)

FC21

1805

JR

#FC28

FC23

1158FB

LD

DE,#FB58

FC26

CBFE

SET

7,(HL)

FC28

21365C

LD

HL,#5C36

FC2B

73

LD

(HL),E

FC2C

23

INC

HL

FC2D

72

LD

(HL),D

FC2E

210002

LD

HL,#0200

FC31

117F00

LD

DE, #007F

FC34

CDB503

CALL

#03B5

FC37

00

NOP

FC38

00

NOP

FC39

00

NOP

FC3A

F1

POP

AF

FC3B

E1

POP

HL

FC3C

D1

POP

DE

FC3D

C1

POP

BC

FC3E

C33800

JP

#0036

Прежде чем начать пояснения, рассмотрим подробно карту памяти, тех областей, которые имеют значение для работы программы.

RAMTOP 64499

Программа в машинных 645 0 0

кодах (новый вариант) FBF4H

77 байт

Свободное место; для ра- 64577 боты программы не исполь FC41H зуется 23 байта

Символьный набор 64600

(любой по вкусу) FC58H

7 68 байт

UDG-графика, стандартно 653 68

расположенная здесь FF58H

168 байт

P_RAMT

Эта область памяти должна быть зарезервирована при старте Бейсик-программы, путем переустановки RAMTOP командой CLEAR 64499. Файл, содержащий блок кодов, начинается с адреса 64500 и включает в себя, в зависимости от конкретных задач, либо только программу в кодах (до адреса 64577), либо программу и символьный набор (заодно с 23-мя неиспользуемыми байтами), либо еще и блок UDG-графики (то есть по адрес 65535 включительно). Область памяти с адреса 64577 (23 байта) в работе программы не участвует, Вы можете использовать ее по своему усмотрению.

Инициализация выполняется командой RANDOMIZE USR 64500. С этого адреса (FBF4H) начинается инициализируемая процедура. Кстати сказать, нет необходимости заполнять почти 300 байт кодом для задания адреса обслуживавшей процедуры. Дело в том, что при существующей архитектуре "Спектрума" младший байт всегда будет равен FF. То есть, если в регистре I процессора задать, например FB, то при прерывании второго рода переход произойдет всегда на программу, адрес которой хранится в FBFFH. В этой паре ячеек (FBFF - младший байт, в FC00 - старший байт) находится адрес процедуры, обслуживающей прерывание второго рода. Читаем этот адрес (см. листинг программы): FC01.

Начало процедуры, расположенной по этому адресу точно такое же, как и в неполном варианте. Так же опрашивается нажатие интересующих клавишей, а дальше начинается отличие. Системной ячейкой, определяющей, какой символьный набор должен включиться, выбрана ячейка FC32H. Точнее, определяющим является 7 бит числа, находящегося там, (получается либо 7F, либо FF). В этой ячейке содержится параметр, задающий время звукового сигнала для подпрограммы BEEPER, вызываемой из ПЗУ. Таким образом, переключение на символьный набор из ОЗУ сопровождается длинным звуком, а обратное переключение на символьный набор из ОЗУ - коротким.

После вызова подпрограммы BEEPER, зарезервировано 3 свободных ячейки памяти. Здесь, при необходимости, можно организовать вызов каких-то дополнительных сервисных процедур, если это потребуется в будущем (вызов какой-нибудь подпрограммы: CALL ... или переход - JP ... - все это занимает 3 байта) далее - финишные операции и переход на адрес 0033H.

Кроме указанных отличий, новый вариант программы предусматривает возможность отключения режима прерываний второго рода, это необходимо делать прежде, чем, например, обращаться к дисководу. Иначе произойдет сбой, зависание или сброс компьютера. "Де-инициализация" или восстановление традиционного режима работы выполняется командой RANDOMIZE USR 64508. С этого адреса (FBFCH) расположена восстанавливавшая процедура. Здесь включается режим прерываний первого рода, восстанавливая исходный режим работы "Спектрума".

В заключение хочется поблагодарить Александра Еременко за присланную программу. Надеемся, что она подтолкнет и других читателей к решению насущных проблем оригинальными, нетрадиционными методами.




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Реклама - реклама и обьявления.
От редакции - в этом номере: содержание номера.
Реклама - обьявления о купле/продаже Спектрума и программ для него.
Предисловие - Наступил последний месяц лета.
Программинг - сборник кодов: Рисование окна с рамкой в цвете, обработка дисковых ошибок TR-DOS, универсальня процедура Scroll'a экрана.

В этот день...   20 апреля