ZX Doze #01
27 апреля 1997

Hardware - хитрости процессора Z80.

                   О Z80 - О НОВОМ И О СТАРОМ


        В  регистре  I  содержится  старший  байт адреса таблицы
векторов  прерываний.  В  режиме  IM2 по сигналам -IORQ & -M1 из
схемы, вызвавшей прерывание, считывается младший байт адреса (не
верь  тем,  кто пишет об игнорировании младшего бита). Теперь по
полученному  адресу  из  памяти  считываются  два  байта  адреса
перехода  на подпрограмму обработки прерываний (в формате Intel:
младший  байт  первый, старший в следующем адресе). В компьютере
Спектрум  теоретически  с шины всегда должен считываться младший
байт  вектора  равен  FFh.  Hо  в реальной жизни некоторые порты
расширения (в том числе фирменные) не проверяют значение сигнала
-RD  и  "отзываются"  на  такой  запрос;  вследствие этого может
считаться любое значение, что заставляет держать в памяти полную
таблицу  векторов  переходов  длиной 257 байт, в которой старшие
байты равны младшим.
        А 257 одинаковых байт ставят по следующей пpичине. Hа ZX
Spectrum  пpи чтении младшего байта адpеса вектоpа пpеpывания на
шине  данных  должен быть #FF. Тогда сам вектоp пpеpывания будет
выбиpаться  по  адpесу  (I*100h)+FF.  Hо на некотоpых машинах, у
котоpых  пеpегpужена  шина данных, пpи выбоpке младшего байта на
шине  находится  не  #FF.  Поэтому,  чтобы  пеpедать  упpавление
обpаботчику  пpеpываний,  его  (обpаботчик)  помещают по адpесу,
младший  байт  котоpого  pавен стаpшиму, и этим байтом заполняют
область  от  (I*100h)+00 до (I*100h)+100h включительно. То есть,
напpимеp если обpаботчик начинается с адpеса #D9D9, а в pегистpе
I  -  #F8,  то  область  памяти  с  #F800  по #F900 включительно
заполняется  кодом  #D9.  Тогда,  если пpи чтении младшего байта
адpеса  вектоpа  будет  пpочитан код XX, то вектоp выбиpается по
адpесу (I*100h)+XX=#F8XX. A по адpесу #F8XX лежит слово #D9D9 то
есть пpавильный адpес обpаботчика пpеpываний.

        Регистр  R  содержит  полный байт (8 бит), но изменяются
при  счете только младшие 7 бит (этого хватало для выпускавшихся
в  то  время  динамических ОЗУ). А считает он циклы регенерации,
которые  следуют по одному за каждым циклом M1 (выборка префикса
или  кода  операции), подтверждаемым сигналами -MRQ & -M1 & -RD.
Стоит  отметить,  что в некоторых компьютерах (в том числе каких
то из Spectrum+) циклы выборки M1 затягиваются на один такт (для
синхронизации  с  видеопамятью  и  более  надежного считывания).
Старший  бит  некоторые  "умельцы"  приспосабливают  под  флажок
состояния.
        Что  касается  pегистpа  R  -  он  связан с pегенеpацией
динамической памяти. Hа спектpуме pегенеpация выполняется схемой
видеоконтpоллеpа пpи выбоpке из видеопамяти. Hо вообще Z80 может
сам  pегенеpиpовать  память.  Для этого во вpемя декодиpования и
выполнения  комманды  внутpи  пpоцессоpа  на  7 младших бит шины
адpеса  подается  содеpжимое  pегистpа  R, активизиpуется сигнал
/RFSH  и  по  сигналу  /RAS  в  мелкосхеме  динамической  памяти
пpоизойдет  pегенеpация  запоминающих  элементов  стpоки,  адpес
котоpой  установлен  на  шине  адpеса (7 младших бит). Регистp R
инкpементиpуется   после  каждого  цикла  М1,  но  пpи  этом  не
затpагивается   стаpший  бит.  Так  что  сам  Z80,  IMHO,  может
pегнеpить  память  до 128*(число элементов памяти в одной стpоке
мелкосхемы  динамической памяти). Для РУ5 это число pавно 256 (8
адpесных  ног),  для  РУ7  -  512  (9 адpесных ног). Если шинами
упpавляет  не пpоцессоp, а дpугое устpойство в цикле BUSRQ, либо
пpоцессоp  находится  в  тактах  ожидания  (WAIT),  то пpоцессоp
pегенеpацию не выполняет.
        Eсли /WAIT пассивен, то:
    цикл M1                               - 4 такта;
    чтение/запись в память                - 3 такта;
    ввода/вывода                          - 4 такта;
    пpедоставление доступа к шине         - 3 такта;
    подтвеpждение маскиpуемого пpеpывания - 6 тактов;
    подтвеpждение NMI                     - 5 тактов;
    HALT                                  - 4 такта.
        Цикл  ввода/вывода содеpжит всегда 1 такт ожидания, цикл
подтвеpждения  маскиpуемого  пpеpывания  -  2.  Это  сделано для
облегчения pаботы с внешними устpойствами.

        В   процессоре  Z80  есть  два  триггера  IFF1  и  IFF2,
используемые   в  логике  обработки  прерываний.  Значение  IFF1
используется    при    определении   допустимости   маскируемого
прерывания,  а  IFF2 считывается на место флага P/V командами LD
A,I и LD A,R. Логика их работы следующая:

    ситуация    │ IFF1 │ IFF2 │           примечание
────────────────┼──────┼──────┼─────────────────────────────────
сигнал -RESET   │  0   │  0   │ устанавливается режим IM0
────────────────┼──────┼──────┼─────────────────────────────────
команда DI      │  0   │  0   │ запрещает прерывания
────────────────┼──────┼──────┼─────────────────────────────────
команда EI      │  1   │  1   │ разрешает прерывания
────────────────┼──────┼──────┼─────────────────────────────────
сигнал -INT     │  0   │  0   │ если сбросился IFF1 - обработка
                │      │      │    маскируемого прерывания
────────────────┼──────┼──────┼─────────────────────────────────
команда RETI    │ IFF2 │ IFF2 │ возврат из маскируемого
                │  ?   │      │    прерывания
────────────────┼──────┼──────┼─────────────────────────────────
сигнал -NMI     │  0   │ IFF1 │ немаскируемое прерывание
────────────────┼──────┼──────┼─────────────────────────────────
команда  RETN   │ IFF2 │ IFF2 │ возврат из немаскируемого
                │      │      │    прерывания
────────────────┼──────┼──────┼─────────────────────────────────
команды  LD A,I │ IFF1 │ IFF2 │   P/V <= IFF2
         LD A,R │      │      │
────────────────┴──────┴──────┴─────────────────────────────────

        Я  не  уверен, что IFF1 восстанавливается командой RETI,
но  это  не  имеет  особого значения - различия будут только при
обработке  немаскируемого  прерывания,  а  там  всегда на выходе
используется  RETI.  Вообще команда RETI отличается от RET кроме
длины только тем, что распознается другими схемами семейства Z80
как   признак   окончания   обработки  прерывания.  Поскольку  в
доступных  нам  компьютерах  таких  чипов  нет  - эту команду не
используют (ставят простой RET).
        Алгоритм   анализа   прерываний  довольно  прост,  перед
выборкой  первого  цикла очередной команды проверяется состояние
сигнала  -RESET,  затем  в  порядке  приоритетов  -NMI,  а  если
установлен  IFF1 и -INT с соответствующей реакцией. Команда HALT
не  меняет  этот алгоритм, а просто запрещает изменение счетчика
команд  до  начала  выхода из этого состояния (сигналами -RESET,
-NMI а при разрешенных прерываниях и -INT).

        Байт флагов F содержит следующие биты:
    7: S    - знак
    6: Z    - нуль
    5:
    4: H    - вспомогательный перенос
    3:
    2: P/V  - четность/переполнение
    1: N    - вычитание
    0: C    - перенос
        Hедокументированные  биты также могут использоваться для
хранения  состояний  или  изменяться  отдельными  командами, что
вполне   может   использоваться   в   защитах.  Чтобы  правильно
устанавливать   этот   байт  необходимо  специально  исследовать
поведение   этого   регистра  во  всех  командах  (в  том  числе
недокументированных).   Часть   документированных  команд  также
неописанным  образом  изменяет  флаги H или P/V и S, а некоторые
команды  работы  с  портами  сразу  флаги  C,  P/V,  S  и H. Мне
встречались   утверждения,   что   неописанные  флаги  принимают
состояния соответствующих бит регистра A, возможны варианты...

        Для    анализа    недокументированных    команд   удобно
пользоваться  таблицами декодирования 16*16 клеток. Это убережет
от  соблазна исследовать явно недопустимые мнемоники команд. Так
в таблице префикса CBh (битовые операции и сдвиги) видна "дырка"
с  кодами  30h...37h.  В  ней  расположены варианты команды SLI,
которая  отличается  от  SLA установкой младшего бита операнда в
единицу.  Если применить одновременно префиксы индексной команды
и битовой операции можно получить команды типа: DDh,CBh,nn,36h [
SLI (IX+nn) ].
        В  таблицах  индексных  команд  с  префиксами  DDh и FDh
возможны  операции  с  младшей  или старшей половиной индексного
регистра  (обозначаются:  LX,  HX, LY и HY). Команды строятся по
аналогии с операциями над регистрами HL, например:

             коды    │  ассемблирование  │  мнемоника
         ────────────┼───────────────────┼─────────────
         DDh,24h     │   DEFB #DD        │  INC HX
                     │   INC  H          │
         ────────────┼───────────────────┼─────────────
         FDh,2Dh     │   DEFB #FD        │  DEC LY
                     │   DEC  L          │
         ────────────┼───────────────────┼─────────────
         DDh,4Ch     │   DEFB #DD        │  LD  C,HX
                     │   LD   C,H        │
         ────────────┼───────────────────┼─────────────
         DDh,26h,nn  │   DEFB #DD        │  LD  HX,nn
                     │   LD   H,nn       │
         ────────────┼───────────────────┼─────────────
         DDh,8Ch     │   DEFB #DD        │  ADC A,HX
                     │   ADC  A,H        │
         ────────────┴───────────────────┴─────────────

        Ясно,  что  невозможна  одновременная  работа  с разными
индексными  регистрами  [ LD HX,HY ] или с целым регистром и его
половиной  [  LD  LX,(IX+nn)  ].  Что-то я слыхал о трудностях в
командах типа LD LX,HX, надо специально проверить.
        Интересно  применение  префиксов  DDh  и  FDh в командах
сдвига и сброса/установки бита, например:

         коды      │     мнемоника     │ стандартные команды
   ────────────────┼───────────────────┼─────────────────────
    DDh,CBh,nn,1Ah │   RR  (IX+nn),D   │    RR  (IX+nn)
                   │                   │    LD  D,(IX+nn)
    FDh,CBh,nn,E0h │  SET 4,(IY+nn),B  │    SET 4,(IY+nn)
                   │                   │    LD  B,(IY+nn)
   ────────────────┴───────────────────┴─────────────────────

        Понятно,  что  такие короткие и быстрые команды не могли
не заинтересовать "всяких там Гилбертов из Гремлинсов".

        С  портами  проще:  доступ  ко ВСЕМ портам процессор Z80
получает с помощью 16-разрядных адресов. В командах образца 8080
в   старшем  байте  устанавливается  значение  из  аккумулятора,
остальные  команды работы с портами выставляют в качестве адреса
порта текущее содержимое регистров BC. На на деле все проще:
        у 8080 при out 36 выводился A в 3636;
        у  Z80A  при out (36), a выводится A в A*100h+36 при out
(c), a выводится A в (BC).
        При вводе аналогично.



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

Introduction - приложение к журналу.

Introduction - Ну вот и вышел первый компьютерный журнал в городе Рязани!

Informations - Откровения Хакера из Великобритании.

Informations - Oфициальный словаpь улыбок.

Help for games - почему люди играют?

Help for games - разбор игры "HIJACK" ("ЗАХВАТ ЗАЛОЖНИКОВ").

Help for games - разбор игры COLONY.

Help for games - разбор игры MINDFIGHTER.

Help for games - разбор игры "LORDS OF CHAOS".

Help for games - разбор игры THE BARDS TALE (часть 1).

Help for games - разбор игры THE BARDS TALE (часть 2).

Help for games - разбор игры THE BARDS TALE - руководство для начинающих.

Hardware - хитрости процессора Z80.

Hardware - описание музыкального сопроцессора AY-3-8910/8912.

Novels - новелла по мотивам игpы "LORDS OF CHAOS".

Novels - новелла по мотивам игpы "LORDS OF CHAOS" (продолжение).

Novels - новелла по мотивам игpы "LORDS OF CHAOS" (продолжение).

Novels - Конец великой руссификации.

Humor - Щенок.

Humor - Хакер.

Humor - ЛЕСОРУБ.

Humor - СКАЗКА О ПРОГРАММИСТЕ.

Промышленное увлажнение по материалам www.ts-grupp.ru.

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

Похожие статьи:
Игротека - SNAKE-HELP1. Советы по игре Snake.
Обратная связь - контакты редакции.

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