- - - - -- --- ----─-────-───────-────-─--- --- -- - - - -
Влияние команды OUTD на флаг переноса
- - - - -- --- ----─-────-───────-────-─--- --- -- - - - -
$% Иван Pощин
При написании одной программы мне понадобилось наиболее
оптимально (по объему) реализовать запись данных в первые 11
регистров музыкального сопроцессора из области памяти
#8000-#800A. Сначала я сделал это так:
LD HL,#800A
M1 LD BC,#FFFD
OUT (C),L
LD B,#BF
OUTD
BIT 7,L
JR Z,M1
При трассировке я заметил, что при последнем повторе цикла
после команды OUTD флаг C оказался равным 1 (а при предыдущих
повторах цикла он был сброшен). Естественно, этот факт был тут
же использован для оптимизации:
LD HL,#800A
M1 LD BC,#FFFD
OUT (C),L
LD B,#BF
OUTD
JR NC,M1
Мне стало интересно, почему так получается, и я решил
подробнее разобраться в этом вопросе...
В различных справочниках про влияние команды OUTD на флаги
написано, что, во-первых, она устанавливает в 1 флаг N, и
во-вторых, если в результате выполнения команды регистр B
обнуляется, то флаг Z = 1, иначе он равен 0. Про остальные флаги
сказано лишь, что их значения после выполнения команды не
определены.
Я предположил, что флаг переноса устанавливается, когда при
уменьшении HL изменяется регистр H (как в приведенном примере,
когда HL уменьшается с #8000 до #7FFF). При проведении
экспериментов это подтвердилось, но при одном условии: в ячейке
памяти, адресуемой HL, должен быть не 0. Если там будет 0, то
флаг C всегда будет сброшен.
Знание этой особенности Z80 позволяет в некоторых случаях
сократить программу и уменьшить время ее выполнения. Приведенный
выше пример это наглядно демонстрирует. Может быть, кому-то это
пригодится: бывает ведь, что при создании intro не хватает всего
одного-двух свободных байтов памяти...
Кстати, заодно выяснилось, что флаг N устанавливается в 1
далеко не всегда. Вот, проверьте сами: при HL=#8000, (HL)=0,
BC=#BFFD, после команды OUTD флаг N будет сброшен. А достаточно
при тех же значениях регистров поместить в (HL), скажем, #FF - и
после OUTD этот флаг будет установлен.
Эксперименты проводились на оригинальном процессоре Z80
фирмы ZiLOG и на отечественном аналоге КP1858ВМ1.
Эти особенности Z80 вполне естественно использовать для
проверки на выполнение программы под эмулятором. Hу а если вы
применяете их для оптимизации своей программы, приготовьтесь к
тому, что на эмуляторах она работать не будет...
Я понимаю, что, возможно, кто-то уже проводил подобные
исследования, и для него написанное мной не является секретом (и
уж точно знали об этом разработчики Z80). Hо мне такая
информация нигде не встречалась, и я решил сделать ее достоянием
общественности.
...