Элементарная графика 1993 г.

Элементарная графика в машинных кодах - понятие о каналах и потоках. Печать на экран из машинного кода.


                  2. ЭЛЕМЕНТАРНАЯ  ГРАФИКА  В МАШИННЫХ  КОДАХ

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

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

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

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

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

                        2.1  ПОНЯТИЕ О КАНАЛАХ И ПОТОКАХ

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

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

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

              Проще  всего  представить  концепцию  каналов и потоков на
         примере морского побережья с многочисленными заливами и  бухта-
         ми. Со стороны суши в них впадают многочисленные ручьи и  реки.
         Так вот, эти заливы  и бухты - это  каналы, а те ручьи  и реки,
         которые в них впадают - это потоки, подключенные к каналам.

              Те,  кто  более  глубоко  заинтересуются  этой концепцией,
         могут найти информацию в нашем издании "ZX-РЕВЮ" (N12,  1991г.,
         с.227; N 5,6, 1992 г.,с. 111), мы же здесь рассмотрим этот  во-
         прос в минимально необходимом объеме.

              Стандартными  каналами  "Спектрума"  для вывода информации
         являются каналы "К" -  нижние две строки экрана  (системное ок-
         но), "S" - главная часть  экрана и "P" - стандартный  "ZX-прин-
         тер".

              К этим каналам стандартно подключены потоки:

              - поток #0 - к каналу "К";
              - поток #1 - тоже подключен к каналу "K";
              - поток #2 - подключен к каналу "S";
              - поток #3 - к каналу "P".

              Таким образом,  оказываются идентичными  следующие команды
         ввода/вывода:

             PRINT #0 "Hello"; A$ - то же самое, что и INPUT "Hello"; A$
             PRINT "Hello" - то же самое, что и PRINT #2 "Hello"
             LPRINT "Hello" - то же самое, что и PRINT #3 "Hello"

             Номер, стоящий  после знака  # в  вышеприведенных примерах,
         является номером потока. Поскольку эти потоки подключены  стан-
         дартно  и  переподключены  быть  не  могут, мы программируем на
         БЕЙСИКе и используем операторы INPUT, PRINT, LPRINT без  указа-
         ния номера потока.

              Это то, что касалось стандартных каналов и потоков, но они
         могут быть и нестандартными. Так, если Вы работаете в локальной
         сети, то сеть становится еще одним каналом, к которому Вы  под-
         ключите поток.

              Вы знаете, что "Спектрум" может в любой момент времени вы-
         полнять только одно дело. Например, либо он печатает на экране,
         либо на принтере. Одновременно выдавать информацию и туда и ту-
         да он  не может,  поэтому в  любой момент  времени задействован
         только один канал  ввода/вывода и, соответственно,  только один
         поток,  связанный  с  ним.  Этот  канал и этот поток называются
         текущими. В большинстве случаев,  когда Вы работаете с  компью-
         тером, текущим является канал "K", несколько реже - канал "S".

              Программируя в машинном  коде, переключаться с  канала "K"
         на "S" (и наоборот) очень просто. Информацию о том, какой канал
         является текущим в данный  момент, несет нулевой бит  системной
         переменной TVFLAG (5С3СH -  23612).  Когда он выключен   (равен
         нулю), используется канал "S", а когда включен - "K".

              Две небольшие процедуры продемонстрируют разницу в их  ис-
         пользовании.
                               Демо_S

              213C5C            LD HL,TVFLAG
              3600              LD (HL),00     ; Выключили бит 0 систем-
                                               ; ной переменной TVFLAG.
              3E2A      LOOP    LD A,42        ; Загрузили в аккумулятор
                                               ; число 42 (код символа
                                               ; "*".
              D7                RST 10H        ; Выдали на печать по те-
                                               ; кущему каналу то, что
                                               ; находится в аккумулято-
                                               ; ре.
              18FB              JR LOOP        ; Возврат для повтора.

                               Демо_K

              213C5C            LD HL,TVFLAG
              3601              LD (TVFLAG),01 ; Включили бит 0 систем-
                                               ; ной переменной TVFLAG.
              3E2A      LOOP    LD A,42
              D7                RST 10H        ; Печать символа "*".
              18FB              JR LOOP        ; Возврат для повтора.

              Не менее  просто переключаться  с каналов  "S" или  "K" на
         канал "P". Здесь тоже достаточно изменить один бит. Это  первый
         бит системной переменной FLAGS (5C3BH - 23611). Он должен  быть
         выключен для каналов "S" и "K", но включен для канала "P".

                               Демо_P

              213B5C            LD HL,FLAGS
              CBCE              SET 1,(FLAGS)  ; Включили бит 1 систем-
                                               ; ной переменной FLAGS.
              0600              LD B,00        ; Обнуление счетчика
                                               ; (подготовка к печати
                                               ; 256-ти символов).
              3E2A      LOOP    LD A,42
              D7                RST 10H        ; Печать символа "*".
              10FB              DJNZ LOOP      ; Возврат для повтора,
                                               ; пока счетчик не достиг-
                                               ; нет нуля.
              С9                RET            ; Возврат в вызывающую
                                               ; программу.

              Вы можете также изменить текущий канал, переключившись  на
         другой поток. Это можно сделать вызовом процедуры ПЗУ,  называ-
         ющейся CHAN_OPEN и находящейся по адресу 1601H. Перед тем,  как
         ее вызывать, следует в аккумуляторе установить номер  желаемого
         потока.

              3E02              LD A,02        ; Ввели номер желаемого
                                               ; потока.
              CD0116            CALL 1601H     ; Сделали его текущим.
              3E2A      LOOP    LD A,42
              D7                RST 10H
              18FB              JR LOOP

              Нам необходимо знать эти  азы потому, что если  мы исполь-
         зуем для печати из  машинного кода команду процессора  RST 10H,
         то должны  иметь в  виду, что  она выдает  информацию ТОЛЬКО  В
         ТЕКУЩИЙ КАНАЛ. Прежде, чем Вы дадите компьютеру команду, что бы
         Вы хотели, чтобы он напечатал, надо сначала определиться,  куда
         он будет это печатать и как.

              Команду RST  10H Вы  можете использовать  для печати любых
         символов, будь то символ  стандарта ASCII или графический  сим-

         вол. Это может быть  управляющий символ и даже  токен ключевого
         слова стандартного БЕЙСИКа. Поместите код того, что хотите  на-
         печатать, в аккумулятор и дайте команду RST 10H. При этом обыч-
         ные символы  займут одно  знакоместо, управляющие  коды сделают
         то, что им положено, а токены ключевых слов будут развернуты  и
         займут столько знакомест, сколько  букв в этом ключевом  слове.
         Вам надо  также знать,  что команда  RST 10H  никогда не портит
         содержимое регистров процессора,  кроме BC', DE'  (альтернатив-
         ные) и аккумулятора, который портит не всегда.

                      2.2 ПЕЧАТЬ НА ЭКРАН ИЗ МАШИННОГО КОДА

                            2.2.1. Печать чисел.

              1. Целые числа  от 0 до  9. Выполнить печать  целого числа
         от 0 до 9 можно двумя способами.

              Во-первых, Вы можете напечатать его обычным способом,  как
         и  любой  другой  символ.  Для  этого  поместите  в аккумулятор
         процессора его код (код  0 - 48 (30H),...  код 9 - 57  (39H)) и
         дайте команду RST 10H.

              Во-вторых, можно это число напечатать, загрузив в  аккуму-
         лятор не его код, а само число, но в этом случае печать следует
         выполнять не командой RST  10H, а вызовом специально  для этого
         предназначенной процедуры ПЗУ - CALL 15EFH (десятиричный  адрес
         - 5615), она называется OUT_CODE. Это, конечно, удобнее, но при
         своей  работе  эта  процедура  портит  регистр  E (имейте это в
         виду).

              Возможен  и  промежуточный  вариант,  когда Вы засылаете в
         аккумулятор само число, а не его код, затем прибавляете к  нему
         30H (получаете его код) и затем даете RST 10H.

                            LD A,N
                            ADD A,30H
                            RST 10

              По расходу памяти это то же самое, что и CALL OUT_CODE, но
         не портит регистр E.

              2. Целые числа от 0 до 9999.
              Для печати  целых чисел,  меньших чем  10000, введите  это
         число в регистровую пару BC и вызовите процедуру ПЗУ OUT_NUM_1.
         Она находится по адресу 1A1BH (6683).

              Если Ваше число содержится в виде двух байтов в  известном
         Вам адресе памяти, то Вы можете воспользоваться процедурой  ПЗУ
         OUT_NUM_2 (1A28H = 6696). В этом случае перед вызовом процедуры
         надо в регистровую пару  HL заслать адрес, в  котором находится
         Ваше число.

              И в том  и в другом  случае, если Вы  попробуете через эти
         процедуры  распечатать  число,  которое  больше 9999, результат
         будет неверным.

              3. Целые числа от 0 до 65535.
              В  этом  случае  Ваше  число  тоже  должно быть помещено в
         регистровую  пару  BC,  но  в  отличие  от  предыдущего  случая
         необходимо делать не один вызов процедур ПЗУ, а два.

              Сначала оно должно быть конвертировано в интегральную (пя-
         тибайтную форму) и помещено на стек калькулятора. Это  делается
         вызовом процедуры STACK_BC (CALL 2D2BH = 11563). И только после
         этого оно  может быть  напечатано, как  действительное число  с
         плавающей точкой. Это  выполняется вызовом процедуры  PRINT_FP,
         расположенной по адресу 2DE3H (11747).

              4. Отрицательные целые числа.
              Знак "минус" имеет код  2DH. Поместите его в  аккумулятор,
         выполните RST  10H и  абсолютную величину  числа печатайте, как
         показано выше.

              5. Произвольные  действительные числа  (числа с  плавающей
         точкой).

              Такое число занимает 5 байтов и хранить его ни в каком ре-
         гистре, ни в  регистровой паре невозможно.  В этом случае  Вами
         должны быть приняты меры для того, чтобы предварительно размес-
         тить его на вершине стека калькулятора. Когда это сделано,  вы-
         зов процедуры PRINT_FP (2DE3H=11747) напечатает его на экране.

              Здесь надо сделать пару предупреждений для тех, кто  рабо-
         тает с калькулятором "Спектрума", "зашитым" в ПЗУ.

              Во-первых, после работы PRINT_FP число со стека  калькуля-
         тора снимается и, если Вам оно еще может потребоваться, то  по-
         заботьтесь предварительно продублировать вершину стека  кальку-
         лятора (соответствующая  команда в  сводке команд  калькулятора
         имеется - см. "Первые шаги  в машинном коде", М.:   "ИНФОРКОМ",
         1990г.,1992г.).

              Во-вторых,  в  процедурах  ПЗУ, обслуживающих калькулятор,
         есть ошибка. Она  заключается в том,  что это число  при вызове
         PRINT_FP снимается со стека не всегда. Если Ваше действительное
         число находится в диапазоне от -1 до +1 (ноль исключается),  то
         вместо Вашего числа на  вершине стека остается 0.  Обращайте на
         это внимание.

                         2.2.2. Печать символьных строк.

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

              Самый простой метод состоит в следующем. Регистровая  пара
         DE должна содержать адрес, с которого начинается Ваша  символь-
         ная строка, а в  регистровой паре BC необходимо  предварительно
         установить длину этой строки. Печать выполняется вызовом проце-
         дуры PR_STRING, которая находится по адресу 203СH (8252).

              Во-вторых, символьная  строка может  быть Вами  получена в
         результате работы встроенного  калькулятора. В этом  случае она

         находится на вершине стека калькулятора и может быть напечатана
         прямо оттуда вызовом процедуры ПЗУ PR_STR_1 (адрес 2036H=8246).

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

              У Вас может быть целый  набор из N различных сообщений.  И
         Вы, допустим,  хотите напечатать  k-ое сообщение.  Тогда можете
         действовать следующим образом:

              - установите в аккумуляторе число k-1;
              - установите в регистровой  паре DE адрес, указывающий  на
         байт, находящийся перед первым байтом самого первого  сообщения
         из Вашей таблицы сообщений. Имейте в виду, что этот байт должен
         быть больше  или равен  80H, но  меньше, чем  FFH, т.е. старший
         (седьмой) бит в этом байте должен быть включен (он явится  мар-
         кером начала текстового сообщения);

              - вызовите процедуру PO_MSG (0C0AH=3082) и Ваше сообщение
         будет напечатано на экране.

              Впрочем, у этого метода есть ряд ограничений и требований.
         Их необходимо также иметь в виду при программировании:

              -  недопустимо  использование  графических  символов   или
         токенов ключевых  слов БЕЙСИКа,  т.е. коды  печатаемых символов
         должны быть  менее 128  (80H). Впрочем,  можно ведь  и поменять
         символьный набор, заменив на время символы ASCII на нужные  Вам
         графические шаблоны;

              - во-вторых, Вам надо при заполнении таблицы сообщений
         сделать  так,  чтобы  последеий  символ  каждого сообщения имел
         включенный 7-ой бит, тем самым он будет служить маркером  конца
         i-го  сообщения  и  компьютер  всегда  по  номеру,  заданному в
         аккумуляторе, найдет нужное Вам сообщение;

              - в таблице не может быть пустых строк.

                            2.2.3.  Полезные советы.

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

              Итак, во-первых, если Вам необходимо выдать на экран  сим-
         волы блочной графики (коды с 80H  по 8FH) - эти символы  распо-
         ложены на цифровом ряду  клавиатуры, - то коррумпируются  (пор-
         тятся) системные  переменные, расположенные  в адресах  с 5C92H
         (23698) по 5C99H (23705). Те, кто читал "Первые шаги в машинном
         коде",  знают,  что  здесь  хранятся  две  первые ячейки памяти
         встроенного калькулятора (из шести стандартных).  Это ячейки M0
         и M1. Почти во всех случаях Вам эта порча безразлична, но  если
         Вы активно работаете с калькулятором и именно они Вам и  нужны,
         то примите меры по сохранению  их значений в другом месте,  на-
         пример на стеке калькулятора или в других ячейках.

              Во-вторых, при печати чисел мы довольно активно  пользова-
         лись процедурой ПЗУ PRINT_FP, которая распечатывает  содержимое
         вершины стека калькулятора, а  она во время своей  работы "пор-
         тит" все шесть ячеек  памяти калькулятора, т.е. все  содержимое
         системной переменной  MEMBOT с  адреса 5C92H  (23698) по  адрес
         5CAFH (23727). Опять же  для Вас это почти  всегда безразлично,
         за исключением  тех редких  случаев, когда  Вы оставили  там на
         хранение данные без присмотра.

              А вот третий случай довольно часто встречается у тех,  кто
         много работает со встроенным  калькулятором. Дело в том,  что в
         таблице системных переменных есть переменная под названием MEM,
         она расположена в  адресе 5C68H (23656)  и занимает 2  байта. В
         ней хранится адрес, по которому расположена память  калькулято-
         ра, т.е. адрес системной переменной MEMBOT. Если Вам достаточно
         тех шести ячеек  памяти калькулятора, которые  есть стандартно,
         то нет проблем. А  если же Вам их  мало, то Вы создаете  их по-
         больше, для чего меняете адрес MEMBOT и, естественно,  указание
         на нее, содержащееся в MEM. Так вот, после такой замены  проце-
         дура PRINT_FP правильно работать не сможет.



СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Отдохни - Стих о Sysop'e. Поэзия однако...
Дмитрий Громов - Рухнувшая Стена (обзор фантастики 1995-96 г. г.).
Список BBS - Список BBS.
Веселуха - юмористический рассказ: Я МАШИНА.
minskzxnet - поинтовка (воспоминания пьяной женщины).

В этот день...   21 ноября