Adventurer #02
16 марта 1996

Обмен опытом - Программирование на ассемблере: эмуляция команд Clear, Cls, Pause, Plot, Draw ...

╔───────────────────────────────────────╗
│             ОБМЕН  ОПЫТОМ             │
│ ───────────────────────────────────── │
│тем, кто много знает,читать запрещается│
╚───────────────────────────────────────╝

   (C) Заводчиков Константин
   (C) Музыка NEVER   

      Сегодня мы осветим некоторые вопро-
сы  по  программированнию на  ассемблере,
часто  возникающие у начинающих  програм-
мистов. Возможно,эта статья  будет повто-
рять своим содержанием некоторые печатные
или  электронные  издания, и кто-то, воз-
можно, упрекнет наш журнал  в  этом. Хотя
стоит вспомнить, что не каждый имеет дома
подшивку ZX-РЕВЮ хотя-бы за  какой-нибудь
год. Так что, кто силен в кодах  и  знает
множество  приемов, может смело  покинуть
эту статью. А с теми, кто остался,мы пос-
тaраемся что-нибудь выяснить для всеобще-
го блага.
      Для начала затронем несколько  про-
цедур, находящихся в ПЗУ :
      CLEAR xxxxx - программа очистки об-
ласти переменных  BASICа,  экрана,  уста-
новки стека и переменной RAMTOP  в  новые
значения. Для эмуляции этой команды в ко-
дах регистровая пара BC  должна содержать
адрес установки стека. В  ассемблере  это
будет выглядеть так :

         LD    BC,xxxxx
         CALL  7855 (#1EAF) .

Если в  BC  содержится 0 тогда произойдет
только очистка переменных и экранной  об-
ласти.

      CLS - программа очистки экрана. Ат-
рибуты   устанавливаются   соответственно
значению переменной  ATTR-P (23693).  При
обращении к этой программе в регистры за-
носить данные не надо. Она вызывается :
         CALL  3435 (#0D6B) .

      CLEAR-LINES  - подпрограмма очистки
нижних N строк экрана. В регистр B  зано-
сится количество очищаемых строк :

         LD    B,N
         CALL  3652 (#0E44) .

      PAUSE  -  полный   аналог   команды
BASICа. В регистре BC содержится количес-
тво задержек, если оно равно нулю то воз-
врат из процедуры будет  совершен  только
при нажатой клавише :

         LD    BC,пауза
         CALL  7997 (#1F3D) .

Вызывая  эту программу, не забудте разре-
шить прерывания и включить  первый  режим
прерываний (IM1), иначе из данной  проце-
дуры вы сможете вернуться только по кноп-
ке RESET.
      BREAK_KEY  - процедура, проверяющая
нажатие клавиши BREAK (не следует  путать
с клавишей SPACE). Вызывается она:

         CALL  8020 (#1F54) .

После возврата  из  процедуры, сброшенный
флаг переноса указывает на то,  что  была
нажата клавиша BREAK.

      PLOT - эта поцедура  зажигает  (или
гасит,в зависимости от системных перемен-
ных),на экране точку. В регисте C - коор-
дината X, регистре B - Y:

         LD    B,Y
         LD    C,X
         CALL  8933 (#22E5) .

      DRAW - программа изображения на эк-
ране  прямой  линии. Здесь, также  как  и
в процедуре PLOT, в регистрах B и C нахо-
дятся координаты Y и X, но не фиксирован-
ные - координаты смещения. В  регистре  D
знак смещения по координате X, в  E  знак
смещения по Y. То есть, если в знаке сме-
щения какой-нибудь координаты находится :
255 (#FF),  то  соответствующее  смещение
будет воспринято со знаком "минус"; 1- то
смещение будет со знаком "плюс"; 0 - сме-
щение по данной координате просто игнори-
руется.

         LD    B,Y
         LD    C,X
         LD    D,знак для Y
         LD    E,знак для X
         CALL  9402 (#24BA)  .

      CHAN-OPEN - подпрограмма служит для
открытия канала. Часто  начинающие  прог-
раммисты забывают открывать канал "S" при
использовании процедуры  печати  из  ПЗУ,
после чего с недоумением смотрят на стра-
но появившееся их сообщение, да еще и  не
там, где надо, либо, что более интересно,
выскакивает "OUT OF SCREEN". Для правиль-
ного вызова этой процедуры, в регистре  A
должно находится число в диапозоне от 253
(#FD) до 3. Эти числа являются  потоками,
ведущими к каналам : клавиатуры "K",  эк-
рана "S", принтера "P" и  рабочей области
"R". Перед вами значения потоков, ведущие
к стандартным каналам:

       253 (#FD) - открывает канал "K"
       254 (#FE) - открывает канал "S"
       255 (#FF) - открывает канал "R"
         0 (#00) - открывает канал "K"
         1 (#01) - открывает канал "K"
         2 (#02) - открывает канал "S"
         3 (#03) - открывает канал "P"  .

Так вот, повторюсь, при вызове  процедуры
аккумулятор должен содержать номер потока
(см. таблицу). К тому же,процедура должна
вызываться  в  сответствии с  приведенным
ниже текстом:

         LD    A,номер потока
         CALL  5633 (#1601)  .
А для того, чтобы  печатать  нормально во
всем экране, надо  в  регистр  A  занести
число 2 и вызвать процедуру CHAN-OPEN .

      SET_ADDR - программа расчета адреса
знакоместа  на  экране. При  обращении  к
данной процедуре регистр B  должен содер-
жать координату X, а регистр C координату
Y требуемого  знакоместа.   Вместо  точки
входа в ПЗУ, представляю вам листинг этой
программы.

         LD    B,координата Y
         LD    C,координата X
         CALL  SET_ADDR
         ............

SET_ADDR

         LD    A,B
         RRCA
         RRCA
         RRCA
         AND   #E0
         LD    L,A
         LD    A,B
         AND   #18
         OR    #40
         LD    H,A
         LD    B,#00
         ADD   HL,BC
         RET  .
После  вызова  процедуры  SET_ADDR  адрес
знакоместа находится в регистре HL.

      SET_ATTR - эта процедура расчитыва-
ет адрес  атрибута  для  соответствующего
адреса из области точек. На входе в  про-
цедуру регистр HL должен содержать нужный
адрес  из  области  точек. Также  приведу
листинг данной процедуры.

         LD    HL,адрес
         CALL  SET_ATTR
         ............

SET_ATTR

         LD    A,H
         RRCA
         RRCA
         RRCA
         AND   #0B
         OR    #50
         LD    H,A
         RET  .

Здесь в HL возвращается адрес атрибута.
      А теперь приведу несколько  простых
приемов, требующихся при написании  прог-
рамм в ассемблере.
      Деление регистровoй пары на 2, 4, 8
и т.д. :

         AND   A
         RR    B
         RR    C  .

При повторе данного примера N раз вы раз-
делите число на 2 в степени N. Таким  ме-
тодом возможно разделить и отдельные  ре-
гистры.
      Умножить  регистровую пару можно по
аналогии с предыдущим  примером,  заменив
команды RR на RL:

         AND   A
         RL    C
         RL    B  .

А если вам надо перемножить регистр HL,то
это лучше сделать командой сложения ADD :

         ADD   HL,HL      умножить на два
         ADD   HL,HL      на четыре
         ADD   HL,HL      на восемь
         ...........      и т.д.

      А сейчас частные примеры:
Умножение HL на шесть :

         ADD   HL,HL
         LD    B,H
         LD    C,L
         ADD   HL,HL
         ADD   HL,BC  ,

умножение HL на сорок :

         ADD   HL,HL
         ADD   HL,HL
         ADD   HL,HL
         LD    B,H
         LD    C,L
         ADD   HL,HL
         ADD   HL,HL
         ADD   HL,BC  ,

деление A на шесть:

         LD    A,делимое
         LD    B,#00
LABEL    SUB   #06 (делитель)
         RET   C
         INC   B
         JR    LABEL 

на выходе этой  процедуры  частное  будет
находится в регистре B  (не  забудте, что
таким методом можно выполнить только  це-
лочисленное деление!).
      Если  вы  используете  для сложения
или вычитания регистровых  пар  команды :
ADC и SBC, помните - при вычислениях  они
используют  флаг  переноса  (CARRY FLAG).
Поэтому перед ADC  или SBC  для получения
верного результата этот  флаг  необходимо
сбрасывать.  Очень  удобно делать это ко-
мандой  AND A.  При этом содержимое акку-
мулятора не меняется.

      Между прочим, в ПЗУ SPECTRUMа  есть
специальная мощная программа для разнооб-
разных математических вычислений.  Но она
имеет ряд  недостатков,  из-за которых ее
использование бывает затруднительно :
1.Вычисления производятся достаточно мед-
ленно. Поэтому калькулятор нецелесообраз-
но применять, например для расчета  коор-
динат в программах с динамической вектор-
ной графикой.
2.Работа с  калькулятором  осуществляется
несколько  необычным  способом,  впрочем,
хорошо знакомым тем, кто когда-нибудь ра-
ботал на  ПМК (программируемом микрокаль-
куляторе. Суть работы такова : сначала на
СТЕК КАЛЬКУЛЯТОРА (не на машинный!) зано-
сятся значения, а затем производятся опе-
рации с ними.  После чего, опять  же,  со
стека  калькулятора  снимается результат.
Не вдаваясь глубоко в подробности, приве-
дем некоторые  точки  входа,  необходимые
для работы :

    значение из A на стек    #2D28
    значение со стека в A    #2DD5
    значение из BC на стек   #2D2B (*)
    заначение со стека в BC  #2DA2

*) при возврате из  этой  подпрограммы  в
регистре  IY  будет  установлено значение
23610 (#5C3A).
     Теперь небольшой пример практическо-
го применения калькулятора.

     Необходимо вычислить (21-Y)*8+3 :

         LD    A,21   ; заносим на стек
         CALL  #2D28
         LD    A,(Y)  ; значения в поряд-
         CALL  #2D28
         LD    A,8    ; ке вычислений,
         CALL  #2D28
         LD    A,3    ; т.е. 21 Y 8 3
         CALL  #2D28
         ; теперь будем считать
         RST   #28    ; вкл. калькулятор
         DEFB  #03    ; вычитаем
         DEFB  #04    ; умножаем
         DEFB  #0F    ; прибавляем
         DEFB  #38    ; выкл. калькулятор
         ; снимаем результат со стека
         CALL  #2DD5  ; результат в A

     Попробуйте  написать  самостоятельно
подпрограмму  вычислений  по этой формуле
без использования калькулятора и сравнить
и эти две процедуры.
     Таблицу кодов операций  калькулятора
вы можете найти в трехтомнике по програм-
мированию в машинных кодах фирмы  "ИНФОР-
КОМ".  А если вы не сможете найти эту ли-
тературу, мы поделимся информацией в сле-
дующих выпусках журнала.

     На   этом  разрешите  откланяться, а
если кому-то что-то не ясно или появились
вопросы - обращайтесь в редакцию журнала,
мы  приложим  все  усилия  и  постараемся
помочь вам!

                 * * * 




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

Похожие статьи:
Голыми руками - ведро воды на головы обсмотревшихся фильмов про "кийя-кийя".
Анкета - Vinnnу.
анкета - Благодарим за заполнение анкеты. Просьба назвать этот файл своим ником и отослать нам.

В этот день...   16 августа