Операции нал блоками
В этой главе рассматривается последний набор очень полезных программ, в нескольких
последующих главах мы будем иметь дело с командами, которые приятно иметь под рукой и ко-
торые при определенных обстоятельствах играют свою роль, но в общем вы должны уметь
писать машинные программы на машинном языке с помощью уже известного вам материала.
Тем не менее, обязательно прочтите главу о планировании вашей программы на машинном
Рассматриваемые в этой главе команды по самой своей природе способны одним махом охва-
тывать длинные конструкции быстрее летящей пули иными словами, команды, обрабатывающие
целые блоки памяти, а не отдельные 8-битовые байты.
Давайте начнем с простейшей из них:
CPI при вашем знании язька Z80, вы должны сразу распознать одного из представителей
семейства "сравнений", и на самом деле это и есть расширенное сравнение.
По-русски она читается "сравнить и д^ть приращение". (Вы помните, что сравнивать что
бы то ни было можно только с содержимым регистра "а", и об этом в команде не требуется
упоминать).
Команда "СРГ сравнивает "а" с (HL) и автоматически увеличивает HL. Зто означает, что
после операции CPI HL уже указывает на следующую ячейку и готов к повторению ее.
С помощью этой команды мы могли бы написать программу просмотра всей памяти в поисках
конкретного совпадения следующим образом:
SEARCH CPI
JR N2,SEARCH
SEARCH - поиск
При таком способе, пока не будет обнаружено совпадение (будет установлен флаг нуля,
как во всех операциях сравнения) программа будет продолжать просмотр.
К сожалению, это - не такая хорошая идея, поскольку, если совпадение не будет обнару-
жено, программа никогда не закончится! (С счастью конструкторы языка Z80 позаботились об
этом, и команда CPI также автоматически уменьшает вс!
Поэтому мы можем по желанию выбирать длину блока, который мы хотим просмотреть, и та-
ким образом задать конец просмотра.
Давайте предположим, что длина просматриваемого нами блока не превышает 255 байтов,
так что счетчик вс будет храниться только в регистре с, тогда мы могли бы написать:
SEARCH CPI
JR Z, FOUND
INC с
DEC с
JR NZ, SEARCH
NO FOUND...........
FOUND...........
SEARCH - поиск; FOUND - найдено; NOT FOUND - не найдено.
Очевидно, если бы длина блока превышала 255 байтов, нужна была бы другая программа.
Обратите внимание на применение команд INC и DEC для проверки условия с= 0. Зти две ко-
манды требуют по одному только байту каждая, и поскольку обе они действуют на Флаг нуля,
результат их действия состоит в том, что флаг устанавливается только если "с" был перво-
начально равен нулю. Еще одно преимущество состоит в том, что при таком написании прог-
раммы не изменяются никакие другие регистры.
Теперь мы могли бы также захотеть просмотреть блоки памяти начиная с вершины, а не с
конца, и поэтому нас имеется команда:
которая по-русски читается "сравнить и уменьшить". Уменьшение, конечно, относится к HL, а
результат для вс - тот же самый!
Еще большими возможностями, чем зти две команды, обладают следующие истинные титаны в
мире K0Ma^jR
CPDR
они читаются: "сравнить, увеличить и повторить"
и "сравнить, уменьшить и повторить".
Зти двухбайтовые команды обладают невероятными возможностями: они позволяют ЦП автома-
тически продолжить просмотр блока памяти до тех пор, пока либо не будет найдено совпаде-
ние, либо не будет достигнут конец блока. (Естественно, нам нужно указать a, HL и вс пе-
ред началом, но даже при этих условиях это - невероятно экономичный способ записи)
Поскольку завершение работы этой команды происходит в двух возможных случаях (а имен-
но, при найденном совпадении в середине блока и при отсутствии совпадения вообще), нам
необходимо обеспечить наличие некоторого текста в конце, чтобы проводить различие между
этими двумя возможностями.
Вам, однако, следует знать, что вне зависимости от скорости выюлнения программ на ма-
шинном языке CPIR и другие аналогичные команды могут отнимать очень много времени.
Команда CPIR, например, затрачивает 21 цикл на поиск каждого байта. Конечно, каждую
секунду выюлняется 3 500 000 циклов, 1 но даже с учетом этого поиск среди 3 500 байтов
требует 1/50 секунды.
Зто может показаться вам не очень длительным временем, но если учесть, что выдача
изображения на дисплей осуществляется каждые 1/50 секунды или около того, вы поймете, что
это может оказаться важным.
Остальные блочные операции строятся вокруг идеи перемещения информации.
Вот они:
LDI LDIR
LDD LDDR очевидно, они относятся к семейству "загрузок" и
читаются как:
загрузить и дать приращение;
загрузить, дать приращение и повторить;
загрузить и уменьшить;
загрузить, уменьшить и повторить;
Разберем сначала самую простую из них, "LDI" - это на самом деле комбинация следующего
набора действий:
загрузить (HL) в (DE),
дать приращение DE, HL,
уменьшить вс.
Обратите внимание, что это - единственная команда, загружающая из одной ячейки памяти
в другую без необходимости загрузки сначала в регистр.
Применение регистра "DE" в качестве адреса-цели очень разумно, так вы никогда не забу-
дете, в каком регистре содержится адрес-цель! (В оригинале используется мнемоника: "DE"
DE-STINATION (адрес-цель) (примеч. Пер. ).
Симметричная этой команде LDD совершенно совпадает с этой, за исключением того, что в
процессе загрузки HL и DE уменьшаются. Разница между LDI и LDD оказывается важна в том
случае, когда два блока (тот, где информация находится, и тот, в который она направля-
ется) пересекаются.
Предположим, мы применяем эту команду в прикладной задаче текстовой обработки и хотим
удалить слово из предложения:
THE BIG BROWN DOG JUMPED OVER THE FOX.
(Большая коричневая собака перепрыгнула через лису).
1357913579135/91357 9
Если мы хотим удалить слово "BROWN" (коричневая), то нам нужно только сдвинуть осталь-
ную часть предложения влево на 6 литер.
DE = цель = литера 9
HL = источник = литера 15
вс = счетчик = 24 литеры.
Давайте начнем с LDI: после первой команды у нас будет первоначально = THE BIG BROWN
DOG JUMPED OVER THE FOX. Сдвиг на 1 литеру: D (—-D новое предложение= THE BIG DROWN DOG
JUMPED OVER THE FOX. В HL = 10. DE = 16, вс = 23. После двух следующих команд:
THE BIG DOGWN DOG JUMPED OVER THE FOX.
И после того как все команды выполнены:
THE BIG DOG JUMPED OVER THE FOX. E FOX.
(Если бы мы хотели, чтобы часть предложения после точки была заменена пробелами, то этого
можно было бы достигнуть за счет добавления пробелов в конце первоначального предложения
и увеличения вс, скажем, до 30).
Если мы теперь решили обратить этот процесс и возвратить слово "BROW в предложение,
то нам нужно просто снова применить команду "LDI", поскольку мы забьем информацию, кото-
рую мы хотим сдвинуть:
например, HL = источник = литера 9
DE = цель = литера 15
вс « счетчик = 24 литеры
После выполнения одной команды у нас будет:
первоначально = THE BIG DOG JUMPED OVER THE FOX. E FOX.
Сдвиг на литеру D—) D
новое предложение = THE BIG DOG JUDPED OVER THE FOX. I FOX.
После выполнений 6 команд мы получим:
THE BIG DOG JUDOG JUVER THE FOX. E FOX.
Пока все хорошо. Но после выполнения следующих трех команд получим:
THE BIG DOG JUDOG JUD OG THE FOX. E FOX.
Трудность состоит в том, что мы забили информацию, которую мы хотели перемещать. Вы
можете проверить это, пытаясь переместить по одному символу вручную.
Поэтому лучше использовать команду "LDI" с регистром DE, указывающим на конец предло-
жения. Зто гарантирует что информация не будет забита при перемещении. (В оригинале,
очевидно, опечатка, W0LL вместо dILL. (Примеч. Пер. ).
Команды "LDIR" и "LDDR" обладают еще большими возможностями, они могут быстро переме-
щать тысячи байтов.
Более релко используемые команлы Z80
Первая команда такова:
h AF, AF"
она делает в точности то, что подсказывает ее название: " обменять пары регистров AF и
AF" .
Следующая общая команда обмена такова:
это команда "обменивает" все остальные 8-битовые регистры следующим образом:
вс в" с"
D e (-) D" e"
н L h" L"
Поэтому это - очень мо1цная команда, но именно ее возможности делают ее ограниченной в
применении. Так происходит потому, что она действует на все регистры сразу, и невозможно
оставить ни одно значение.
(За исключением регистра 'а", на который "ехх" не действует).
Единственный способ преодолеть эту трудность - написать короткую программу такого ти-
па:
PUSH HL
ехх
pop HL
Зто означает, что вы запомнили значения вс, DE и HL в наборе альтернативных регистров,
но по-прежнему оставляем для работы HL.
Последняя команда из этой группы на самом деле не относится к типу "переодевания пер-
чаток":
de ex DE, HL в этой команде задаете» перекрести* обмен содершь* регистра HL и
Зта команда на самом деле очень полезна, поскольку, как мы видели, HL - привилегиро-
ванная пара регистров во многих прикладных задачах, и есть ситуации, когда нужное нам
значение для обработки находится в DE.