Ликбез - Ассемблер взгляд издалека: О блочных командах, работа c портами.
Ассемблер - взгляд издалека
Продолжение.
Начало в || 20, 21, 24, 25, 28-30, 32
{}Инфарх, 1999
Поговорим о блочных командах
Рассмотрим следующий пример. Требуется
перенести блок данных длиной в #1B00 байт,
расположенный по адресу #C000, в адрес
#4000.
Программа, выполняющая такое действие,
может выглядеть примерно так:
LD HL,#C000
LD DE,#4000
LD BC,#1B00
LOOP LD A,(HL)
LD (DE),A
INC HL
INC DE
DEC BC
LD A,B
OR C
JR NZ,LOOP
RET
Этот фрагмент для решения нашей задачи
вполне подходит в случае, если перенос
должен происходить относительно быстро. Но
если скорость для вас - не главное, то его
можно и укоротить. А заодно - изучить но-
вую команду ассемблера LDI. Оная выполняет
действия:
LD (DE),(HL) ;такой команды на
;самом деле нет у Z80
INC HL
INC DE
DEC BC
При этом, если содержимое BC равно нулю,
то флаг P/V будет установлен в 0.
Теперь попробуем переписать пример с
учётом новой информации:
LD HL,#C000
LD DE,#4000
LD BC,#1B00
LOOP LDI
JP PE,LOOP
RET
Таким образом, программа получилась уже
короче.
Но разработчики Z80 не остановились на
достигнутом и предусмотрели команду LDIR,
предназначенную для переноса целого блока.
Как и в предыдущем примере, начало блока
помещается в регистровую пару HL, длина -
в BC, а адрес, куда произойдт перенос, на-
ходится в DE.
Изобразим схематически её действие:
LOOP LDI
JP PE,LOOP
Теперь наш пример теперь может быть за-
писан так:
LD HL,#C000
LD DE,#4000
LD BC,#1B00
LDIR
RET
Область экранной памяти в нашем примере
была выбрана не случайно. Загрузите некий
экранный файл (#1B00 байт) по адресу #C000
и выполните пример. Результат будет нагля-
ден. Кстати сказать, таким образом можно
не только создавать экраны, а и чистить
области памяти. Попробуйте:
LD HL,#4000
LD DE,#4001
LD BC,#1800
LD (HL),L
LDIR
LD BC,#2FF
LD (HL),7
LDIR
RET
Итак, что оно такое? Начало понятно, это
настройка HL на начало экранной памяти. Но
в DE помещается значение на единицу
больше, а по адресу #4000 помещается "0"
(пробел для экрана). Tеперь начинает рабо-
тать команда LDIR. Хоть она и предназначе-
на для работы с блоками, но перенос проис-
ходит всё равно по одному байту. Таким об-
разом, каждый раз команда будет переносить
в следующий адрес содеримое предыдущего
(0), и так до того момента, пока BC не об-
ретёт нулевое значение.
Вот экран и очищен. Но это касалось
только графической области, остались ещё и
атрибуты. Вторая половина процедуры ис-
пользуется именно для них. Здесь уже не
надо задавать значение для HL и DЕ, оно
осталось от первого LDIR'а. Надо только
задать длину области атрибутов #300-1 (а
почему оно так - подумайте сами) и в её
начало поместить байт атрибута. Мы ис-
пользовали 7, а значит, экран будет иметь
чёрную "бумагу" и белые "чернила".
А вот теперь... теперь начинается самое
стр-р-рашное!
Команды LDI и LDIR - далеко не единс-
твенные для работы с блоками. Есть ещё LDD
и LDDR.
Но не волнуйтесь! Разобрться с ними
весьма просто. Дело в том, что они произ-
водят действия почти полностью аналогичные
командам LDI и LDIR, но значения DE и HL
не увеличиваются, а уменьшаются. Примерно
так:
;команда LDD
LD (DE),(HL)
DEC HL
DEC DE
DEC BC
;команда LDDR
LOOP LDD
JP PE,LOOP
Спросите, зачем оно надо?
А очень просто!
Действительно, если при переносе блоков
они друг друга не перекрывают, разницы ни-
какой нет. Но представьте себе, что
"блок-приёмник" своим началом накрывает
окончание "блока-источника". Тогда перенос
методом LDIR повредит информацию. Выходом
из данной ситуации и служит команда LDDR.
Просто надо задать в DE и HL адреса блоков
не начальные, а конечные. Длина, ес-
тественно, остаётся без изменения.
Ну, с одним кошамром мы разобрались, те-
перь перейдём к другому. Итак...
Работа с портами
Так вот - оказывается, для работы с пор-
тами тоже есть свои хитрые групповые опе-
рации!
Для начала рассмотрим мутантов команды
IN. Начнём с чего попроще, например, INI:
;пример команды INI
IN (HL),(C); (сам придумал)
INC HL
DEC B
Достаточно понятно, вроде. Происходит
чтение из порта с заданным адресом в ре-
гистр C, полученный байт пересылается в
память по адресу, указанному в регистровой
паре HL, а регистр B страдает от декремен-
та, в результате чего флаг Z или сбросит-
ся, или установится.
Теперь посмотрим на более извращённый
вариант:
;пример команды INIR
LOOP INI
JR NZ,LOOP
Налицо явная аналогия с LDI и LDIR.
А чтобы сия аналогия была более полной,
расскажу о командах IND и INDR:
;пример команды IND
IN (HL),(C)
DEC HL
DEC B
;пример команды INDR
LOOP IND
JR NZ,LOOP
Вот и все сложности. Насколько мне ка-
жется, проблем при освоении этих команд у
вас возникать не должно.
Но это были мутанты команды IN, а есть
ещё и от OUT. Не вдаваясь в пустые рассуж-
дения, сразу приведу их:
OUTI, OUTD, OTIR, OTDR
А учитывая то, что их действие до отвра-
щения похоже на всё, о чём вы уже узнали,
попробуем обойтись без излишних подробнос-
тей. Из схем действия команд вам наверняка
всё станет ясно:
;пример команды OUTI
OUT (C),(HL)
INC HL
DEC B
;пример команды OTIR
LOOP OUTI
JR NZ,LOOP
;пример команды OUTD
OUT (C),(HL)
DEC HL
DEC B
;пример команды OTDR
LOOP OUTD
JR NZ,LOOP
Ну, что я говорил? Всё до безобразия по-
нятно. Но если всё-таки вопросы возникнут,
спрашивайте. По мере сил постараюсь на них
ответить.
Итак, с групповыми операциями мы разоб-
рались. Осталось только, по давней нашей
традиции, поведать...
О влиянии групповых операций на флаги
Как всегда, таблица нам в этом поможет.
╔═══════════╤═══════════════╗
║ Мнемоника │ Флаги ║
║ операции ├───────────────╢
║ │ C Z P/V S N H ║
╟───────────┼───────────────╢
║ LDI │ . . x . 0 0 ║
║ LDD │ . . x . 0 0 ║
║ LDIR │ . . 0 . 0 0 ║
║ LDDR │ . . 0 . 0 0 ║
║ INI │ . x ? ? 1 ? ║
║ IND │ . x ? ? 1 ? ║
║ INIR │ . 1 ? ? 1 ? ║
║ INDR │ . 1 ? ? 1 ? ║
║ OUTI │ ? x ? ? 1 ? ║
║ OUTD │ ? x ? ? 1 1 ║
║ OTIR │ ? 1 ? ? 1 ? ║
║ OTDR │ ? 1 ? ? 1 ? ║
╚═══════════╧═══════════════╝
А вот теперь действительно всё... на се-
годня. А вообще-то нам с вами ещё долго
предстоит "Учиться, учиться, и учиться".
Но это потом, а пока - до свидания!
Продолжение следует...
──══════════──
Другие статьи номера:
|
|
|
|
|
|
|
|
Ликбез - Ассемблер взгляд издалека: О блочных командах, работа c портами.
|
|
|
|
|