Отключаемые счетчики электроэнергии на пульте. Все с документами пломбами, гарантией и без посредников!

Арифметические и логические команды

Арифметические и логические команды

Табл.1. Арифметические и логические команды:

Команда

Описание

Действие

Циклы

Код операции

Флаги

ATtiny

ATmega

add    Rd,Rr

Add two Registers

Rd←Rd+Rr

1

0000 11rd dddd rrrr

Z,C,S,

N,V,H

+

+

adc    Rd,Rr

Add with Carry two Registers

Rd←Rd+Rr+C

1

0001 11rd dddd rrrr

Z,C,S,

N,V,H

+

+

adiw   Rdl,K

Add Immediate to Word

Rdh:Rdl←Rdh:Rdl+K

2

1001 0110 KKdd KKKK

Z,C,S,

N,V

±

+

sub    Rd,Rr

Subtract two Registers

Rd←Rd-Rr

1

0001 10rd dddd rrrr

Z,C,S,

N,V,H

  +

+

sbc    Rd,Rr

Subtract with Carry two Registers

Rd←Rd-Rr-C

1

0000 10rd dddd rrrr

Z,C,S,

N,V,H

+

+

subi   Rd,K

Subtract Constant from Register

Rd←Rd-K

1

1010 KKKK dddd KKKK

Z,C,S,

N,V,H

+

+

sbci   Rd,K

Subtract with Carry Constant from Register

Rd←Rd-K-C

1

0100 KKKK dddd KKKK

Z,C,S,

N,V,H

+

+

sbiw   Rdl,K

Subtract  Immediate from Word

Rdh:Rdl←Rdh:Rdl-K

2

1001 0111 KKdd KKKK

Z,C,S,

N,V

±

+

and    Rd,Rr

Logical AND Registers

Rd←Rd AND Rr

1

0010 00rd dddd rrrr

 

Z,S,N

+

+

andi   Rd,K

Logical AND Register and Constant

Rd←Rd AND K

1

0111 KKKK dddd KKKK

 

Z,S,N

+

+

or     Rd,Rr

Logical OR Registers

Rd←Rd OR Rr

1

0010 10rd dddd rrrr

 

Z,S,N

  +

+

ori    Rd,K

Logical OR Register and Constant

Rd←Rd OR K

1

0110 KKKK dddd KKKK

 

Z,S,N

+

+

eor    Rd,Rr

 

Exclusive OR Registers

Rd←Rd EOR Rr

1

0010 01rd dddd rrrr

 

Z,S,N

+

+

com    Rd

One’s complement

Rd←0xFF-Rd

1

1001 010d dddd 0000

 

Z,S,N

+

+

neg    Rd

Two’s complement

Rd←0x00-Rd

1

1001 010d dddd 0001

Z,C,S,

N,V,H

+

+

sbr    Rd,K

Set Bit(s) in Register

Rd←Rd OR K

1

0110 KKKK dddd KKKK

Z,S,N

+

+

cbr    Rd,K

Clear Bit(s) in Register

Rd←Rd AND (0xFF- K)

1

0111 KKKK dddd KKKK

 

Z,S,N

+

+

inc    Rd

Increment

Rd←Rd+1

1

1001 010d dddd 0011

Z,S,

N,V

+

+

dec    Rd

Decrement

Rd←Rd-1

1

1001 010d dddd 1010

Z,S,

N,V

+

+

tst    Rd

Test for Zero or Minus

Rd←Rd AND Rd

1

0010 00dd dddd dddd

 

Z,S,N

+

+

clr    Rd

Clear Register

Rd←Rd EOR Rd

1

0010 01dd dddd dddd

 

Z,S,N

+

+

ser    Rd

Set Register

Rd←0xFF

1

1110 1111 dddd 1111

None

+

+

mul    Rd,Rr

 

Multiply Unsigned

R1:R0←Rd*Rr

2

1001 11rd dddd rrrr

Z,C

+

muls   Rd,Rr

Multiply Signed

R1:R0←Rd*Rr

2

0000 0010 dddd rrrr

Z,C

+

mulsu  Rd,Rr

Multiply Signed with Unsigned 

R1:R0←Rd*Rr

2

0000 0011 0ddd 0rrr

Z,C

+

fmul   Rd,Rr

Fractional Multiply

Unsigned

R1:R0←(Rd*Rr)<<1

2

0000 0011 0ddd 1rrr

Z,C

+

fmuls  Rd,Rr

Fractional Multiply

Signed

R1:R0←(Rd*Rr)<<1

2

0000 0011 1ddd 0rrr

Z,C

+

fmulsu Rd,Rr

Fractional Multiply

Signed with Unsigned

R1:R0←(Rd*Rr)<<1

2

0000 0011 1ddd 1rrr

  Z,C

+

Как видно из табл.1, AVR имеют всего 3 разновидности команды сложения. Инструкции add Rd,Rr (Сложение двух регистров), adc Rd,Rr (Сложение двух регистров с учётом переноса), позволяют складывать как однобайтовые числа, так числа произвольной разрядности. В последнем случае для связи байтов используется флаг переноса C в регистре SREG, который устанавливается всякий раз, когда разрядность суммы превысит 8 бит. Этот перенос должен быть добавлен к сумме старших байтов командой adc Rd,Rr:

add R18,R16 ; сложение двухбайтовых чисел adc R19,R17 ; R19:R18 = R19:R18 + R17:R16

Сложение регистра с константой, к сожалению, отсутствует. И это приносит некоторые неудобства, так как приходится использовать две команды, одна из которых занесение числа во вспомогательный регистр, а уже вторая – сложение регистров:

ldi R17,0x30 ; заносим в R17 константу 0x30 add R16,R17 ; R16 = R17 + 0x30

Во многих случаях вышеуказанную проблему можно решить, используя команду  adiw Rdl,K (Сложение константы со словом). Она позволяет прибавить 6-разрядную константу, лежащую в диапазоне 0…63, к одной из 4х регистровых пар Rdh:Rdl (R25:R24, R27:R26, R29:R28, R31:R30). С её помощью также удобно реализовать 16-разрядный счётчик событий:

key_press: adiw R24,1 ; инкрементируем счётчик R25:R24 sbis PINB,0 ; пока на линии 0 порта PORTB низкий rjmp key_press ; логический уровень

Из всех арифметических операций, вычитание в AVR – наиболее разнообразно по способам адресации.

Имеется две команды с прямой адресацией РОН:  sub Rd,Rr (Вычитание двух регистров),  sbc Rd,Rr (Вычитание двух регистров с учётом заема). При совместном использовании они позволяют получить разность чисел любой разрядности. Для связи байт, при этом, и здесь служит флаг C. Но в отличие от сложения он устанавливается, когда разность оказалась отрицательной(Rd < Rr) и имеет в этом случае смысл заема, который должен быть вычтен из разности старших байт командой sbc Rd,Rr:

sub R18,R16 ; вычитание двухбайтовых чисел sbc R19,R17 ; R19:R18 = R19:R18 – R17:R16

Ещё две команды с непосредственной адресацией используются для тех же целей:  subi Rd,K (Вычитание константы из  регистра) и sbсi Rd,K (Вычитание константы из регистра c учётом заёма). Эти инструкции очень универсальны. Их с одинаковым успехом можно применять как в целях вычитания, так и сложения. В последнем случае необходимо использовать представление числа K в дополнительном коде (т.е. изменить знак числа –K = 0xFF+1-K):

subi R16,-0x30 ; R16 = R16 + 0x30 = R16 – (-0x30)

Существует также инструкция, работающая в двухбайтовом формате, sbiw  Rdl,K (Вычитание константы из слова). Подобно сложению adiw  Rdl,K, с её помощью можно вычесть 6-разрядную K (0…63) из тех же самых регистровых пар (R25:R24, R27:R26, R29:R28, R31:R30). Главная область применения команды – реализация счётчика циклов:

delay: sbiw R24,1 ; декрементируем счётчик R25:R24 пока brne delay ; его содержимое не станет 0, формируя . ; задержку времени 4*R25:R24 циклов

Группа логических инструкций представлена 6-ю командами.

Операция “НЕ” производится по команде com Rd (Дополнение до одного). При этом фактически производится действие Rd←0xFF-Rd, при котором инвертируются все биты регистра. Команды and Rd,Rr (“Логическое И” регистров), andi Rd,K (“Логическое И” регистра и константы) и or Rd,Rr (“Логическое ИЛИ” регистров), ori Rd,K (“Логическое ИЛИ” регистра и константы) производят соответствующие логические операции как с регистрами, так и регистра с константой. Операция же “Исключающее ИЛИ” возможна только между регистрами. Для этих целей служит команда eor Rd,Rr (“Исключающее ИЛИ” регистров). Если провести операцию “Исключающее ИЛИ” регистра с самим собой (eor Rd,Rd), то будет получен нулевой результат (Rd←Rd EOR Rd = 0). Это свойство часто применяется, когда необходимо отчистить регистр, а команда eor Rd,Rd может иметь при этом альтернативную форму записи clr Rd (Очистить регистр). Кроме того, с помощью последовательности всего трех команд eor Rd,Rr можно обменять содержимое двух регистров (команда обмена РОНов у AVR отсутствует) местами не используя ни одной дополнительной ячейки памяти:

eor R16,R17 ; R16 = R16 XOR R17 eor R17,R16 ; R17 = R17 XOR (R16 XOR R17) = R16 eor R16,R17 ; R16 = (R16 XOR R17) XOR R16 = R17

Все описанные логические операции могут использоваться, например, в следующем контексте:

in R16,PORTB ;заносим для изменения РВВ PORTB в РОН R16 ori R16,(1«PB0)|(1«PB5) ;устанавливаем биты 0,5 в R16 andi R16,~((1«PB1)|(1«PB2));сбрасываем биты 1,2 в R16 out PORTB,R16 ;выводим изменённое значение R16 в PORTB eor R16,R16 ;обнуляем R16 out PORTC,R16 ;заносим 0 в PORTC

Как во многих других случаях, у инструкции ori Rd,K существует другая форма написания sbr Rd,K (Установка бита(ов) в регистре), числящаяся, однако, как самостоятельная команда. Применяя её необходимо помнить, что, несмотря на аббревиатуру, на самом деле производится именно операция “Логическое ИЛИ” регистра и битовой маски, а не установка битов в регистре. Так, например, для установки бита n в регистре Rd правильно писать sbr Rd,1<<n, а не sbr Rd,n. То же самое относится и к инструкции cbr Rd,K (Отчистка бита(ов) в регистре). Она также является псевдокомандой. В место неё в процессе компиляции программы будет произведена замена на andi Rd,K (под константой K в команде andi Rd,K понимается инвертированное значение K в команде cbr Rd,K). Таким образом, предыдущий участок программного кода может быть записан в следующем виде:

in R16,PORTB ; заносим для изменения РВВ PORTB в РОН R16 sbr R16,(1«PB0)|(1«PB5) ; устанавливаем биты 0,5 в R16 cbr R16,(1«PB1)|(1«PB2) ; сбрасываем биты 1,2 в R16 out PORTB,R16 ; выводим изменённое значение R16 в PORTB clr R16 ; обнуляем R16 out PORTC,R16 ; заносим 0 в PORTC

Когда надо установить все биты регистра, то можно воспользоваться инструкцией ser Rd (Установка регистра), которая заносит константу 0xFF в регистр Rd. Она является частной формой написания команды ldi Rd,K (Загрузка константы в регистр), относящейся к группе команд пересылки. Подобное действие можно осуществить и другими способами. Например, в результате команды andi R16,0xFF все биты регистра R16 также будут установленными.

Но в отличие от ser R16 или, что тоже самое, ldi R16,0xFF – будут изменены значения флагов N и Z, что может повлиять на правильный ход выполнение программы. По той же причине в ряде случаев для обнуления регистра лучше использовать ldi R16,0 вместо clr R16 (eor R16,R16); все флаги в регистре SREG останутся неизменными. Единственное, что мешает повсеместному применению команды ldi Rd,K, это ограниченный набор РОН с которыми она работает. Только регистры R16…R31 могут использоваться с этой инструкцией. Это существенное ограничение наложено и на все арифметические и логические команды, которые используют непосредственную адресацию (действие над регистром и константой).

На практике часто необходимо осуществить проверку регистра на нуль. Проще всего это сделать если произвести операцию “Логическое И” регистра самим с собой (and Rd,Rd). При этом содержимое Rd останется неизменным, а в регистре SREG будет установлен флаг нулевого результата Z если Rd = 0. Параллельно с ним будет переопределён и флаг N, который в случае использования знаковых чисел будет свидетельствовать об отрицательном содержимом регистра. Для инструкции and Rd,Rn где Rd = Rn, может быть использована  другая форма записи в виде псевдокоманды tst Rd (Проверка на нуль и минус).

В тех случаях, когда необходимо изменить знак однобайтового числа используют команду neg Rd (Дополнение до двух). Она осуществляет действие Rd←0x00-Rd и используется только для чисел представленных дополнительном коде.

У AVR имеются также команды прямого и обратного счёта. Первая из них inc Rd (Инкремент) увеличивает на единицу содержимое регистра, а вторая dec Rd (Декремент), соответственно, уменьшает. Конечно, действия инкрементирования и декрементирования могут быть заменены, например, на прибавление 1 и вычитание 1 из регистра Rd (subi R16,-1 эквивалентно inc R16, а subi R16,1  тоже, что и dec Rd). Но, несмотря на это обе команды имеют большое самостоятельное значение. Главная их особенность в том, что они не влияют на флаг переноса C и тем самым оптимизированы для формирования циклов, в которых он может использоваться:

ldi R16,SIZE ; производим сдвиг числа, clc ; находящегося в ОЗУ и состоящего из rleft: ld R17,X ; SIZE байт на один разряд влево rol R17 st X+,R18 dec R16 brne rleft .

Дополняет группу арифметических команд умножение однобайтовых чисел. В зависимости от формата представления множителя и множимого, существует 6 вариаций данной операции. Произведение, полученное по команде умножения (2-байтовая величина) заносится в регистровую пару R1:R0. Эта интересная аппаратная особенность AVR позволяет очень быстро обработать результат, так как он размещается в РОН и может быть перемещён в любое место всего одной командой пересылки. Следует, однако, предварительно позаботится о сохранении содержимого регистров R1, R0 если они используются в программе.

Для умножения целых чисел разработаны три команды: mul Rd,Rr (Умножение беззнаковых чисел), muls Rd,Rr (Умножение знаковых чисел), mulsu Rd,Rr (Умножение знакового числа на беззнаковое).

Знаковые числами должны быть представлены в дополнительном коде. При этом для первых двух команд безразлично на месте каких операндов будут находиться множитель и множимое. К одному и тому же результату приведут, например,  mul R16,R17 и  mul R17,R16 (muls R16,R17 и  muls R17,R16). В случае mulsu Rd,Rr на месте Rd обязательно должно стоять знаковое число. Помимо флага Z (один из операндов 0), умножение оказывает влияние и на флаг переноса C. В него заносится старший бит регистра R1. Таким образом, в командах  muls Rd,Rr, mulsu Rd,Rr он фактически является флагом знака и устанавливается когда произведение отрицательное. Необходимо также помнить, что инструкция muls Rd, Rr может использоваться только с регистрами R16…R31. Ещё меньше поддерживает команда mulsu Rd,Rr, только R16…R23.

Существует ряд специфических приложений, в которых может понадобиться умножения дробных чисел с фиксированной запятой. Главная задача, где это может быть необходимо, – цифровая обработка сигналов. Для дробного умножения имеются команды: fmul Rd,Rr (Умножение дробных беззнаковых чисел), fmuls Rd,Rr (Умножение дробных знаковых чисел), fmulsu Rd,Rr (Умножение дробного знакового числа на беззнаковое). Все команды работают с числами в формате (1.7). Старший бит регистра является целой частью числа, а  младшие 7 битов отведены под дробную. Произведение приводится к формату (2.14). Для этого производится сдвиг результата на один разряд влево так, что старший разряд оказывается во флаге C. Все инструкции дробного умножения работают только с регистрами R16…R23.

Перейти к следующей части:


Категория: Микроконтроллеры
Метки:

Написать коментарий

*
= 4 + 7

Добавить изображение

Последние статьи