Компілятор працює з файлами, що містять інструкції, мітки і директиви. Інструкції та директиви, як правило, мають один або кілька операндів.
Рядок коду не повинна бути довше 120 символів.
Будь-яка рядок може починатися з позначки, яка є набором символів закінчується двокрапкою. Мітки використовуються для зазначення місця, в яке передається управління при переходах, а також для завдання імен змінних.
Вхідна рядок може мати одну з чотирьох форм:
Позиції в квадратних дужках необов'язкові. Текст після крапки з комою (;) і до кінця рядка ігнорується компілятором. Мітки, інструкції та директиви більш детально описуються нижче.
label: ════ .EQU var1 = 100; Встановлює var1 рівним 100 (Це директива)
══════════ .EQU var2 = 200; Встановлює var2 рівним 200
═ Інструкції процесорів AVR
Нижче наведено набір команд процесорів AVR, більш детальний опис їх можна знайти в AVR Data Book.
═
Арифметичні і логічні інструкції
═
Асемблер не розрізняє регістр символів.
Операнди можуть бути таких видів:
директиви асемблера
Компілятор підтримує ряд директив. Директиви не транслюються безпосередньо в код. Замість цього вони використовуються для вказівки положення в програмній пам'яті, визначення макросів, ініціалізації пам'яті і т.д. Список директив наведено в таблиці нижче.
═
Всі директиви предваряются точкою.
BYTE - Зарезервувати байти в ОЗУ
Директива BYTE резервує байти в ОЗУ. Якщо ви хочете мати можливість посилатися на виділену область пам'яті, то директива BYTE повинна бути випереджу міткою. Директива приймає один обов'язковий параметр, який вказує кількість виділених байт. Ця директива може використовуватися тільки в сегменті даних (дивитися директиви CSEG і DSEG). Виділені байти НЕ инициализируются.
синтаксис:
МЕТКА. BYTE вираз
приклад:
.DSEG
var1: ═══ .BYTE 1═══════════; резервує 1 байт для var1
table: ══ .BYTE tab_size════; резервує tab_size байт
.CSEG
════════ ldi r30, low (var1) ═; Завантажує молодший байт регістра Z
════════ ldi r31, high (var1); Завантажує старший байт регістра Z
════════ ld r1, Z═══════════; Завантажує VAR1 в регістр 1
CSEG - Програмний сегмент
Директива CSEG визначає початок програмного сегмента. Вихідний файл може складатися з декількох програмних сегментів, які об'єднуються в один програмний сегмент при компіляції. Програмний сегмент є сегментом за замовчуванням. Програмні сегменти мають свої власні лічильники положення які вважають не побайтно, а по немов. Директива ORG може бути використана для розміщення коду і констант в необхідному місці сегмента. Директива CSEG не має параметрів.
приклад:
.DSEG══════════════════════; Початок сегмента даних
vartab. BYTE 4════════════; Резервує 4 байта в ОЗУ
.CSEG══════════════════════; Початок кодового сегмента
const: ═ .DW 2══════════════; Розмістити константу 0x0002 в пам'яті програм
═══════ mov r1, r0══════════; виконати дії
DB - Визначити байти у флеш або EEPROM
Директива DB резервує необхідну кількість байт в пам'яті програм або в EEPROM. Якщо ви хочете мати можливість посилатися на виділену область пам'яті, то директива DB повинна бути випереджу міткою. Директива DB повинна мати хоча б один параметр. Дана директива може бути розміщена тільки в сегменті програм (CSEG) або в сегменті EEPROM (ESEG).
Параметри передаються директиві - це послідовність виразів розділених комами. Кожен вираз має бути або числом в діапазоні (-128..255), або в результаті обчислення повинно давати результат в цьому ж діапазоні, в іншому випадку число усікається до байта, причому БЕЗ видачі попереджень.
Якщо директива отримує більше одного параметра і поточним є програмний сегмент, то параметри упаковуються в слова (перший параметр - молодший байт), і якщо число параметрів непарній, то останній вираз буде усечено до байта і записано як слово зі старшим байтом рівним нулю, навіть якщо далі йде ще одна директива DB.
синтаксис:
МЕТКА: ═ .DB спісок_вираженій
приклад:
.CSEG
consts. DB 0, 255, 0b01010101, -128, 0xaa
DEF - Призначити регістру символічне ім'я
Директива DEF дозволяє посилатися на регістр через деякий символічне ім'я. Призначене ім'я може використовуватися у всій наступній частині програми для звернень до даного регістру. Регістр може мати кілька різних імен. Символічне ім'я може бути перепризначено пізніше в програмі.
синтаксис:
.DEF Сімволіческое_імя = Регістр
.CSEG
═ldi temp, 0xf0═; Завантажити 0xf0 в регістр temp (R16)
═in ior, 0x3f═; Прочитати SREG в регістр ior (R0)
═eor temp, ior═; Регістри temp і ior складаються по виключає або
DEVICE - Визначити пристрій для якого компілюється програма
Директива DEVICE дозволяє вказати для якого пристрою компілюється програма. При використанні даної директиви компілятор видасть попередження, якщо буде знайдена інструкція, яку не підтримує даний мікроконтролер. Також буде видано попередження, якщо програмний сегмент, або сегмент EEPROM перевищать розмір допускається пристроєм. Якщо ж директива не використовується то все інструкції вважаються допустимими, і відсутні обмеження на розмір сегментів.
синтаксис:
.DEVICE AT90S1200 | AT90S2313 | AT90S2323 | AT90S2333 | AT90S2343 | AT90S4414 | AT90S4433 | AT90S4434 | AT90S8515 | AT90S8534 | AT90S8535 | ATtiny11 | ATtiny12 | ATtiny22 | ATmega603 | ATmega103
приклад:
.DEVICE AT90S1200═; використовується AT90S1200
.CSEG
═══════ push r30══; Ця інструкція викличе попередження
══════════════════; оскільки AT90S1200 її немає
DSEG - Сегмент даних
Директива DSEG визначає початок сегмента даних. Вихідний файл може складатися з декількох сегментів даних, які об'єднуються в один сегмент при компіляції. Сегмент даних зазвичай складається тільки з директив BYTE і міток. Сегменти даних мають свої власні побайтное лічильники положення. Директива ORG може бути використана для розміщення змінних в необхідному місці ОЗУ. Директива не має параметрів.
приклад:
.DSEG═══════════════════════; Початок сегмента даних
var1: ═ .BYTE 1══════════════; зарезервувати 1 байт для var1
table: ═ .BYTE tab_size══════; зарезервувати tab_size байт.
.CSEG
═══════ ldi r30, low (var1) ═══; Завантажити молодший байт регістра Z
═══════ ldi r31, high (var1) ══; Завантажити старший байт регістра Z
═══════ ld r1, Z═════════════; Завантажити var1 в регістр r1
DW - Визначити слова у флеш або EEPROM
Директива DW резервує необхідну кількість слів у пам'яті програм або в EEPROM. Якщо ви хочете мати можливість посилатися на виділену область пам'яті, то директива DW повинна бути випереджу міткою. Директива DW повинна мати хоча б один параметр. Дана директива може бути розміщена тільки в сегменті програм (CSEG) або в сегменті EEPROM (ESEG).
Параметри передаються директиві - це послідовність виразів розділених комами. Кожен вираз має бути або числом в діапазоні (-32768..65535), або в результаті обчислення повинно давати результат в цьому ж діапазоні, в іншому випадку число усікається до слова, причому БЕЗ видачі попереджень.
синтаксис:
МЕТКА. DW expressionlist
приклад:
.CSEG
varlist: ═ .DW 0, 0xffff, 0b1001110001010101, -32768, 65535
ENDMACRO - Кінець макросу
Директива визначає кінець макроозначення, і не приймає ніяких параметрів. Для інформації щодо визначення макросів дивіться директиву MACRO.
приклад:
.MACRO SUBI16══════════════; Початок визначення макросу
═══════ subi r16, low (@ 0) ═══; Відняти молодший байт першого параметра
═══════ sbci r17, high (@ 0) ══; Відняти старший байт першого параметра
.ENDMACRO
EQU - Встановити постійне вираз
Директива EQU привласнює мітці значення. Ця мітка може пізніше використовуватися у виразах. Мітка якій присвоєно значення даної директиви не може бути перепризначено і її значення не може бути змінено.
синтаксис:
.EQU мітка = вираз
приклад:
.EQU io_offset = 0x23
.EQU porta════ = io_offset + 2
.CSEG════════════════; Початок сегмента даних
═══════ clr r2═══════; Очистити регістр r2
═══════ out porta, r2═; Записати в порт A
ESEG - Сегмент EEPROM
Директива ESEG визначає початок сегмента EEPROM. Вихідний файл може складатися з декількох сегментів EEPROM, які об'єднуються в один сегмент при компіляції. Сегмент EEPROM зазвичай складається тільки з директив DB. DW і міток. Сегменти EEPROM мають свої власні побайтное лічильники положення. Директива ORG може бути використана для розміщення змінних в необхідному місці EEPROM. Директива не має параметрів.
приклад:
.DSEG═══════════════════; Початок сегмента даних
var1: ══ .BYTE 1═════════; зарезервувати 1 байт для var1
table: ═ .BYTE tab_size══; зарезервувати tab_size байт.
.ESEG
eevar1. DW 0xffff═══════; проинициализировать 1 слово в EEPROM
EXIT - Вийти з файлу
Зустрівши директиву EXIT компілятор припиняє компіляцію даного файлу. Якщо директива використана у вкладеному файлі (див. Директиву INCLUDE), то компіляція триває з рядка наступної після директиви INCLUDE. Якщо ж файл не є вкладеним, то компіляція припиняється.
приклад:
.EXIT═; Вийти з цього файлу
INCLUDE - Вкласти інший файл
Зустрівши директиву INCLUDE компілятор відкриває вказаний в ній файл, компілює його поки файл не закінчиться або не зустрінеться директива EXIT. після цього продовжує компіляцію початкового файлу з рядка наступної за директивою INCLUDE. Вкладений файл може також містити директиви INCLUDE.
синтаксис:
.INCLUDE "имя_файла"
приклад:
; файл iodefs.asm:
.EQU sreg══ = 0x3f════; регістр статусу
.EQU sphigh = 0x3e════; Старший байт покажчика стека
.EQU splow═ = 0x3d════; Молодший байт покажчика стека
; файл incdemo.asm
.INCLUDE iodefs.asm═══; Вкласти визначення портів
═══════ in r0, sreg════; Прочитати регістр статусу
LIST - Включити генерацію лістингу
приклад:
.NOLIST═══════════════; Відключити генерацію лістингу
.INCLUDE "macro.inc" ══; Вкладені файли не будуть
.INCLUDE "const.def" ══; відображені в лістингу
.LIST═════════════════; Включити генерацію лістингу
LISTMAC - Включити розгортання макросів в лістингу
Після директиви LISTMAC компілятор буде показувати в лістингу вміст макросу. За замовчуванням в лістингу показується тільки виклик макросу і передані параметри.
.LISTMAC═══════════; Включити розгортання макросів
═══════ MACX r2, r1═; Виклик макроса (в лістингу буде показано тіло макросу)
MACRO - Початок макросу
З директиви MACRO починається визначення макросу. Як параметр директиві передається ім'я макросу. При зустрічі імені макросу пізніше в тексті програми, компілятор замінює це ім'я на тіло макросу. Макрос може мати до 10 параметрів, до яких в його тілі звертаються через @ 0- @ 9. При виклику параметри перераховуються через коми. Визначення макросу закінчується директивою ENDMACRO.
За замовчуванням в лістинг включається тільки виклик макросу, для розгортання макросу необхідно використовувати директиву LISTMAC. Макрос в лістингу показується знаком +.
═
синтаксис:
.MACRO макроімен
приклад:
.MACRO SUBI16══════════════════; початок макроозначення
═══════ subi @ 1, low (@ 0) ════════; Відняти молодший байт параметра 0 з параметра 1
═══════ sbci @ 2, high (@ 0) ═══════; Відняти старший байт параметра 0 з параметра 2
.ENDMACRO══════════════════════; кінець макроозначення
.CSEG══════════════════════════; Початок програмного сегмента
═══════ SUBI16 0x1234, r16, r17══; Відняти 0x1234 з r17: r16
NOLIST - Вимкнути генерацію лістингу
приклад:
.NOLIST═══════════════; Відключити генерацію лістингу
.INCLUDE "macro.inc" ══; Вкладені файли не будуть
.INCLUDE "const.def" ══; відображені в лістингу
.LIST═════════════════; Включити генерацію лістингу
ORG - Встановити положення в сегменті
SET - Встановити змінний символічний еквівалент вираження
Директива SET привласнює імені деяке значення. Це ім'я пізніше може бути використано в виразах. Причому на відміну від директиви EQU значення імені може бути змінено інший директивою SET.
синтаксис:
.SET ім'я = вираз
приклад:
.SET io_offset = 0x23
.SET porta════ = io_offset + 2
.CSEG════════════════; Початок кодового сегмента
═══════ clr r2═══════; Очистити регістр 2
═══════ out porta, r2═; Записати в порт A
Компілятор дозволяє використовувати в програмі вираження які можуть складатися операндів. знаків операцій і функцій. Всі вирази є 32-бітними.
Можуть бути використані наступні операнди:
- Мітки певні користувачем (дають значення свого становища).
- Змінні певні директиви SET
- Константи певні директивою EQU
- Числа задані в форматі:
- Десятковому (прийнятий за замовчуванням): 10, 255
- Шістнадцятковому (два варіанти запису): 0x0a, $ 0a, 0xff, $ ff
- Довічним: 0b00001010, 0b11111111
- Вісімковому (починаються з нуля): 010, 077
- PC - поточне значення програмного лічильника (Programm Counter)
Компілятор підтримує ряд операцій, які перераховані в таблиці (чим вище становище в таблиці, тим вище пріоритет операції). Вирази можуть полягати в круглі дужки, такі вирази обчислюються перед виразами за дужками.
Визначено наступні функції:
- LOW (вираз) повертає молодший байт вираження
- HIGH (вираз) повертає другий байт вираження
- BYTE2 (вираз) то ж що і функція HIGH
- BYTE3 (вираз) повертає третій байт вираження
- BYTE4 (вираз) повертає четвертий байт вираження
- LWRD (вираз) повертає біти 0-15 вираження
- HWRD (вираз) повертає біти 16-31 вираження
- PAGE (вираз) повертає біти 16-21 вираження
- EXP2 (вираз) повертає 2 певною мірою (вираз)
- LOG2 (вираз) повертає цілу частину log2 (вираз)
Використання програми
відкриття файлів
Повідомлення про помилки
Після компіляції програми з'являється вікно повідомлень. Всі виявлені компілятором помилки будуть перераховані в цьому вікні. При виборі рядка з повідомленням про помилку, рядок вихідного файлу, в якій знайдена помилка, стає червоною. Якщо ж помилка знаходиться у вкладеному файлі, то цього підсвічування не відбудеться.
Якщо по рядку в вікні повідомлень клацнути двічі, то вікно файлу з вказаною помилкою стає активним, і курсор поміщається на початку рядка містить помилку. Якщо ж файл з помилкою не відкритий (наприклад це вкладений файл) то він буде автоматично відкрито.
Врахуйте, що якщо ви внесли зміни в вихідні тексти (додали або видалили рядки), то інформація про номери рядків у вікні повідомлень не є коректною.
Деякі установки програми можуть бути змінені через пункт меню "Options".
В поле введення під назвою "List-file extension", вводиться розширення, яке використовується для файлу лістингу, а в поле "Output-file extension" знаходиться розширення для файлів з результатом компіляції програми. В прямокутнику "Output file format" можна вибрати формат вихідного файлу (як правило використовується интеловский). Однак це не впливає на об'єктний файл (який використовується AVR Studio), який завжди має один і той же формат, і розширення OBJ. Якщо у вихідному файлі присутній сегмент EEPROM то буде також створено файл з розширенням EEP. Установки задані в даному вікні запам'ятовуються на постійно, і при наступному запуску програми, їх немає необхідності встановлювати заново.
Опція "Save before assemble" вказує програмі на необхідність автоматичного збереження активного вікна (і тільки його) перед компіляцією.
Якщо ви хочете, щоб при закритті програми закривалися всі відкриті вікна, то поставте галочку в поле "Close all windows before exit".
Atmel, AVR є зареєстрованими товарними знаками фірми Atmel Corporation
Переклад виконав Руслан Шімкевіч, [email protected]