Программирование в машинных кодах и на языке ассемблера 1993 г.

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


4.6. Практические приемы работы с калькулятором.

В части 1 мы достаточно подробно осветили принципы работы встроенного калькулятора "Спектрума", а в "Справочнике" (часть 3) дали полную сводку команд калькулятора с указанием особенностей их применения. Система команд калькулятора достаточно проста, но вместе с тем при практическом программировании начинающий пользователь упирается в проблему. А как организовать взаимосвязь трех основных инструментов "Спектрума" - БЕЙСИКа, машинного кода и калькулятора?

Если связь между БЕЙСИКом и машинным кодом осуществляется достаточно просто через выделение области программных переменных, к которым БЕЙСИК обращается через PEEK, POKE, а машинный

65DA C1 POP BC

65DB E1 POP HL

65DC B7 OR A

65DD C9 RET

65DE ERROR C1 POP BC

65DF D1 POP DE

65E0 37 SCF

65E1 C9 RET

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

Вы уже должны знать, что вся работа калькулятора строится вокруг специальной области памяти - стека калькулятора. Если у Вас есть инструмент для того, чтобы из БЕЙСИКа помещать переменные на стек калькулятора (не путать с машинным стеком процессора), то и проблем для Вас не будет. Логика работы такая:

- поместить данные из БЕЙСИКа на стек калькулятора;

- перейти в машинный код;

- перейти в калькулятор;

- обработать данные;

- выйти из калькулятора;

- войти в БЕЙСИК

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

Рассмотрим простейшую БЕЙСИК-строку: LET P = Q + USR addr. Вы, конечно, понимаете, что по такой команде будет вызвано исполнение программы в машинных кодах, которая записана, начиная с адреса addr. А уж что будет дальше - это вопрос, который зависит от того, что написано в этой машинокодовой программе. Может быть после нее Вы в БЕЙСИК и не вернетесь, и до вычисления Q + .... дело и не дойдет. Зато вместе с запуском машинного кода вышеуказанная БЕЙСИК-строка делает еще одно дело. Она помещает содержимое переменной Q на вершину стека калькулятора!!! И, конечно, же делает это в пятибайтной форме. Если теперь Вы организуете машинный код с адреса addr так, чтобы он переходил в калькулятор и производил обработку данных, помещенных на стек, то проблема решена.

Рассмотрим конкретный пример. Допустим, Вам надо вычислить выражение P = SQR(Q+1). Допустим, мы расположим наш машинный код, начиная с адреса 30000.

Дайте команду LET P = Q + USR 30000. Q поместится на вершину стека калькулятора, и запустится машинный код, начинающий-

КОД МНЕМОНИКА СТЕК

АДРЕС

30000

30001

30002

EF RST 28 Q

Q, 1

0F

Q+1

A1 stk one

add

КОММЕНТАРИИ Включение калькулятора, Q уже находится на стеке Команда калькулятора, помещающая на стек единицу Команда калькулятора "сложение"

30003

28

sqr

SQR(Q+1

Извлечение

квадратного корня

30004

38

end calc

Выключение

калькулятора

30005

C9

RET

Возврат в

БЕЙСИК.

А как быть, если надо передать последовательность данных? А если надо передать символьный стринг?

В этом случае можно воспользоваться оператором БЕЙСИКа DEF FN <имя> () . Он служит для объявления функции пользователя, которая в дальнейшем может вызываться на исполнение командой FN <имя> () . В круглых скобках может стоять список параметров функции пользователя, отделенных друг от друга запятыми. Задание и вызов функции пользователя выглядят по-разному в зависимости от того, являются ли они числовыми или стринговыми. Например, они могут выглядеть так:

DEF FN A(K,L,M,C$,D$...) - числовая функция DEF FN A$ (K,L,M,C$,D$. . . ) - символьная функция Аналогично выглядят и обращения к ним: FN A(K,L,...); FN A$(K,L,.. .)

Чтобы двигаться дальше, нам необходимо знать, как хранятся в БЕЙСИКе параметры функций пользователя. Для этого выделяется специальная область памяти, на которую указывает системная переменная DEFADD, имеющая длину два байта и адреса 23563, 23564. Найти адрес, с которого начинается размещение параметров функции пользователя, несложно:

PRINT PEEK 23563 + 256*PEEK 23564

Каждый параметр числовой функции пользователя занимает 8 байтов, а стринговой - девять байтов, и хранятся они там в следующем формате:

Для числовой функции: Байт 1 - Имя функции (один символ) ; Байт 2 - код 0Е;

Байт 3... 7 - значение параметра в пятибайтной форме; Байт 8 - код 29, если этот параметр последний, если т - код 2С;

Для символьной функции: Байт 1 - Имя функции (один символ) ; Байт 2 - код 2 4; Байт 3 - код 0Е;

Байт 4... 8 - значение параметра в пятибайтной форме; Байт 9 - код 29, если этот параметр последний, если нет - код 2С.

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

DEF FN A(......) = USR addr - для работы с числами;

DEF FN A$(......) = P$ AND USR addr - для работы со

стрингами.

И теперь Ваша задача организовать, начиная с адреса addr такую процедуру в машинных кодах, которая прочитает передаваемое в качестве параметра функции пользователя число в пятибайт-ной форме, поместит его на стек и перейдет к переброске следующего числа, если данный параметр не является последним. Например, такая процедура может выглядеть так:

REP INC HL

LD A,(HL)

CP 0E

JR Z, NUMB

LD HL,(DEFADD)

2A0B5C

23

FE0E 2801 23

23

INC HL

NUMB INC HL

указание на адрес параметров функции пользователя DEF FN теперь HL указывает на 2-й байт, который 0Е или 24 проверка этого байта

Вперед, если функция числовая Если символьная, то лишний байт надо пропустить Теперь HL указывает на пятибайтную форму

Вызов процедуры ПЗУ STACK-NUM, которая отправляет пятибайтное число на стек калькулятора

Проверка на то, что этот параметр последний Возврат на повтор, если не так Выход в БЕЙСИК.

7E

FE2C

2 8F0 C9

LD A, (HL)

CP 2C

JR Z,REP RET

Можно передавать также и переменные из БЕЙСИКа на стек калькулятора. Первое, что надо сделать - это поместить имя переменной в качестве стринга на стек калькулятора, а затем использовать команду калькулятора "val" для числовой переменной или "val$" для символьной. Однако надо помнить, что обе эти команды являются зависимыми от регистра В процессора, т.е. еще находясь в машинном коде, до команды RST 28, надо в регистр В поместить 1D для команды "val" или 18 для команды "val$".

Чтобы поместить имя переменной на вершину стека в качестве стринга, можно поместить туда в упакованной форме код первого символа, затем конвертировать его в символ командой калькулятора chr$, затем тоже для второго символа, слить их воедино командой s_add и т.д. в зависимости от длины имени переменной. Рассмотрим два примера - для числовой переменной и для строковой .

Передача числовой переменной.

МНЕМОНИКА LD B,1D

EF RST 28

3440В00041 s t k_data 41

2F chr$

МАШ.КОД 0 61D

3В execute b

38

end ca l c

КОММЕНТАРИЙ

Предварительная настройка регистра B с целью последующего вызова команды калькулятора val Включение калькулятора

Поместить на стек код буквы А(41 HEX) Преобразование кода 41 в стринг "А" Выполнение команды, код которой записан в регистре В, т. е. преобразование переменной А в ее числовое значение Выключение калькулятора

МНЕМОНИКА LD B,18

RST 28

3440В00042 stk data 42

chr$

3440B00024 stk data 24

chr$

s_add

execute_B

end calc

МАШ. КОД 0618

EF

2F

2F 17 3В

38

КОММЕНТАРИИ

Предварительная настройка регистра B с целью последующего вызова команды калькулятора val$ Включение калькулятора

Поместить на стек код буквы B(42 HEX) Преобразование кода 42 в стринг "B" Помещение на стек кода знака $ Преобразование кода 24 в стринг "$" Слияние стрингов в стринг "В$" Преобразование имени стринга "B$" в его значение, Выключение калькулятора

Пусть имя переменной B$.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Тема ОС - Многозадачная ОС и нe только: размышления Vitamin'a.
General Sound - У самого автоpа пpодается по 185/205 тыp.
Почтовый ящик - доска обьявлений.
Hackers-Top 98 - Breeze: отчет с Беларуской тусовки на которой почти никого не было, но было весело.
7 Origins - Семерка лучших origin'ов-мудрых и не очень выражений.

В этот день...   19 марта