┌──────────────────────────────┐
│ ───────── СИСТЕМА ────────── │
└──────────────────────────────┘
Станислав В. Ефимов
Новое о Z-80, или как используются недокументированные возможности процессора, а также кое-что про архитектуру компьютера.
Тот, кто программирует на ассемблере, прекрасно знает все инструкции, флаги, которые меняются под воздействием этих инструкций и, в зависимости от опыта и прочих условий, полагает, что ему известно все о Z80. Однако я уверен, что информация, изложенная мною ниже, если и не будет для кого-то неожиданной, то будет интересной и, возможно, полезной. Каждый из вас изучал ассемблер по своему: кто-то читал различные книги "русского" издания (Из великого множества книг безусловно можно выделить широко известный трехтомник "Инфоркома"), а кто-то со временем, и не читая никаких книг, набирался опыта у "западных" программистов, бесконечно просматривая в MONSе бесконечные тексты бесконечного множества программ, а также листая различные "западные" энциклопедии по Z80 (этим путем шло огромное количество людей, которые начали заниматься программированием Z80 в не столь отдаленные "перестроечные" года). Со временем появляется все больше книг, так или иначе касающихся Спектрума, однако там нет ни слова о том, о чем пойдет речь ниже...
Существует множество нигде не документированных возможностей Z80, которые не описаны ZILOG ни в каких документах. Однако программы, которые используют эти возможности, существуют (и, разумеется, работают).
Подавляющее количество инструкций ассемблера однобайтовые, т.е. состоят из одного байта, собственно, кода операции и операнда: байта или слова. Четыре байта CB, DD, ED и FD - это байты, которые меняют смысл кодов, следующих за ними. Существуют 248 CB-инструкций. Однако комбинации с CB30 до CB37 опущены из официального списка. Эти инструкции обычно дизассемблируются как мнемоники SLL-Shift Left Logical, которые сдвигают операнд влево и устанавливают 0-й бит операнда. Например, эту инструкцию используют программы Bouder и Enduro Racer. И таких программ довольно много...
Инструкции, начинающиеся с байтов DD и FD предполагают использование регистров IX и IY. Посмотрите внимательно, как они работают:
2A nn LD HL,(nn)
DD 2A nn LD IX,(nn)
7E LD A,(HL)
DD 7E d LD A,(IX+d)
Но это вещи хорошо известные. Когда Вы видите инструкцию DD2Ann, то она воспринимается Вами как очевидная.
Однако, если инструкция использует регистр H или L, то байт-префикс позволяет работать Вам со старшей или младшей половиной регистра IX или IY.
Например:
44 LD B,H
FD 44 LD B,IYh
Эти типы неофициальных инструкций используются огромным количеством программ. Другие типы DD и FD инструкций, не приведенные выше, можно лишь использовать с полезностью, не большей NOP. Некоторую подряд DD или FD можете попробовать распечатать MONSом (посмотрите результат сами)...
Я не встречал программ, которые использовали бы неофициальные ED инструкции, такие как ED6Bnn - "длинная" версия 2Ann, LD HL,(nn).
Ну а теперь о регистре R, точнее о том, по какому закону происходит его изменение... Попросту говоря, регистр R - это счетчик, который обновляется после каждой инструкции, причем DD, FD, ED и CB процессор "воспринимает" как отдельные инструкции! Т.е. инструкции с такими префиксами увеличивают R на 2. Но существует интересная особенность: "двойные" префиксы, такие как DDCB и FDCB увеличивают R также на 2! LDI увеличивает R на два, LDIR на 2*BC (также как и LDDR).
Последовательность LD R,A/LD A,R увеличивает А на 2, кроме старшего бита (7-го): Этот бит регистра R не изменяется. Происходит это потому, что ранее использовались 16KBitные микросхемы, где биты группируются в матрицу 128x128, т.е. для доступа к ним необходимо лишь 7 бит... Во многих программах регистр R используется как база для реализации генератора случайных чисел.
Следующие несколько страниц будут верны лишь для машин с "раздельным полем памяти", т.е. на плате это выглядит как 8 штук K565РУ6 & 8 штук K565РУ5 (например, версия схемы МОСКВА-48). Ну и, конечно, нижеследующее будет верно для "фирменного" Спектрума с 48k RAM.
Если у Вас одна из таких машин, Вы можете посмотреть, как работает регистр R при регенерации памяти. (Нижеследующая программа также будет полезна тем, кто хочет определить, с каким "полем памяти" у него машина.)
Введите программу:
ORG #7530
DI
XOR A
LD B,A
L1 XOR A
LD R,A
DEC HL
LD A,L
OR H
JR NZ,L1
DJNZ L1
EI
RET
Запустите эту программу. Когда она отработает (это произойдет через несколько минут), посмотрите содержимое "верхних" 32k. Лишь несколько первых байт из каждых 256-и будут содержать ту информацию, которая в них находилась. Содержимое этих байт не изменится, потому что они успеют регенерировать за время "тела цикла"...
ULA оперирует с памятью в диапазоне #4000-#7FFF, процессор "верхним" диапазоном памяти и ПЗУ составляет диапазон #0000-#3FFF, каждая из этих составляющих всю память работает с различной скоростью и независимо друг от друга. Шины данных и адреса Z80 и ULA соединяются с помощью сопротивлений малой емкости; это дает очень эффективный доступ к памяти. Если Z80 нужно прочитать или записать данные в "нижние" 16k в то время, когда ULA занята чтением, процессор приостанавливается, а когда этот процесс закончит, ULA позволяет получить доступ к "нижним" 16K непосредственно через сопротивления. Это необычайно эффективно. Когда Вы запускаете программу в "нижних" 16k RAM или пишите-читаете эту память, процессор слегка "подвисает". Поэтому эта часть памяти медленнее, чем верхние 32k. Именно поэтому никогда не пишите программы типа ввод/вывод в этих "нижних" 16k RAM (также это относится к написанию подпрограмм, связанных с воспроизведением звуков через встроенный динамик).
Из всего вышесказанного следует, что если Вы напишете такие подпрограммы на машине с "общим полем памяти", то когда Вашу программу запустят на "фирменном" Спектруме, в случае синхро-ввода/вывода программа просто не будет работать, а в случае со звуками Ваша музыка будет "непрезентабельной". К этому же относится чтение порта FE, поскольку ULA "поставляет" его значение. Каждый раз, когда Вы будете читать этот порт, ULA временно останавливает процессор, потому чтение значения из этого порта несколько медленнее, чем из других портов. Приведу факты: обычно IN A,(nn) выполняется процессором за 11T (тактов), однако это время возрастает до 12.15T, если nn=FE (приведено, разумеется, среднее значение).
На тему чтения несуществующих портов, порта FF, о вопросах синхронизации экрана, прерываниях, степени "совместимости" программ на различных компьютерах (т.е. отчего одна программа работает на одном Спектруме и не работает на другом ...), специальных эффектах, совместимости различных версий TR-DOS и о многом другом планируется еще один разговор. Поскольку я немного отошел в сторону от темы данной статьи, я продолжаю...
Есть еще один, но далеко не единственный "темный угол", им пользуются программы Sabrewulf, Ghosts'n Goblins, а также защита Speedlock. Это загадка недокументированных флагов. Биты 3 и 5 регистра флагов F не используются.
Казалось бы, Вы можете их установить или сбросить, используя лишь POP AF и PUSH AF. Однако эмпирическим путем (т.е. методом научного тыка) было определено, что значение этих битов зависит от 8-и бит результата последней инструкции, которая воздействует на обычные биты регистра флагов F. (Уфф, ну и сказал).
Пример 1:
После ADD A,B биты 7,5 и 3 будут идентичны битам регистра А (бит 7 регистра F - бит знака, понятно, что он также берется из 7-го бита A).
Пример 2:
После инструкции CP x (где x, разумеется, регистр, (HL) или константа), в недокументированных битах будут находятся биты аргумента.
Рассмотрим инструкции, которые оперируют с 16-битовым словом. В этом случае значение недокументированных битов следует брать из старших 8-ми бит результата. Так, S-флаг берем из 15-го бита результата.
За примером программы, которая использовала бы недокументированные биты регистра F, далеко ходить не надо. Возьмем очень старую программу Sabre Wulf '84.
Носорог в этой программе бежит в одну, затем в другую сторону, благодаря следующей последовательности инструкций:
#AD86 DDCB067E BIT 7,(IX+6)
#AD8A F28FAD JP P,#AD8F
Не правда ли, оригинально!
Те, кто сталкивался на практике с системой защиты программ, называемой Speedlock, обратили внимание, что для того чтобы "пройти шагом" по программе далее, необходимо точнейшим образом обойти все ловушки, такие, как показано выше. К слову сказать, наши "отечественные" системы такого рода на базе вышесказанного смотрятся более чем скромно...
В заключение следует также сказать, что ROM для 128-го Спектрума использует AF для временного хранения адреса подпрограммы.
Как принято во всем цивилизованном мире, я передам огромное спасибо автору отменного эмулятора ZX-SPECTUM 48/128 + Sammy + Interface I & more...more... для IBM PC, Z80 v2.01:
Hello & thanx, Gerton A. Lunter!
Отдельные моменты его советов изложены выше.
Как уже было сказано, еще есть темы, о которых можно поговорить.
P.S.
Эту статью не следует воспринимать как Истину в последней инстанции (Истина находится в оригинальной "фирменной" документации, которой не существует). Любая неверно данная информация связана с моим возможным заблуждением относительно трактовки данного вопроса. Любая неполно(!) данная информация связана исключительно с моей неуверенностью в правильной трактовке данного вопроса, а не с нежеланием давать подобную информацию в силу других причин (если это не указано особо), за исключением "очевидных" вещей, где степень "очевидности" остается на моей совести. Поэтому Вы можете присылать любые дополнения и пр.
Любые претензии касательно СОДЕРЖАНИЯ по сути, высказанные в некорректной форме, не принимаются и не обсуждаются.
Автор не вступает в переписку с читателями ни под каким видом, однако присланная Вами информация будет полезна при подготовке материала следующих статей.
С уважением, Fanatic Stas.
* * *
- Экспертиза - Дмитрий Усманов
Детальный мануал по исследованию магического замка с акцентом на действия, такие как открытие сундуков и управление ресурсами. Обсуждаются стратегии выживания, взаимодействие с персонажами и решение загадок в замке Зоба. Включает управление опасными элементами и использование магических свойств.
- Штурм
Обсуждение игры Mindfighter с мнениями читателей, стратегиями и головоломками. Изучение механики игры через письма. Описаны трудности в прохождении и интерактивные элементы сюжета.
- Премьера
Введение нового раздела программного обеспечения с программой 'ЗАПИСНАЯ КНИЖКА' для ZX Spectrum от Андрея Егорова. Описание функционала и сравнение с аналогами. Также выделяется выпуск игры 'COLOR LINES', похожей на 'ТЕТРИС'.
- Обзор - Станислав Ефимов
Обзор шахматных программ для ZX Spectrum с акцентом на алгоритмы и функции. Подчеркиваются сильные и слабые стороны популярных программ, таких как IS-Chess, Spectrum Voice Chess и Colossus Chess 4. Предоставляет рекомендации по выбору шахматного софта.
- С миру по биту
Обсуждение различных игр и вопросов, связанных с ZX Spectrum, включая подробности об игре 'Lords of Chaos' и советы по игре 'Elite-2'.
- Система - Станислав Ефимов
Обсуждение недокументированных возможностей процессора Z-80 и их использования в программировании. Изучение неофициальных инструкций и их применения в программном обеспечении. Информация о работе с памятью и особенностях архитектуры ZX Spectrum.
- Реклама
Реклама покупки журнала 'SPECTROFON', приглашение авторам программ и предложение лицензий дистрибьюторам по России.