Как написать игру для ZX Spectrum на ассемблере

         

ДИРЕКТИВЫ УСЛОВНОЙ ТРАНСЛЯЦИИ



ДИРЕКТИВЫ УСЛОВНОЙ ТРАНСЛЯЦИИ

Работая с GENS4, у вас есть возможность получать различные варианты исполняемого кода в зависимости от выполнения тех или иных условий. Достигается это включением в программу команд условной трансляции IF, ELSE и END, которые записываются в поле мнемоник (эти слова не относятся к зарезервированным и поэтому их можно использовать в качестве меток, но не макрокоманд). Общий вид текста программы при этом будет таким:

......... IF выражение команды_1 [ELSE команды_2] END .........

Команда ELSE и следующий за ней блок инструкций «команды_2» являются необязательной частью условной конструкции, поэтому в данном примере они заключены в квадратные скобки. Если значение выражения после команды IF истинно (то есть не равно нулю), то транслируется блок команд «команды_1» до ELSE или, если его нет, до END. В противном случае (если значение выражения равно нулю) ассемблируются «команды_2» после ELSE, конечно, если эта команда указана. После END трансляция текста протекает как обычно.

Часто эти команды используются для получения различных версий одной и той же программы, одна из которых, например, предназначена для работы на «обычном» Speccy, другая на ZX Spectrum 128 и т. п. Но, на наш взгляд, наиболее полезными они оказываются при написании макроопределений. В этом случае макрос можно составить таким образом, чтобы в зависимости от задаваемых в макрокоманде параметров получался максимально компактный код. Рассмотрим такой пример:

CHAN MAC IF =0 LD A,=0 ;если первый параметр не 0 ELSE XOR A ;если параметр равен 0 END CALL 5633 ENDM

Встретив в тексте макрокоманду CHAN, ассемблер обратится к одноименному макросу и в первую очередь проверит значение первого параметра =0. Если его величина отлична от 0 (условие истинно), то транслируется команда LD A,N, затем ассемблирование продолжается после команды END. В противном же случае, то есть если заданный параметр равен 0 (условие ложно), то обрабатываются команды после ELSE, в данном случае - XOR A и далее текст транслируется, как и в предыдущем варианте. Поэтому после трансляции макрокоманды


CHAN 2

получится последовательность инструкций

LD A,2 CALL 5633

а если задать

CHAN 0

то такая макрокоманда оттранслируется иначе:

XOR A CALL 5633

Приведем другой, более серьезный пример применения команд условной трансляции в макросах:

ORG 60000 UP EQU 1 DN EQU %10 RT EQU %100 LF EQU %1000 SCRL MAC PUSH BC LD HL,=1*256+=0 LD (COL),HL LD HL,=3*256+=2 LD (LEN),HL IF =4 & UP ;если 5-й параметр = UP CALL SCR_UP END IF =4 & DN ;если 5-й параметр = DN CALL SCR_DN END IF =4 & RT ;если 5-й параметр = RT CALL SCR_RT END IF =4 & LF ;если 5-й параметр = LF CALL SCR_LF END POP BC ENDM ; ------ LD B,16 SCRL1 SCRL 10,4,5,7,UP DJNZ SCRL1 LD B,16 SCRL2 SCRL 10,4,5,7,RT DJNZ SCRL2 LD B,16 SCRL3 SCRL 10,4,5,7,DN DJNZ SCRL3 LD B,16 SCRL4 SCRL 10,4,5,7,LF DJNZ SCRL4 RET

COL DEFB 0 ROW DEFB 0 LEN DEFB 0 HGT DEFB 0

В выражениях ассемблера GENS отсутствует знак равенства, но из этого затруднения можно выйти, если употребить поразрядную операцию «И» - AND, обозначаемую символом «амперсанд» (&), а в соответствующем параметре использовать отдельные биты, указывающие на различные действия. В приведенном макросе после определения графических переменных COL, ROW, LEN и HGT в зависимости от последнего параметра вызывается одна из четырех процедур скроллингов (напомним, что сами процедуры были описаны в 6-й главе). Как видите, благодаря командам условной трансляции стало возможно объединить их в одном макросе. В результате и текст программы заметно сократился и стал значительно более удобочитаемым. Правда, при этом несколько возрос размер исполняемого модуля, но этот недостаток также можно устранить, слегка доработав макрос. Например, можно добавить еще один условный блок в самом начале, в котором проверяется значение самого первого параметра и только если он не равен 0, транслируются команды определения переменных, а в противном случае они будут пропускаться.


Содержание раздела