PIC16. Ассемблер. Оптимизация последовательности условного ветвления

Влад Князев
1 апреля 2004

В системе команд данного семейства, команда сравнения двух чисел отсутствует. В качестве инструкций сравнения используются либо инструкция вычитания sublw, либо инструкция «Исключающее ИЛИ» xorlw. Последнюю инструкцию особенно удобно использовать при проверке условий «равно» / «не равно».

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

Пусть мы имеем некоторый фрагмент такого кода:

        call    GetChr          ; Ввод данных с клавиатуры,
                                ; результат в регистре W
                                ; и в переменной KeyBuf
        xorlw   'F'             ; Выбор текущего пункта меню?
        bz      DoItem          ; Да, выполнить обработку

        movfw   KeyBuf          ; Выбор следующего пункта?  #####
        xorlw   '+'             ;
        bz      NextItem        ; Переход, если ДА

        movfw   KeyBuf          ; Выбор предыдущего пункта?  #####
        xorlw   '-'             ;
        bnz     menu_loop       ; Переход, если НЕТ –
                                ; все остальные кнопки игнорировать

Инструкции перезагрузки рабочего регистра W (обозначено ##### в комментариях) в данном случае не является необходимой и их можно удалить при соответствующей модификации кода:

        call    GetChr          ; Ввод данных с клавиатуры,
                                ; результат в регистре W
        xorlw   'F'             ; Выбор текущего пункта меню?
        bz      DoItem          ; Да, выполнить обработку

        xorlw   '+' ^  'F'      ; Выбор следующего пункта?
        bz      NextItem        ; Переход, если ДА

        xorlw   '-' ^ '+'       ; Выбор предыдущего пункта?
        bnz     menu_loop       ; Переход, если НЕТ –
                                ; все остальные кнопки игнорировать

Как видим, фрагмент кода сократился на две инструкции и, кроме того, освободилась ячейка регистрового файла, что также в ряде случаев может быть необходимо. Здесь в соответствии с синтаксисом ассемблера для обозначения операции «Исключающее ИЛИ» используется символ ^.

Чтобы понять, как такая оптимизация работает, нужно вспомнить некоторые свойства логической функции «Исключающее ИЛИ»:

x ^ x = 0;
x ^ y = y ^ x, т.е. «Исключающее ИЛИ» является коммутативной функцией;
x ^ y ^ z = (x ^ y) ^ z = x ^ (y ^ z), т.е. «Исключающее ИЛИ» является ассоциативной функцией.

Из этих свойств следует, что в нашем случае

результат первого сравнения — W = W ^ 'F';
результат второго сравнения — W = W ^ ('+' ^ 'F') = W ^ 'F' ^ '+' ^ 'F' = W ^ '+';
результат третьего сравнения — W = W ^ ('-' ^ '+') = W ^ '+' ^ '-' ^ '+' = W ^ '-'.