Born Dead #0E
19 декабря 1999

Злоба Дня-II - особенности работы с регистрами I/R в процессоре Z80: выдержки из официально документации.

════════════════════════════════════════════════════════════════
                        ЗЛОБА ДНЯ-II 
════════════════════════════════════════════════════════════════

(c) Mac Buster^XTM
(c) UnBEL!EVER^XTM

Около  года  назад  Иван Рощин вместе с релизом очередной версии
BEST  VIEW  опубликовал  небольшую  исследовательскую  заметку о
найденном им  глюке ( недокументированной особенности ) в работе
команд   процессора  Z80  в  аспекте  возникновения  прерываний.
Сенсацией  стало то, что благодаря описанному Иваном тесту можно
было 100% определить - выполняется ваша программа под эмулятором
или  на  живой  машине.  В  силу  редкости  возникновения  этого
"недокументированного"  явления  ни  один эмулятор тех времен не
работал именно так, как вёл себя реальный Z80.

Прошло  время...  Было  выяснено, что и раньше, программисты или
знали, или догадывались о неправильном установлении флага IFF2 в
случае  прихода прерывания в момент выполнения команд LD A,R или
LD  A,I.  Судить  об  этом  можно  совершенно однозначно по коду
программ,  написанных  ещё  задолго  до  98-го года. Большинство
эмуляторов  в  настоящее  время уже поддерживают эту особенность
Z80,   но   остаётся   лишь  один  вопрос:  "Почему  за  20  лет
существования процеcсора этот феномен не стал достоянием широких
масс  общественности  наряду  с половинками индексных регистров,
двойной     префиксации     и     массой    других,    so-called
недокументированных особенностей???"

Ответ на этот вопрос трагичен... Мы живём в состоянии настоящего
информационного  голода!!!!  Именно  из-за  отсутствия доступа к
первоисточникам  происходит  это  постоянное открывание Америки.
Вот   представьте   себе,   что   вы  стали  обладателем  Hi-End
видеомагнитофона,  но  к нему нет инструкции. И вот год за годом
вы  нажимаете на нём кнопки управления и постепенно осознаёте их
истинные  функции. Точно так же глупо выглядит игрок, пытающийся
понять,  что  скрывается  за клавишами, издающими звуки в режиме
PAUSE  в  знаменитой  ELITE.  И  ведь ему даже в голову не может
прийти,  что в прилагаемом к ELITE фирменном руководстве всё это
подробно описано...

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

Именно так поступил Mac Buster^XTM, когда не пожалев 5$, заказал
в  фирме  Zilog  руководство по процессору Z80. Ну и естественно
результат   превзошёл  все  ожидания!  Ниже  приводится  перевод
нескольких   ключевых   страниц   руководства,   имеющих  прямое
отношение к "bug'у Ивана Рощина".

----------[начало]----------------------------------------------
Zilog                         МП Z80(R) Руководство пользователя
----------------------------------------------------------------
                                                          LD A,I
 Операция : A<-I

 Оператор:  LD

 Операнды:  A,I

            +-+-+-+-+-+-+-+-+
            |1|1|1|0|1|1|0|1| ED
            +-+-+-+-+-+-+-+-+

            +-+-+-+-+-+-+-+-+
            |0|1|0|1|0|1|1|1| 57
            +-+-+-+-+-+-+-+-+

 Описание : Содержимое регистра вектора прерывания I загружается
            в аккумулятор.

              M Cycles       T States       MHz E.T.
                  2           9(4,5)          2.25

 Действие на флаги:

             S:  Установлен, если 7-ой бит в регистре I равен 1;
                 иначе сброшен
             Z:  Установлен, если регистр I = 0; иначе сброшен
             H:  Сбрасывается
           P/V:  Содержит копию триггера прерываний IFF2
             N:  Сбрасывается
             C:  Не изменяется

Примечание:  Если прерывание происходит в момент выполнения этой
команды, флаг переполнения/чётности ( P/V ) будет содержать 0.
------------------------------------------------------[A5-23]---

Zilog                         МП Z80(R) Руководство пользователя
----------------------------------------------------------------
                                                          LD A,R

 Операция : A<-R

 Оператор:  LD

 Операнды:  A,R

            +-+-+-+-+-+-+-+-+
            |1|1|1|0|1|1|0|1| ED
            +-+-+-+-+-+-+-+-+

            +-+-+-+-+-+-+-+-+
            |0|1|0|1|1|1|1|1| 5F
            +-+-+-+-+-+-+-+-+

 Описание : Содержимое регистра  обновления памяти R загружается
            в аккумулятор.

              M Cycles       T States       MHz E.T.
                  2           9(4,5)          2.25


 Действие на флаги:

             S:  Установлен, если 7-ой бит в регистре I равен 1;
                 иначе сброшен
             Z:  Установлен, если регистр I = 0; иначе сброшен
             H:  Сбрасывается
           P/V:  Содержит копию триггера прерываний IFF2
             N:  Сбрасывается
             C:  Не изменяется

Примечание:  Если прерывание происходит в момент выполнения этой
команды, флаг переполнения/чётности ( P/V ) будет содержать 0.
------------------------------------------------------[A5-24]---

Zilog                    Семейство Z80, Вопросы и Ответы: МП Z80
----------------------------------------------------------------

В: Я  не уверен в  том, что получаю  истинное значение состояния
   прерываний, когда  использую  инструкции  LD A,I и LD A,R для
   чтения IFF2. Почему это происходит? Как с этим бороться?

О: В CMOS версии Z80 CPU мы исправили эту проблему. Но в Z80 CPU
   NMOS   версии,   при  определённых  обстоятельствах,  триггер
   прерываний  IFF2 процессора Z80 не всегда отображает реальное
   состояние прерываний.

Две  инструкции  -  LD  A,R и LD A,I копируют состояние триггера
прерываний   IFF2  во  флаг  чётности/переполнения  (  P/V  ), и
изменяют  содержимое аккумулятора Z80 ( см. таблицу 7.0.1 в "Z80
CPU technical manual").

Таким образом, можно определить, были ли разрешены или запрещены
прерывания  во  время  выполнения  одной  из  этих  команд.  Это
необходимо  для  получения  достоверной  информации  о состоянии
машины.  Тем  не  менее,  если  прерывание  произойдёт  во время
выполнения   одной  из  этих  инструкций  (подразумевается,  что
прерывания   должны  быть  разрешены),  то  флаг  P/V  очистится
(сбросится  в  0).  Это  приведёт  к  неверной трактовке - якобы
прерывания были запрещены на момент выполнения инструкции.

Этот  парадокс  может быть объяснён последовательностью действий
при  выполнении  внутренних  функций процессора. Дело в том, что
в  данной ситуации вторичный триггер прерываний (IFF2) очищается
ещё до того, как его содержимое пересылается во флаг P/V.

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

Наиболее простой способ определить такую ситуацию основан на том
факте,   что  при  возникновении  прерывания  на  вершину  стека
заносится  как  минимум один элемент - старое значение PC. Таким
образом,  записав  нулевое  значение  по адресу, предшествующему
текущей вершине стека, непосредственно перед исполнением команды
LD  A,I ( или LD A,R ) и проверив это значение сразу же после её
исполнения,  мы  сможем  установить  истинное  значение триггера
прерываний.  Если это значение изменилось во время выполнения LD
A,I  (  или  LD  A,R  ),  значит прерывание произошло в процессе
исполнения  этой команды и прерывания определённо разрешены. Вот
последовательность   действий,  воспользовавшись  которой, можно
написать процедуру для определения состояния прерываний:

 - обнуляем слово, предшествующее текущей вершине стека
 - выполняем команду LD A,I ( или LD A,R )
 - сразу  же  проверяем состояние флага P/V. Если он установлен,
   то  у  нас  нет  никаких   причин   сомневаться  в  том,  что
   прерывания и в самом деле разрешены
 - если  же  P/V сброшен, то нам имеет смысл проверить состояние
   слова  перед  вершиной стека и если оно не равно нулю, то это
   значит, что прерывания всё же разрешены и в момент исполнения
   LD  A,I  ( или LD A,R ) происходило прерывание. Если то слово
   перед  вершиной  стека  не  изменялось - можно с уверенностью
   сказать, что прерывания и в самом деле запрещены

Обе нижеприведённых процедуры возвращают флаг C сброшенным в том
случае,  если прерывания разрешены, либо установленным, если они
запрещены. Процедуры изменяют содержимое регистра A, но не стоит
рассчитывать  на  то,  что на выходе он будет содержать значение
регистров I или R. Значение прочих флагов неопределено.

Первая  процедура  может располагаться где угодно в памяти кроме
"нулевой   страницы"   -   от  #0000  до  #00FF.  Это  небольшое
ограничение обусловлено лишь тем, что процедура проверяет только
старший  байт  слова  из  следующей  позиции стека. Этот байт не
будет  нулевым  после  прихода  прерываний только в случае, если
процедура  сама  не  находится  в  "нулевой странице". Вторая же
процедура  проверяет  сразу оба байта следующей позиции стека и,
таким образом, избавлено от подобного ограничения.

Внимание!  Эти процедуры предполагают, что обработчик прерываний
разрешает прерывания при завершении своей работы. Это делается в
большинстве   случаев.   Однако,  возможно  получение  неверного
результата,  если  процедура  обработки  прерывания,  которая не
разрешает   прерывания  при  прекращении  своей  работы,  начнёт
выполняться  непосредственно  после исполнения инструкции LD A,I
(или LD A,R).

  Листинг 1: Эта процедура не может работать из адресов #0-#00FF

   GETIFF:
         XOR  A         ;C flag, acc.:=0
         PUSH AF        ;stack bottom :=00xxh
         POP  AF        ;Restore SP
         LD   A,I       ;P flag :=IFF2
         RET  PE        ;Exit if enabled
         DEC  SP        ;May be disabled ( P flag :=0 ).
         DEC  SP        ;Has stack bottom been
         POP  AF        ;overwritten ?
         AND  A         ;If not xx00h, INTs were
         RET  NZ        ;actually enabled.
         SCF            ;Otherwise, they really are
         RET            ;disabled.
         END

  Листинг 2: Эта процедура может работать из любых адресов

   GETIFF:
         PUSH HL       ;Save HL contents
         XOR  A        ;C flag, acc.:=0
         LD   H,A      ;HL :=0000h
         LD   L,A      ;
         PUSH HL       ;Stack bottom :=0000h
         POP  HL       ;Restore SP
         LD   A,I      ;P flag :=IFF2
         JP   PE,POPHL ;Exit if enabled
         DEC  SP       ;May be disabled ( P flag := 0).
         DEC  SP       ;Let's see if stack bottom
         POP  HL       ;is still 0000h.
         LD   A,H      ;Are any bits set in H
         OR   L        ;or L ?
         POP  HL       ;Restore old contents.
         RET  NZ       ;HL <> 0 : isn't enabled
         SCF           ;Otherwise they really are
         RET           ;disabled.
   POPHL:              ;
         POP  HL       ;Exit when P flag is
         RET           ;set by LD A,I ( P flag := 1 ).
         END

----------[конец]-----------------------------------------------

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



Другие статьи номера:

ВСТУПЛЕНИЕ - "Хрен в сумку тем, кто решил, что BORN DEAD кончился...": 666 байт От Редакции.

ВВЕДЕНИЕ В ОБОЛОЧКУ - BornDead #0E это однозначно шедевр современного кодинга в любых его аспектах.

Новости - презентация нового европейского демопати - FOREVER 2E3.

Обзор софта - игра 12 ТАЙНЫХ КНИГ: Миссия, коммандер REAL COMMANDER v1.9, журнал ZX-GIUDE #2, демо IRIS ultrademo, игра Operation "Oil" demo v0.666, игра ВЗРЫВ v1.1.

Hints - хитрости текстового редактора Modern Word 2.1.

Злоба дня - Как правильно(!) делать дисковые версии программ для ZX Spectrum.

Злоба Дня-II - особенности работы с регистрами I/R в процессоре Z80: выдержки из официально документации.

Голос из могилы - новое детище Клайва Синклера: Sinclair QL - Отделение фактов от вымысла.

Партийная зона - DI:HALT99; Лучше поздно, чем ещё раз! История провального демопати.

Партийная зона - итоги 1999 года: 18 дем для Спектрума. Разбор новых и старых дем.

LETTER'АТУРА - письмо от Slider/BrokImSoft/Rushи ответ на него.

Iron made in - схема огромного экрана из светодидов для ZX Spectrum.

Под звуком "ПИ" - "Мне страшно за SPECTRUM! Из всей армии его поклонников, лишь единицы истинные спектрумисты!"

Реклама - CD-ROM, который тебе нужен!? Сборник вареза для Спектрума от MMA.

Послесловие - ни одна сволочь даже не вспомнила, что нашей газете исполнился год...


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

Похожие статьи:
Help - Описание оболочки электронного издания "ZX-FORUM 4".
АLEХ'у от меня - я только рад обоснованной критике.
Гости - О происхождении группы ACCEPT CORP из г. Армавира.

В этот день...   24 июня