Давно спрашивали, но ответа не было... пускай будет))
Условимся, что машина без циклов wait. Считаем такты в исходном примере: 11+10+11+4+10 = 46, длина 7 байт.
Без использования стека как хранилища/приемника данных вариантов немного. Первый, без каких-либо опций со стеком:
ld hl ,from
ld de ,to
ld bc ,80-ширина спрайта ; b=0, c=смещение
ld a,с ; аккум хранит смещение, задается один раз перед выводом спрайта
ldi ldi ldi сколько надо
------ сама процедура перевода строки:
ld c,a ; восстанавливаем регистр
ex de, hl
add hl, bc
ex de, hl
------ все, дальше опять пошло ldi ldi ldi
Итого: 4+4+11+4 = 23 такта, 4 байта. Используем аккум, зато в 2 раза ускоряем процедуру.
Если код вывода свернут в цикл, счетчик можно организовать в половинке IX либо в альт. регистре
Второй способ нестандартный, используем регистр SP как константу:
ld (savesp+1), sp ; сохраняем стек
ld sp, смещение ; (80-ширина) грузим смещение в SP и больше его не трогаем
; задаем hl и de. аккумулятор не задействуется
ldi ldi ldi сколько надо
------ сама процедура перевода строки:
ex de, hl
add hl, sp
ex de, hl
------ все, дальше опять пошло ldi ldi ldi
savesp ld sp, 0 ; восстанавливаем sp, конец вывода
Итого 19 тактов, 3 байта. Разница с первым вариантом минимальна, но все зависит от конкретных условий применения.
Сразу видно ограничение: можно юзать только при запрещенных прерываниях, поскольку sp будет указывать в ПЗУ.
Однако можно красиво обойти его при одном условии: строки спрайта хранятся наоборот, от нижних к верхним, и выводятся так же.
В таком случае смещение задается отрицательное, т.к. нужно вернуться "назад" по экранным адресам, зато регистр sp будет указывать
на самый верх ОЗУ (#FFXX), который можно спокойно затереть (скажем, верхние 256 байт памяти резервируем и не трогаем).
Сама процедура аналогична предыдущей, можно юзать при разрешенных прерываниях.





Ответить с цитированием
