Выбрать главу

∙ incf

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

∙ decf

Эта команда уменьшает на единицу содержимое заданного регистра данных, помещая результат либо обратно в исходный регистр, либо в рабочий регистр W. Например, если в регистре h’26’ было записано число h’64’, то после выполнения команды decf h’26’,f в нем окажется число h’63’.

Если в качестве адресата указать рабочий регистр (decf h’26’, w), то содержимое регистра h’26’ останется равным h’64’, а содержимое рабочего регистра станет равным h’63’.

* * *

Хочу обратить ваше внимание на то, что обе эти команды не влияют на флаг переноса С в отличие от эквивалентных команд прибавления или вычитания единицы[84]. В частности, это означает, что если вы собираетесь инкрементировать 3-байтное число, хранящееся в формате , то просто инкрементировать младший байт и проконтролировать переносы в старшие байты не получится. В следующем фрагменте программы используется команда btfss, которая пропускает команду, если 2-й бит регистра STATUS (флаг нуля Z) установлен в 1.

   incf LOWER,f; Прибавим единицу

   btfss STATUS,Z; Результат равен нулю?

      goto NEXT; ЕСЛИ нет (Z == 0), TO выходим

    incf MIDDLE,f; ИНАЧЕ инкрементируем следующий байт

      goto NEXT; ЕСЛИ нет (Z == 0), ТО выходим

     incf UPPER,f; ИНАЧЕ инкрементируем следующий байт

NEXT

... ...; Прочий код

В приведенном фрагменте инкрементируется самый младший байт, и если он становится равным нулю (h’FF’ —> h’00’), то инкрементируется следующий байт и так далее для всех байтов. Эта последовательность прерывается, если при инкрементировании регистра получается ненулевое значение, например

h’06 FF FE’ h’06 FF FF —> h’07 00 00’.

Бит-ориентированные команды

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

∙ bcf

Эта команда позволяет программисту сбросить в 0 любой из восьми битов указанного регистра памяти данных.

∙ bsf

Эта команда аналогична bcf, только указанный бит не сбрасывается, а устанавливается в 1. Например, при установке 5-го бита регистра h’26’ мы имеем

Одним из назначений данных команд является управление различными флагами и переключателями регистра STATUS. В коде, приведенном на стр. 119, мы уже использовали эти две команды для изменения состояния битов RPx (для переключения банков памяти данных). Ни одна из этих команд не воздействует на биты регистра STATUS. Однако важно понимать, что все команды, непосредственно изменяющие содержимое регистров данных, на самом деле считывают этот байт во временный регистр, выполняют соответствующую операцию (incf, bcf и т. д.), используя АЛУ, после чего помещают результат обратно в память данных. Такое поведение называется принципом чтение — модификация — запись и выполняется за один машинный цикл. Иногда такое функционирование может привести к неожиданным побочным эффектам (см., например, стр. 335).

Вычитание

В системе команд имеется две команды вычитания, операнды которых аналогичны командам сложения.

∙ subwf

Эта команда вычитает содержимое рабочего регистра из переменной, хранящейся в памяти данных. Как обычно, результат операции может быть помещен либо в рабочий регистр, либо обратно в исходный регистр данных. Например, при выполнении команды subwf h’26’,f происходит следующее:

Как мы уже обсуждали на стр. 95 и в Примере 4.2, приведенном на стр. 109, состояние флага переноса С равно дополнению к биту заема, возникающего при выполнении команд вычитания. Упущение из виду этого факта является одним из основных источников ошибок при написании программы!

∙ sublw

Команда sublw представляет собой еще один из источников ошибок, поскольку она вычитает содержимое рабочего регистра W из константы, а не наоборот, как можно подумать. Например, если в регистре W было, скажем, h’64’ (d’100’), то в результате выполнения команды sublw 1 вместо вычитания единицы получим 1 — h’64’ = h’9D’, что равно десятичному 157 (вообще говоря, это число — h’63’ в дополнительном коде). Лично я считаю, что из-за такой перевернутой реализации использование этой команды является неоправданным риском. В качестве альтернативы давайте посмотрим на команду addlw h’FF’. В нашем случае мы получим h’64’ + h’FF’ = h’(1)63’ (десятичное 99). Если игнорировать перенос, то получается, что 8-битный результат в W на единицу меньше исходного значения. Конечно же, зная о том, что h’FF’ является числом —1 в дополнительном коде, можно записать команду как addlw - 1, что будет более понятно. Более того, флаг С в данном случае равен 1 и, интерпретируя его как дополнение к биту заема, получаем, что заема не было.

вернуться

84

В микроконтроллерах старшего семейства команды incf и decf влияют на флаг С.