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

       

Операция сравнения


Программируя на Бейсике, вы привыкли, что в циклах можно задавать любые граничные значения управляющей переменной. Оказывается, в ассемблере это также возможно, хотя здесь и есть ряд ограничений, касающихся выбора регистра и, естественно, диапазона границ его изменения. В этом случае в качестве счетчика удобнее всего использовать аккумулятор, что избавит от необходимости применения дополнительных команд пересылок между регистрами. Перед началом цикла нужно занести в аккумулятор стартовое значение счетчика, а в конце сравнивать его с числом, до которого он должен измениться. Команда сравнения величины регистра A (и только его!) с числовым значением или с содержимым другого регистра записывается как CP (compare - сравнить), а в поле операндов помещается число или имя регистра, например:

CP 5 ;сравнить значение в аккумуляторе с числом 5

или

CP D ;сравнить содержимое аккумулятора с регистром D

Операция сравнения исключительно важна и ее применение, конечно, далеко не ограничивается только циклами, поэтому мы сочли необходимым привести возможные результаты сравнения регистра A с операндом X и используемые при этом мнемоники условий для переходов в табл. 5.1.

Таблица 5.1. Результаты операции сравнения



Результат сравненияСостояние флаговМнемоника условия
перехода
A = XZ = 1Z
A <> XZ = 0NZ
Беззнаковое сравнение (числа от 0 до 255)
A < XCY = 0C
A >= XCY = 0NC
Сравнение с учетом знака (числа от -128 до +127)
A < XS = 1P
A >= XS = 0M

Используя операцию сравнения, можно написать цикл, в котором регистр A изменяется, например, от 12 до 24:

LD A,12 ;задаем начальное значение в аккумуляторе CYCLE PUSH AF ;сохраняем в стеке ......... ;тело цикла POP AF ;восстановление аккумулятора INC A ;увеличение счетчика CP 25 ;сравниваем содержимое регистра A ; с числом 25 JR C,CYCLE ;переход на начало, если меньше 25 ; (меньше или равно 24)

В данном примере ничего принципиально не изменится, если команду JR C,CYCLE заменить на JR NZ,CYCLE - результат будет тем же, но если шаг цикла окажется отличным от единицы, то второй вариант может не сработать, поэтому предпочтительнее все же применять проверку флага переноса, а не нуля.


Приведенный вариант организации циклов уже почти повторяет такие строки Бейсика:

FOR N=12 TO 24 .............. NEXT N

Основное отличие, пожалуй, состоит лишь в одном: ассемблерный цикл в любом случае выполнит хотя бы один проход, независимо от граничных условий, ведь проверка здесь находится в конце цикла. Поэтому, чтобы исключить такой нежелательный эффект, в тех случаях, когда заранее неизвестны границы цикла, необходимо проверку производить в самом начале. Это лишь немногим усложнит программу, и она примет следующий вид:

;Предположим, что значение аккумулятора до начала цикла неизвестно CYCLE CP 25 ;проверяем на достижение конечного ; значения, то есть выполнение условия ; A > 24 (A >= 25) JR NC,AROUND ;если да, обходим цикл PUSH AF ;сохраняем счетчик в стеке ......... ;тело цикла POP AF ;восстановление значения счетчика INC A ; и увеличение его на 1 JR CYCLE ;безусловный переход на начало AROUND ......... ;продолжение программы

Прежде чем продолжить разговор о циклах, скажем еще несколько слов об особенностях использования в ассемблере чисел со знаком. Вы, конечно, понимаете, что ни в какую ячейку памяти невозможно записать отрицательное значение. Попробуйте в редакторе GENS ввести, а затем оттранслировать команду

LD A,-1

после чего просмотрите память, например, функцией Бейсика PEEK. На первом месте вы увидите байт 62, это код самой команды, а следом за ним вместо -1 обнаружите число 255. Казалось бы, что с отрицательными числами в машинных кодах иметь дело совершенно невозможно, но тем не менее, можно считать, что старший бит в байте или двухбайтовом значении иногда будет играть роль знака: если он установлен, то число отрицательное, а если сброшен - положительное. Таким образом, применение чисел со знаком в ассемблере в достаточной степени условно, но все же возможно. А следить за тем, какой тип чисел применяется в каждом конкретном случае должен сам программист.


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