(c) Иван Рощин, г.Москва, 1997
Время выполнения
недокументированных команд
процессора Z80
В "ZX-РЕВЮ" уже был опублико-
ван ряд статей, посвященных не-
документированным командам Z80,
но ни в одной из них я не смог
найти упоминания о времени вы-
полнения этих команд. Не секрет,
что их часто используют имен-
но для повышения быстродействия
программы (а также для уменьше-
ния ее размера и затруднения от-
ладки). Поэтому я решил опреде-
лить время выполнения опытным
путем, для чего была написана
следующая программа:140.
ORG #6000
;Устанавливаем 2-й режим прерываний,
;обработчик будет по адресу #6262:
DI
LD A,#80 ;таблица будет
LD I,A ;по адресу #8000
LD HL,#8000 ;заполняем
LD (HL),#62 ;таблицу...
LD DE,#8001
LD BC,#100
LDIR
IM 2
LD A,#C9 ;заносим код RET,
LD (#6262),A;чтобы проц. обр.
;прерываний
;ничего не делала
LD HL,0 ;обнулили счетчик
EI
HALT ;ждем прерывания
;Поступил сигнал прерывания, происходит
;следующее:
; - процессор запоминает адрес следующей
; команды программы в стеке;
; - просматривает ячейку, указанную
; шиной данных +256, умноженное на
; содержимое регистра I;
; - передает управление по адресу,
; содержащемуся в этой ячейке (в данном
; случае - по адресу #6262).
;
; На это тратится 18 тактов.
;
; - по адресу #6262 сейчас находится
; команда RET, ее выполнение занимает
; 10 тактов.
;Заменяем эту команду RET на NOP:
XOR A ; 4 такта
LD (#6262),A ; 13
NOP ; 4
NOP ;задержка ; 4
NOP ;во избежание ; 4
NOP ;повторного ; 4
NOP ;захвата ; 4
NOP ;прерывания ; 4
NOP ; 4
NOP ; 4
EI ; 4
;Итак, с момента получения сигнала
;прерывания прошел уже 81 такт.
;Теперь начинаем выполнять в цикле
;последовательность команд,
;при каждом выполнении цикла содержимое
;HL увеличивается на 1.
LOOP1 INC HL ; 6 тактов
;Здесь находится анализируемая команда:
NOP
;Если команда влияет на HL, вместо нее
;можно записать последовательность
;PUSH HL: КОМАНДА :POP HL.
JR LOOP1 ; 12 тактов
;Таким образом, на каждое выполнение
;цикла будет затрачено 18+t тактов,
;где t - время выполнения анализируемой
;команды.
;Сюда будет передано управление, как
;только поступит следующий импульс
;прерывания.
;В HL будет кол-во выполнений цикла.
END RET
;**************************************
;Обработчик прерывания:
ORG #6262
NOP
;В процессе выполнения сюда сначала
;ставится RET, а потом NOP. Если выходить
;из обработчика с помощью RET, снова
;попадем в цикл, что совсем не нужно.
INC SP
INC SP
IM 1
EI
JP END
2
Чтобы определить время выпол-
нения какой-либо команды процес-
сора с помощью этой программы,
необходимо подставить команду
вместо NOP, скомпилировать прог-
рамму и запустить ее из отладчи-
ка STS с помощью команды [C]
#6000. После этого нужно рас-
смотреть содержимое регистра HL
(естественно, сама анализируемая
команда не должна влиять на этот
регистр). Из текста программы
ясно, что существует такое соот-
ношение:
81+(18+t)*x = T
Здесь t - время выполнения ана-
лизируемой команды в тактах;
x - число выполнений цикла (со-
держимое HL);
T - число тактов между прерыва-
ниями.
Прежде всего нужно определить
число тактов между прерываниями,
так как для разных моделей ком-
пьютеров оно различно. Для этого
в качестве анализируемой команды
подставляем NOP, время выполне-
ния которого равно четырем так-
там. Получаем следующее соотно-
шение:
T = 81+22*x
Для моего "Пентагона-128" x =
#CB7. После подстановки в форму-
лу получим T = 71691 такт. Хотя
при таком способе измерения быс-
тродействия погрешность может
достигать времени выполнения
цикла (в данном случае 22 так-
та), на дальнейшие расчеты это
мало повлияет.
Теперь попробуем измерить
время выполнения какой-нибудь
команды, например, LD IX,#1234
(истинное время выполнения 14
тактов). Подставляем ее вместо
команды NOP и запускаем програм-
му, как и в предыдущем случае.
После этого время выполнения на-
ходится по формуле:
T-81
t = ────── - 18
x
Для моего компьютера x =#8BE,
тогда t = 13,9973. Как видим,
при таком способе измерений дос-
тигается неплохая точность.
Теперь я приведу найденные
этим способом оценки времени вы-
полнения некоторых недокументи-
рованных команд:
┌──────────────┬──────────┬─────────────┬──────────────┐
│Мнемоника │Код │Содержимое HL│Время в тактах│
├──────────────┼──────────┼─────────────┼──────────────┤
│LD HX,N │DD 26 N │ #9A5 │11 │
│LD LY,N │FD 2E N │ #9A5 │11 │
│LD HX,A │DD 67 │ #AC2 │8 │
│LD LX,LX │DD 6D │ #AC2 │8 │
│ADD A,HX │DD 84 │ #AC2 │8 │
│SLI A │CB 37 │ #AC2 │8 │
│SLI (HL) │CB 36 │ #87A │15 │
│SLI A,(IX+S) │DD CB S 37│ #6D3 │23 │
│SRL A,(IX+S) │DD CB S 3F│ #6D3 │23 │
│SET 0,A,(IX+S)│DD CB S C7│ #6D3 │23 │
│INF │ED 70 │ #953 │12 │
│OUT (C),* │ED 71 │ #953 │12 │
└──────────────┴──────────┴─────────────┴──────────────┘
Все команды, которые получа-
ются с помощью добавления пре-
фиксов #DD и #FD, в том числе и
недокументированные, выполняются
на 4 такта дольше, чем те же ко-
манды без префикса, а регистр R
при их выполнении дополнительно
увеличивается на 1. Это не каса-
ется команд с индексной адреса-
цией, таких как LD A,(IX+S).
Команда SLI выполняется с та-
кой же скоростью, как команды
SRL, SRA и SLA.
Выполнение команд, помещающих
результат кроме ячейки памяти,
адресуемой IX или IY, в регистр,
занимает столько же времени,
сколько и для обычных вариантов
этих команд.
Команды INF и OUT (C),* вы-
полняются так же быстро, как и
другие команды ввода/вывода,
т.е. 12 тактов.
* * *