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

       

Условные и безусловные переходы


Алгоритм циклов с использованием регистров, отличных отB, принципиально не отличается от порядка выполнения команды DJNZ и может быть выражен словами «уменьшить содержимое регистра и перейти на начало цикла, если не ноль». Как записывается в ассемблерной мнемонике первая часть этого предложения, вам, наверное, уже понятно: если использовать в качестве счетчика, скажем, регистр E, то нужно написать команду DEC E. Что же касается переходов, то в системе команд микропроцессора имеется не одна инструкция (как в Бейсике оператор GO TO), а целых две. Одна из них универсальна и позволяет переходить по любому выбранному адресу, другая же предназначена для более коротких переходов на расстояния, не превышающие 126-127 байт (так же, как и для команды DJNZ). Первая инструкция записывается двумя буквами JP (сокращение от Jump - перепрыгнуть), а вторая имеет мнемоническое обозначение JR (Jump Relative - относительный переход). Сначала приведем несколько примеров безусловных переходов:

JP 3435 ;переход по абсолютному адресу 3435 JP LABEL ;переход на метку LABEL JR $+35 ;относительный переход вперед на ; расстояние в 35 байт JR LABEL ;переход на ту же самую метку LABEL

Сразу может возникнуть вопрос, зачем для выполнения одного и того же действия нужны разные команды? Во-первых, команда JR короче JP и занимает в памяти два байта вместо трех (не улыбайтесь: такая, на первый взгляд, мелочная экономия в итоге может вылиться в килобайты!), а во-вторых, команды «коротких» переходов вы сможете оценить в полной мере, если вам когда-нибудь доведется писать программы или процедуры в машинных кодах, которые позволительно загружать по любому удобному адресу. Применение команды JR в таких подпрограммах избавит вас от необходимости выполнения предварительной их настройки на адрес загрузки. Именно так написано большинство процедур из пакетов Supercode и NewSupercode, что значительно облегчает работу с ними. Поэтому при написании собственных программ старайтесь использовать команду JR везде, где это только позволяет расстояние, оставляя команде JP переходы к дальним адресам.


Теперь относительно условных переходов. Эти команды также начинаются с JP или JR, но в поле операндов записывается мнемоника проверки одного из возможных флагов и после запятой - имя метки или абсолютный адрес, например:

JP Z,8252 ;переход по адресу 8252, если ; установлен флаг нуля JR NC,MAIN ;относительный переход на метку MAIN, ; если флаг переноса сброшен

Перечислим мнемоники всех возможных условий:


  • Z - если ноль (установлен флаг нуля Z);


  • NZ - если не ноль (флаг нуля Z сброшен);


  • C - если перенос (установлен флаг переноса CY);


  • NC - если нет переноса (флаг переноса CY сброшен);


  • M - если отрицательный результат (установлен флаг знака S);


  • P - если результат положительный (флаг знака S сброшен);


  • PE - если четность или переполнение (установлен флаг P/V);


  • PO - если нет четности/переполнения (флаг P/V сброшен).


  • Для флагов H и N условия отсутствуют, так как они используются только в неявном виде командами коррекции двоично-десятичных чисел.

    Здесь нужно еще добавить, что в команде JP возможно применение всех перечисленных мнемоник условий, а с командой JR допускаются только первые четыре: Z, NZ, C и NC.

    Зная все это, можно наконец написать цикл. В общем виде он будет выглядеть так:

    LD E,N ;заносим в регистр E счетчик ; количества повторений цикла N LOOP PUSH DE ;сохраняем его в стеке ......... ;тело цикла POP DE ;восстановление счетчика DEC E ; и уменьшение его на единицу JR NZ,LOOP ;переход на начало цикла, если счетчик ; не обнулился (в самом общем случае ; здесь может находиться инструкция ; JP NZ,LOOP)


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