распознается во всех контекстах, хотя оно должно распознаваться только в условных директивах. Это приводит к тому, что defined может быть распознано как символы пользователя, подобно метке и т.п. С другой стороны, допустима конструкция, подобная .dw foo = defined(bar).
Заметьте, что препроцессор и Ассемблер реализуют различное поведение defined. К настоящему времени точное поведение определенно в версиях 2.1.5 и выше:
Ключевое слово препроцессора defined имеет отношение только к определению #define и правильно работает только в условных директивах препроцессора #if/#elif.
Правильное поведение функции Ассемблера defined должно реализовываться только в условных директивах .if/.elif.
Проблемы с препроцессором:
Препроцессор не обнаруживает неправильные директивы в случае «лжи» при проверке условия. Это может привести к сюрпризам, подобно этому:
#if __ATmega8__ //...
#elseif __ATmega16__ // НЕПРАВИЛЬНО, правильная директива – #elif. //Ошибка пройдет необнаруженной, если __ATmega8__ – ложь. //...
#else
//когда __ATmega8__ – ложь, эта секция будет ассемблирована
//даже если бы __ATmega16__ была истина.
#endif
Причина этого дефекта не выяснена, возможно, она связана с поведением препроцессора Cи.
Препроцессор неправильно распознает дополнительный текст после директив. Например, #endif #endif будет интерпретироваться как единственная #endif директива, без сообщений об ошибках или предупреждений.
Дефект #4741: не работают условные директивы в макросах препроцессора. Использование макроса, определенного ниже, закончится различными сообщениями о синтаксических ошибках в зависимости от значения val (истина или ложь) в условии:
#define ТЕСТ \
.IF val \
.DW 0 \
.ELSE \
.DW 1 \
.ENDIF
50
Причина этого в том, что условные директивы Ассемблера должны быть на отдельной строке, а определение этого макроса препроцессора должно быть конкатенировано в одну строку.
5. СИСЕМА КОМАНД 8-РАЗРЯДНЫХ RISC МИКРОКОНТРОЛЛЕРОВ СЕМЕЙСТВА AVR
5.1. Список команд
Принятые обозначения:
Регистр статуса (SREG):
C – флаг переноса;
Z – флаг нулевого значения;
N – флаг отрицательного значения;
V – флаг-указатель переполнения дополнительного кода;
S– флаг знака, S = N V;
H– флаг полупереноса;
T– флаг пересылки, используемый командами BLD и BST;
I:– флаг разрешения/запрещения глобального прерывания.
|
Регистры и операнды: |
Rd |
– регистр-приемник (и источник) в регистровом файле; |
Rr |
– регистр-источник в регистровом файле; |
K |
– константа: литерал или байт данных (8 бит); |
k |
–адрес, константа; |
b– номер разряда в регистровом файле или регистре ввода/вывода (3 бита);
s:– номер разряда в регистре статуса (3 бита);
X, Y, Z – регистры косвенной адресации (X=R27:R26, Y=R29:R28, Z=R31:R30);
P – регистр порта I/O;
q – смещение при косвенной адресации (6 бит). РС – содержание программного счетчика
Стек:
STACK: |
– стек для адреса возврата и опущенных в стек регистров; |
|
SP: |
– указатель стека. |
|
Операции: |
|
|
* – логическое И, – логическое ИЛИ, |
– исключающее ИЛИ. |
|
MSB – старший значащий разряд. |
|
|
LSB – младший значащий разряд. |
|
|
Список команд микроконтроллеров семейства Mega AVR в алфавитном порядке приведен в табл. 9. Звездочкой помечены команды, отсутствующие в семействе Tiny.
51
|
Список команд |
Таблица 9 |
||
|
|
|||
Обозна- |
Функция |
|
Обозна- |
Функция |
чение |
|
чение |
||
|
|
|
||
1 |
2 |
|
1 |
2 |
ADC |
Сложить с переносом |
|
BRTC |
Перейти, если флаг T очищен |
ADD |
Сложить без переноса |
|
BRTS |
Перейти, если флаг T установлен |
ADIW* |
Сложить непосредственное |
|
BRVC |
Перейти, если переполнение |
|
значение со словом |
|
|
очищено |
AND |
Выполнить логическое AND |
|
BRVS |
Перейти, если переполнение |
|
|
|
|
установлено |
ANDI |
Выполнить логическое AND c |
|
BSET |
Установить флаг |
|
непосредственным значением |
|
|
|
ASR |
Арифметически сдвинуть вправо |
|
BST |
Переписать бит из регистра во |
|
|
|
|
флаг T |
BCLR |
Очистить флаг |
|
CBI |
Очистить бит в регистре I/O |
BLD |
Загрузить T флаг в бит регистра |
|
CBR |
Очистить биты в регистре |
|
|
|
|
|
BRBC |
Перейти, если бит в регистре |
|
CALL* |
Длинный переход на |
|
статуса очищен |
|
|
подпрограмму |
BRBS |
Перейти, если бит в регистре |
|
CBI |
Очистить бит в регистре ввода / |
статуса установлен |
|
|
вывода |
|
BRCC |
Перейти, если флаг переноса |
|
CBR |
Очистить биты в регистре |
|
очищен |
|
|
|
BRCS |
Перейти, если флаг переноса |
|
CLC |
Очистить флаг переноса |
установлен |
|
|
|
|
BREAK |
Выход |
|
CLH |
Очистить флаг полупереноса |
BREQ |
Перейти, если равно |
|
CLI |
Очистить флаг глобального |
|
|
прерывания |
||
|
|
|
|
|
BRGE |
Перейти, если больше или равно |
|
CLN |
Очистить флаг отрицательного |
(с учетом знака) |
|
|
значения |
|
BRHC |
Перейти, если флаг полупереноса |
|
CLR |
Очистить регистр |
очищен |
|
|
|
|
BRHS |
Перейти, если флаг полупереноса |
|
CLS |
Очистить флаг знака |
установлен |
|
|
|
|
BRID |
Перейти, если глобальное |
|
CLT |
Очистить флаг T |
|
прерывание запрещено |
|
|
|
BRIE |
Перейти, если глобальное |
|
CLV |
Очистить флаг переполнения |
|
прерывание разрешено |
|
|
|
BRLO |
Перейти, если меньше (без знака) |
|
CLZ |
Очистить флаг нулевого |
|
|
|
|
значения |
BRLT |
Перейти, если меньше чем (со |
|
COM |
Выполнить дополнение до |
|
знаком) |
|
|
единицы |
BRMI |
Перейти, если минус |
|
CP |
Сравнить |
BRNE |
Перейти, если не равно |
|
CPC |
Сравнить с учетом переноса |
BRPL |
Перейти, если плюс |
|
CPI |
Сравнить c константой |
BRSH |
Перейти, если равно или больше |
|
CPSE |
Сравнить и пропустить, если |
|
(без знака) |
|
|
равно |
52
1 |
2 |
DEC |
Декрементировать |
EICALL* |
Расширенный ICALL |
EIJMP* |
Расширенный IJMP |
ELPM* |
Расширенная загрузка данных |
|
|
EOR |
Выполнить исключающее ИЛИ |
|
|
FMUL* |
Умножение дробных |
|
беззнаковых чисел |
FMULS* |
Умножение дробных чисел со |
|
знаком |
FMULSU |
Умножение дробного |
*беззнакового числа и дробного числа со знаком
ICALL* |
Вызвать подпрограмму |
|
|
косвенно |
|
IJMP* |
Перейти косвенно |
|
IN |
Загрузить данные из порта |
|
I/O в регистр |
||
|
||
INC |
Инкрементировать |
|
JMP* |
Перейти |
|
|
|
|
LD* Rd,X |
Загрузить косвенно |
|
LD* |
Загрузить, косвенно |
|
инкрементировав |
||
Rd,X+ |
||
впоследствии |
||
|
||
LD* Rd,- |
Загрузить, косвенно |
|
декрементировав |
||
X |
предварительно |
|
|
||
LDI |
Загрузить непосредственное |
|
значение |
||
|
||
LDS* |
Загрузить непосредственно из |
|
СОЗУ |
||
|
||
LPM |
Загрузить байт памяти |
|
программ |
||
|
||
LSL |
Логически сдвинуть влево |
|
|
|
|
LSR |
Логически сдвинуть вправо |
|
|
|
|
MOV |
Копировать регистр |
|
|
|
|
MUL* |
Перемножить без знака |
|
MULS* |
Перемножить со знаком |
|
|
|
|
MULSU* |
Перемножить числа со |
|
знаком и без знака |
|
Продолжение табл.9 |
|
1 |
2 |
|
NEG |
Дополнить до двух |
|
NOP |
Выполнить холостую команду |
|
OR |
Выполнить логическое OR |
|
ORI |
Выполнить логическое OR с |
|
непосредственным значением |
||
|
||
OUT |
Записать данные из регистра в |
|
порт I/O |
||
|
||
POP* |
Загрузить регистр из стека |
|
|
|
|
PUSH* |
Поместить регистр в стек |
|
|
|
|
RCALL |
Вызвать подпрограмму |
|
относительно |
||
|
|
|
RET |
Вернуться из подпрограммы |
|
|
|
|
RETI |
Вернуться из прерывания |
|
RJMP |
Перейти относительно |
|
|
|
|
ROL |
Сдвинуть влево через перенос |
|
ROR |
Сдвинуть вправо через |
|
перенос |
||
|
||
SBC |
Вычесть с переносом |
|
SBCI |
Вычесть непосредственное |
|
значение с переносом |
||
|
||
|
|
|
SBI |
Установить бит в регистр I/O |
|
|
|
|
SBIC |
Пропустить, если бит в |
|
регистре I/O очищен |
||
|
||
SBIS |
Пропустить, если бит в |
|
регистре I/O установлен |
||
|
||
SBIW* |
Вычесть непосредственное |
|
значение из слова |
||
SBRC |
Пропустить, если бит в |
|
регистре очищен |
||
SBRS |
Пропустить, если бит в |
|
регистре установлен |
||
|
||
SEC |
Установить флаг переноса |
|
|
|
|
SEH |
Установить флаг полупереноса |
|
SEI |
Установить флаг глобального |
|
прерывания |
||
|
||
SEN |
Установить флаг |
|
отрицательного значения |
||
|
53
|
|
|
|
Окончание табл.9 |
1 |
2 |
|
1 |
2 |
|
Установить все биты |
|
|
Записать косвенно из регистра |
SER |
|
ST Z,Rr |
в СОЗУ с использованием |
|
регистра |
|
|||
|
|
|
индекса Z |
|
|
|
|
|
|
SES |
Установить флаг знака |
|
STS* |
Загрузить непосредственно в |
|
СОЗУ |
|||
|
|
|
|
|
SET |
Установить флаг T |
|
SUB |
Вычесть без переноса |
|
|
|
|
|
|
Установить флаг |
|
|
Записать косвенно из регистра |
SEV |
|
ST Z,Rr |
в СОЗУ с использованием |
|
переполнения |
|
|||
|
|
|
индекса Z |
|
|
|
|
|
|
SEZ |
Установить флаг нулевого |
|
STS |
Загрузить непосредственно в |
значения |
|
СОЗУ |
||
|
|
|
||
SLEEP |
Установить режим SLEEP |
|
SUBI |
Вычесть непосредственное |
|
значение |
|||
|
|
|
|
|
SPM* |
Изменение содержимого |
|
SWAP |
Поменять полубайты местами |
памяти программ |
|
|||
|
|
|
|
|
ST* X,Rr |
Записать косвенно |
|
TST |
Проверить на ноль или минус |
|
Записать косвенно из |
|
|
|
ST* Y,Rr |
регистра в СОЗУ с |
|
WDR |
Сбросить сторожевой таймер |
|
использованием индекса Y |
|
|
|
5.2. Описание команд
Команда ADC сложить с переносом
Описание:
Сложение двух регистров и содержимого флага переноса (С), размещение результата в регистре назначения Rd.
Операция: Rd <– Rd + Rr + C
Синтаксис: |
Операнды: |
Счетчик программ: |
ADC Rd,Rr |
0 < d < 31, 0 < r < 31 |
PC < PC + 1 |
H Устанавливается, если есть перенос из бита 3, в ином случае очищается.
S Для проверок со знаком.
V Устанавливается, если в результате операции образуется переполнение дополнения до двух, в ином случае очищается.
N Устанавливается, если в результате установлен MSB, в ином случае очищается.
Z Устанавливается, если результат $00, в ином случае очищается.
C Устанавливается, если есть перенос из MSB результата, в ином случае очищается.
54