Выполнение команд сдвига регистров
Рисунок 5.3. Выполнение команд сдвига регистров
Алгоритм расчета адресов экрана достаточно сложен, поэтому, как и прежде, обратимся за помощью к ПЗУ, благо в «прошивке» Speccy имеются необходимые процедуры. Для получения начального адреса любой строки экрана можно обратиться к подпрограмме, расположенной по адресу 3742. Перед обращением к ней в аккумулятор необходимо поместить номер строки экрана. На выходе в регистровой паре HL получится искомый адрес, зная который, уже несложно рассчитать и любой другой адрес в пределах данной строки. Каждая строка имеет длину 32байта, которые расположены последовательно, и вмещает 8 рядов пикселей. При переходе к следующему ряду адрес видеобуфера увеличивается на 256, то есть увеличивается только старший байт адреса, а младший остается без изменений.
Для примера покажем, как рассчитать адрес второго байта сверху в 5-й строке и 11-й позиции экрана (иначе, в позиции печати, определяемой директивой Бейсика AT 5,11):
LD A,5 ;номер строки CALL 3742 ;получаем в HL начальный адрес LD A,L ;берем значение младшего байта адреса OR 11 ;добавляем смещение в 11 байт (знакомест) LD L,A ;возвращаем в младший байт INC H ;увеличиваем адрес на 256 и тем самым ; получаем адрес второго байта в ; знакоместе сверху
Теперь можно написать программу, дающую эффект бегущей строки. Для определенности будем скроллировать 21-ю строку экрана:
ORG 60000 LD A,21 ;21-я строка экрана SCRLIN CALL 3742 ;получаем ее адрес в HL ; Так как строка должна бежать слева направо, то раньше нужно сдвигать ; последние байты, поэтому определяем адрес конца строки LD A,L OR 31 LD L,A LD C,8 ;высота строки 8 пикселей SCRL1 LD B,32 ;длина строки 32 байта AND A ;очистка флага CY PUSH HL ;сохраняем адрес SCRL2 RL (HL) ;последовательно сдвигаем все байты DEC HL DJNZ SCRL2 POP HL ;восстанавливаем адрес INC H ;переходим к следующему ряду пикселей DEC C ;повторяем JR NZ,SCRL1 RET
Но это еще не все, ведь данная процедура сдвинет строку только на один пиксель влево, а для перемещения ее на знакоместо потребуется выполнить приведенную подпрограмму 8 раз. Однако прежде чем мы продолжим создание полноценного эффекта, поясним смысл некоторых использованных команд.
Возможно, вам не совсем ясно, что в данной подпрограмме делает инструкция AND A. Как сказано в комментарии к этой строке, она очищает флаг переноса. Собственно, это и все, что нам от нее требуется, но для чего это нужно? Посмотрите на схему перемещения битов командой RL S и увидите, что при ее выполнении бит из CY переходит в младший бит операнда, в то время как старший сохраняется во флаге переноса. Этим и обусловлен выбор именно команды RL (HL), ведь нам нужно скроллировать не отдельный байт, а целую цепочку байтов, значит, вытесняемый бит должен быть сохранен для следующей команды сдвига. Но сдвигая самый первый байт в цепочке, мы должны убедиться, что в младшем бите появится 0, поэтому и нужно сбросить флаг CY. Если этого не сделать, то в конце концов в скроллируемой строке может появиться какой-то нежелательный «мусор» в виде «включенных» пикселей.
Надеемся, что этих объяснений достаточно, а если нет, то попытайтесь мысленно проследить, что происходит в результате выполнения команды RL (HL) на каждом «витке» цикла, обозначенного меткой SCRL2, какие биты и куда при этом сдвигаются.
А сейчас напишем небольшую тестовую программку на Бейсике, проверяющую работоспособность нашей процедуры. Постарайтесь после этого самостоятельно переписать ее на ассемблере, а когда справитесь с задачей, перелистните несколько страниц и проверьте себя, сравнив полученный результат с , данным в конце этого раздела.
10 INK 6: PAPER 0: BORDER 0: CLS 20 LET a$="Examine yourself how you know the assembler!" 30 FOR i=1 TO LEN a$ 40 PRINT AT 21,31; INK 0; a$(i) 50 FOR j=1 TO 8 60 RANDOMIZE USR 60000 70 NEXT j 80 NEXT i 90 FOR i=1 TO 256: RANDOMIZE USR 60000: NEXT i
Используя команды сдвигов, можно придумать великое множество интересных эффектов. Приведем маленький пример наиболее простого из них - циклического скроллинга отдельного знакоместа, и предоставим вам возможность пофантазировать и развить эту идею.
ORG 60000 LD B,8 LD HL,16384 ROL RRC (HL) INC H DJNZ ROL RET
Чтобы посмотреть, как эта программка работает, напечатайте в Бейсике в левом верхнем углу экрана какой-нибудь символ и в цикле вызывайте процедуру. Изображение должно многократно «провернуться» вокруг вертикальной оси, причем уходящие вправо точки будут вновь появляться с левого края. Если заменить команду RRC (HL) на RLC (HL), то скроллинг будет выполняться в обратную сторону.