Итак, приступим. Для начала рассмотрим команды передачи данных.
MOV Rd,Rs
| Эта команда копирует содержимое регистра Rs в регистр Rd. Содержимое Rs не изменяется, предыдущее содержимое Rd теряется. Пример:
mov R3,R19 ; содержимое R19 копируется в R3
Работает со всеми регистрами. Биты признаков не изменяет.
| LDI Rd,K
| Загружает в регистр Rd 8-ми разрядную константу. Работает со старшими регистрами (R16-R31). Пример:
ldi R16,1 ; загружает в R16 значение 1
Биты признаков не изменяет. Если необходимо загрузить константу в младший регистр, то это делается двумя командами:
ldi R16,1 ; загружает в R16 значение 1 mov R4,R16; и копирует в R4
| LD Rd,X
| Загружает в регистр Rd байт из памяти данных, адрес ячейки памяти в регистровой паре X. Содержимое регистровой пары X не изменяется. Например:
ldi XL,0 ; загружает младший байт регистровой пары Х ldi XH,2 ; -//- старший байт регистровой пары Х ld R5,X ; байт из ОЗУ с адресом 0x200 загружается в R5
Биты признаков не изменяет.
| LD Rd,X+
| Аналогично предыдущей команде, но содержимое регистровой пары X после выполнения пересылки данных увеличивается на 1. Например:
ldi XL,0 ; загружает младший байт регистровой пары Х ldi XH,2 ; -//- старший байт регистровой пары Х ld R5,X+ ; байт из ОЗУ с адресом 0x200 загружается в R5 ld R6,X+ ; байт из ОЗУ с адресом 0x201 загружается в R6
Биты признаков не изменяет.
| LD Rd,-X
| Аналогично предыдущей команде, но содержимое регистровой пары X перед выполнением пересылки данных уменьшается на 1. Например:
ldi XL,0 ; загружает младший байт регистровой пары Х ldi XH,2 ; -//- старший байт регистровой пары Х ld R5,-X ; байт из ОЗУ с адресом ox1FF загружается в R5 ld R6,-X ; байт из ОЗУ с адресом 0x1FE загружается в R6
Биты признаков не изменяет.
| LD Rd,Y
LD Rd,Y+
LD Rd,-Y
LD Rd,Z
LD Rd,Z+
LD Rd,-Z
| Эти команды работают абсолютно идентично трем ранее описанным, за исключением того, что индексным регистром является не X, а Y и Z. Наличие трех пар регистров дает возможность эффективной работы с блоками памяти, например:
ldi XL,0x00 ;\первый блок памяти ldi XH,0x02 ; регистровая пара X указывает на адрес 0x200 ldi YL,0x80 ;\второй блок памяти ldi YH,0x01 ; регистровая пара Y указывает на адрес 0x180 ldi R16,10 ; счетчик на 10
LOOP:
ld R5,X+ ; в R5 из первого блока, X указывает на следующий! st Y+,R5 ; из R5 во второй блок, Y также - на следующий dec R16 ; и так - 10 раз! brne LOOP
В результате выполнения этого цикла 10 байт памяти, начиная с адреса 0x200 будут скопированы в область памяти с адресом 0x180
| LDD Rd,Y+q
LDD Rd,Z+q
| Регистровые пары Y и Z, кроме вышеописанных методов обращения к памяти данных, имеют еще один. В этом случае в регистр Rd загружается байт из ячейки памяти, чей адрес вычисляется как содержимое регистровой пары плюс 6-ти разрядное смещение. Содержимое регистровой пары не изменяется! Например:
ldi YL,0 ; \ ldi YH,2 ; регистровая пара Y указывает на адрес 0x200 ldd R5,Y+5 ; байт из ОЗУ с адресом 0x205 загружается в R5 ldd R6,Y+10 ; байт из ОЗУ с адресом 0x210 загружается в R6
Такой режим адресации невозможен для регистровой пары X. Значение смещения q - от 0 до 63.
| Мы рассмотрели команды LD и LDD, которые обеспечивают пересылку данных из памяти данных в регистр общего назначения. Естественно, что для каждой команды LD и LDD имеется "обратная" ей команда - записи в память данных из регистра. Эти команды имеют мнемоники соотвественно ST и STD (store). Например:
ldd R5,Y+5 ; байт из ОЗУ с адресом 0x205 загружается в R5 std Y+6,R5 ; байт из R5 записывается в ОЗУ с адресом 0x206
Думаю, что совершенно нет необходимости расписывать каждую из них в отдельности...
| LDS Rd,A
STS A,Rs
| Команда LDS загрузит в регистр Rd содержимое ячейки памяти данных с адресом A, где A - шестнадцатиразрядная константа. В этом случае нет необходимости предварительно загружать регистровую пару, но сама команда займет два слова программной памяти, а не одно, как предыдущие. Например:
lds R5,0x240 ; байт из ОЗУ с адресом 0x240 загружается в R5 sts 0x060,R5 ; байт R5 в ОЗУ с адресом 0x060
Парой для команды LDS является команда STS - записывающая содержимое регистра в память.
| LPM
| К командам пересылки данных надо отнести и очень специфичную команду LPM, которая пересылает в R0 байт памяти программ, на который указывает региcтровая пара Z. Напомню, что память программ и память данных между собой никак не пересекаются. Данная команда используется в основном для чтения таблиц констант, располагаемых в памяти программ. Например:
TABLE: db 4,6,8,2,3,5,0
;...... ldi ZL,low(TABLE*2) ldi ZH,hi(TABLE*2) LPM ; в R0 будет занесено число 4
Содержимое регистровой пары Z не изменяется, биты признаков - тоже. Вообще, ни одна команда пересылки данных не изменяет признаков.
Важно! Поскольку для команды LPM адресация побайтная, а память программ адресуется словами (слово = 2 байта), то необходимо при загрузке адреса таблицы адрес умножить на 2!
| IN Rd, I/O
| Команда IN прочтет байт из регистра ввода-вывода в регистр общего назначения, например:
in R18,PINA ; прочитать состояние входных линий порта A в R18 in R1,TCCR0 ; прочитать в R1 счетчик таймера 0
Работает со всеми регистрами, биты признаков не изменяет.
| OUT I/O, Rs
| А эта - из регистра выведет в порт.
| PUSH Rs
POP Rd
| Эти команды предназначены для работы со стеком. Команда PUSH поместит Rs в стек, после выполнения команды указатель стека уменьшается на единицу. Команда POP извлечет байт из стека и поместит его в Rd. Соответственно, указатель стека увеличится на единицу.
Указатель стека должен быть установлен (как правило - на последний байт ОЗУ) при старте программы!
| Теперь рассмотрим арифметические и логические команды. Но перед этим освежим в памяти регистр состояния SREG - поскольку все команды будут изменять какие-либо биты в SREG.
Регистр SREG находится в области регистров ввода-вывода, по адресу 0x3F (0x5F). Чтение и запись производится командами IN / OUT, кроме того, есть специальные команды установки и очистки конкретного бита в SREG. Ну и, естественно, команды условного перехода (ветвления) выполняются в зависимости от соcтояния битов SREG, но о ветвлениях - в следующем подразделе...
Итак, в SREG имеются следующие биты: I
| SREG.7
| Бит разрешения прерывания. Если он = 0, то все прерывания в МК запрещены. Если он =1, то разрешением прерываний будут управлять соответствующие биты периферии.
| T
| SREG.6
| Битовый аккумулятор. С этим битом работают команды BST и BLD
| H
| SREG.5
| Флаг переноса из младшей тетрады
| S
| SREG.4
| Sign - ислючающее ИЛИ битов N и V
| V
| SREG.3
| oVerflow - переполнение
| N
| SREG.2
| Negative - Результат операции < 0
| Z
| SREG.1
| Zero - Результат операции равен нулю
| C
| SREG.0
| Carry - Флаг переноса
|
ADD Rd,Rs
| Сложение Rd и Rs, результат помещается в Rd. Изменяемые признаки: H V N Z C
| ADC Rd,Rs
| То же, что и ADD, но еще прибавляется C-разряд. Используется при работе с числами разрядностью более байта:
add R18,R20 ; сложили мл байты - может быть перенос! adc R19,R21 ; сложили старшие с учетом этого переноса
Изменяемые признаки: H V N Z C
| ADIW Rdl,q
| Сложение пары регистров с константой (q - от 0 до 63). Работает с четырьмя старшими парами регистров, то есть Z,Y,X и R25:R24 и используется в основном для операций с указателями.
Изменяемые признаки: V N Z C
| SUB Rd,Rs
| Вычитание Rs из Rd, результат помещается в Rd. Изменяемые признаки: H V N Z C
| SUBI Rd,K
| Вычитание из Rd константы K. Изменяемые признаки: H V N Z C. Отметим, что команды сложения с константой в системе команд почему-то нет! Что, конечно, очень неудобно. Если нужно прибавить к регистру, например, число 10 - следует написать
subi R16, -10
Но тут надо помнить, что признаки будут установлены "неправильно"! Работает со старшими регистрами
| SBC Rd,Rs
| Вычитание Rs из Rd с учетом переноса. Результат в Rd. Изменяемые признаки: H V N Z C
| SBCI Rd,K
| Вычитание константы K из Rd с учетом переноса. Результат в Rd. Работает со старшими регистрами. Изменяемые признаки: H V N Z C
| SBIW Rdl,q
| Вычитание из пары регистров константы. См. описание ADIW
| AND Rd,Rs
| Логическое "И" Rd и Rs, результат помещается в Rd. Изменяемые признаки: V N Z
Суть логического "И" - в Rd будут установлены в состояние лог. 1 те биты, которые были равны 1 и в Rd и в Rs, остальные сбрасываются в 0
| ANDI Rd,K
| То же, только вместо Rs - константа K. Работает со старшими регистрами
| OR Rd,Rs
| Логическое "ИЛИ" Rd и Rs, результат помещается в Rd. Изменяемые признаки: V N Z
Суть логического "ИЛИ" - в Rd будут установлены в состояние лог. 1 те биты, которые были равны 1 или в Rd, или в Rs, остальные сбрасываются в 0
| ORI Rd,K
| Логическое "ИЛИ" Rd и константы K. Работает со старшими регистрами
| EOR Rd,Rs
| Исключающее "ИЛИ" Rd и Rs, результат помещается в Rd. Изменяемые признаки: V N Z
Суть исключающего "ИЛИ" - в Rd будут установлены в состояние лог. 1 те биты, которые были не равны в Rd, и в Rs, Следует заметить, что нет команды "исключающее ИЛИ" с константой!
| COM Rd
| Изменит все биты Rd на противоположные. Внимание! На самом деле эта команда выполняется как 0xFF-Rd ! Результат - то один, но в результате выполнения команды будет установлен C-разряд! Изменяемые признаки: V N Z С
| NEG Rd
| Изменение знака Rd. Вычисляется как 0x00 - Rd Изменяемые признаки: H V N Z С
| SBR Rd,K
| Совершенно непонятно, зачем в систему команд введена эта мнемоника. Set Bit(s) in Register - это та же операция "логическое ИЛИ". Наверное, для того, чтобы в даташите гордо заявить - 118 Powerful Instructions!, хотя на самом деле добрая пятая часть дублируется. Короче, см. описание ORI Rd,K
| CBR Rd,K
| По сути то же самое. На самом деле - ANDI Rd,Not(K)
| INC Rd DEC Rd
| Инкремент / декремент Rd. Думаю, тут все ясно... Изменяемые признаки: N Z V
| TST Rs
| Установка признаков по содержимому Rs. На самом деле вычисляется как AND Rs, Rs. Изменяемые признаки: N Z V
| CLR Rd
| Очистка Rd (занесение в Rd нуля). Выполняется как EOR Rd,Rd , поэтому изменяет признаки: N Z V
| SER Rd
| Занесение константы 0xFF в Rd. Именно так и выполняется - LDI Rd, 0xFF Соответственно признаков не меняет, смысла в этой мнемонике также не наблюдается.
| |