Директивы представляют собой команды управления компилятором. Объявление каждой из них должно начинается с точки. Практика показывает, что в любом ассемблере наиболее интенсивно используется только порядка 10…20 директив. Все остальные либо не являются обязательными, либо отвечают за управление, лишь незначительными свойствами компилятора. К “основным”, характерным и для ассемблеров других процессоров, относятся директивы .equ, .org, .def, .сseg, .dseg и т.д. Ну, а такие директивы, как .dq, .exit, .listmac в реальных программах встречаются действительно очень редко. Ниже приведен перечень, описание и примеры использования директив фирменного ассемблера микроконтроллеров AVR.
Директива .include подставляет текстовый файл в то место программы, где происходит ее употребление. В дополнении к этому сам файл подстановки также может содержать директиву .include. Если файл расположен в директории проекта или в одной из служебных папок, то вместо полного пути, допускается указывать, лишь ссылку на его имя.
Директива .include
Синтаксис написания:
.include "{путь к файлу}"
Пример использования:
.include "m8def.inc" ;вставка стандартного заголовочного файла
Директива .exit указывает ассемблеру место окончания файла исходного текста. Все операторы, находящиеся после директивы, становятся невидимыми для компилятора. Если .exit встречается в подключаемом файле, то сборка проекта заканчивается строкой, где расположена директива .include. В случае отсутствия директивы .exit, конечной точкой сборки считается последняя строка исходного текста.
Директива .exit
Синтаксис написания:
.exit
Пример использования:
.exit ;конец файла
Директивы .nolist и .list служат для управления файлом листинга, который обычно генерируется после сборки проекта. Первая из них запрещает, а другая, соответственно, разрешает вывод информации в файл. Директива .list отменяет действие .nolist и наоборот.
Директивы .nolist, .list
Синтаксис написания:
.nolist, .list
Пример использования:
.nolist ;запретить вывод текста файла “m8def.inc” .include "m8def.inc" ;в файл листинга программы .list ;продолжить вывод информации
Директива .equ присваивает символьному имени некоторое числовое значение. Символьное имя должно быть уникальным и не может быть изменено в процессе написания программы. Директива не может применяться для назначения символьных имен регистрам общего назначения.
Директива .equ
Синтаксис написания:
.equ {символьное имя} = {выражение}
Пример использования:
.equ DDRB = 0x17 ;присвоение имени DDRB значения 0x17 .equ PORTB = DDRB + 1 ;присвоение имени PORTB значения 0x18
Директива .set производит то же самое действие, что и .equ. Но в отличии от последней, символьное имя может быть переопределено в любом месте программы.
Директива .set
Синтаксис написания:
.set {символьное имя} = {выражение}
Пример использования:
.set OFFSET = 0x100 ;присвоение имени OFFSET значения 0x100 . .set OFFSET = OFFSET + 1 ;переопределение значения OFFSET
Директива .def присваивает символьное имя одному из регистров общего назначения. В дальнейшем ходе программы данное имя может быть отменено директивой .undef.
Директивы .def, .undef
Синтаксис написания:
.def {символьное имя} = {регистр}
.undef {символьное имя}
Пример использования:
.def temp = R16 ;присвоение регистру R16 имя temp .undef temp ;отмена дальнейшего использования имени temp
Директивы .db, .dw, .dd, .dq предназначены для резервирования памяти микроконтроллера под инициализированные данные. Все они могут применяться только в сегментах кода и EEPROM-памяти. Разница между этими директивами заключается в разрядности, представляемых данных. Директива .db резервирует байты, .dw – слова, .dd – двойные слова. В редких случаях может так же оказаться удобным использование директивы .dq, резервирующей 64-разрядные данные.
Директивы .db, .dw, .dd, .dq
Синтаксис написания:
{метка}: .db {8-разрядные данные}
{метка}: .dw {16-разрядные данные}
{метка}: .dd {32-разрядные данные}
{метка}: .dq {64-разрядные данные}
Пример использования:
label: .db 0xFA, 250, -6, 0b11111010 .dw 0xFADE, 64222, -1314, 0b1111101011011110 .dd 0xFADEEFCA, 4208914378, -86052918 .dq 0xFADEEFCAEFBACDEF, 18077149609196178927, -521103510453211
Директива .byte резервирует память под неинициализированные данные в сегментах SRAM и EEPROM.
Директива .byte
Синтаксис написания:
{метка}: .byte {количество резервируемых данных}
Пример использования:
.equ PAGESIZE = 0x20 buffer: . byte 2*PAGESIZE ;резервирование 64 байт в SRAM
Директивы .dseg, .eseg, .cseg определяют начало сегментов данных, EEPROM-памяти и кода соответственно. В исходном файле каждый из сегментов может быть представлен только в одном экземпляре. В случае если все эти директивы отсутствуют в программе, компилятор по умолчанию считает, что все операторы расположены в секции кода.
Директивы .dseg, .eseg, .cseg
Синтаксис написания:
.dseg
.eseg
.cseg
Пример использования:
.dseg ;начало сегмента данных buffer: . byte 32 ;резервирование 32 байт под буфер в SRAM .cseg ;начало сегмента кода rjmp initial . string: .db "ATmega8",0 ;строка, хранящаяся во FLASH-памяти .eseg ;начало сегмента EEPROM-памяти _var: .byte 2 ;резервирование 2-ух байт под переменную _var _cnst: .db 0xAA ;резервирование байта под переменную _cnst = 0xAA
Директива .org позволяет задать компилятору начальный адрес в пределах сегментов кода, данных и EEPROM-памяти. В случае применения в сегменте кода, директива определяет адрес размещения 16-разрядного слова программ.
Директива .org
Синтаксис написания:
.org {начальный адрес}
Пример использования:
.equ SRAM_START = 0x60 .equ RAMEND = 0x045F .dseg ;начало сегмента данных .org SRAM_START ;резервирование 32 байт в SRAM под буфер, buffer: . byte 32 ;начиная с адреса 0x60 .cseg ;начало сегмента кода .org 0 ;вектор сброса по адресу 0 rjmp initial . .org 0x50 ;начало основной программы с адреса 0x50 initial: ldi temp,high(RAMEND) ;инициализация стека out SPH,temp ldi temp,low(RAMEND) out SPL,temp .
Директивы .macro, .endmacro (.endm), определяющие начало и конец макроса соответственно.
Директивы .macro, .endmacro (.endm)
Синтаксис написания:
.macro {имя макроса}
Пример использования:
.macro set_bit ;объявление макроса установки бита порта sbi @0,@1 ;установить бит @1 регистра порта @0 sbi @0-1,@1 ;настроить на вывод линию @1 регистра DDRx .endm . set_bit PORTB,0 ;установить на линии 0 порта B лог.1
Директива .listmac разрешает расширенный вывод текста макросов в файле листинга. В этом случае содержимое каждого макроопределения, встретившегося в программе, отображается целиком. Если директива не используется, то код в нутрии макроса не приводится.
Директива .listmac
Синтаксис написания:
.listmac
Пример использования:
.listmac ;разрешить разворачивать текст макросов в файле листинга
Директивы .message, .warning, .error предназначены для вывода в окно сборки проекта дополнительной информации о ходе компиляции программы. Директива .message генерирует сообщение для строки, в которой был встречен ее вызов. Применение .warning приводит к выдачи предупреждения, а .error – к сообщению об ошибки. В последнем случае сборка проекта прекращается.
Директивы .message, .warning, .error
Синтаксис написания:
.message "{текст сообщение}"
.warning "{текст предупреждения}"
.error "{текст соодщения об ошибки}"
Пример использования:
.message "Macros has been called here." .warning "Too high frequency!" .error "Wrong macro argument!"
Группа директив условной компиляции .ifdef, .ifndef, .if, .else, elif, .endif используются для вставок программного кода в зависимости от различных условий. Директива .ifdef проверяют наличие объявления некоторого символьного имени. За директивой может следовать набор команд, которые будут подставлены в текст, если условие проверки “истина” (имя было объявлено). Директива .ifndef противоположна .ifdef проверяет отсутствие объявления символьного имени. Директива .if производит подстановку кода, когда выполняется условие сравнения, указанное в качестве ее параметра. Команды, которые должны выполняться, в случае если условие директивы .if “ложно” – располагаются после директивы .else. Ветвление типа “если” - “то” может иметь несколько уровней вложения благодаря директиве .elif. Каждый блок проверки, начинающийся с .ifdef, .ifndef, .if, должен быть закрыт директивой .endif.
Директивы if, .ifdef, .ifndef, .else, elif, .endif
Синтаксис написания:
.ifdef {символ} (или .ifndef {символ})
.if {условие}
.else {выражение} (или .elif { условие})
.endif
Пример использования:
.macro del_ms ;макрос, формирующий задержку времени в мс .ifndef FREQ ;если не объявлена константа FREQ (частота в Гц), .warning "Undefined FREQ constan!" ;выдаем предупреждение и .equ FREQ = 1000000 ;присваиваем по умолчание значение 1 МГц .endif .equ DELAY = (@0*FREQ)/4000 ;величина задания задержки времени .if DELAY > 65535 ;если DELAY размером больше 2 байт, то .error “Integer overflow in DELAY!” ;реализация макроса не возможна .else push XL ;сохраняем в стеке рабочие регистры XL, XH push XH ldi XH,high(DELAY) ;цикл задержки времени ldi XL,low(DELAY) sbiw XH:XL,1 brne PC-1 pop XH pop XL ;восстанавливаем из стека рабочие регистры XH, XL .endif .endm . .equ FREQ = 2000000 ;объявление тактовой частоты 2 МГц . del_ms 25 ;формирование задержки времени в 25 мс
Перейти к следующей части: Содержимое заголовочного файла
Комментарии (3) | Я собрал (0) | Подписаться
Для добавления Вашей сборки необходима регистрация
Короче, было бы здорово в конце каждой страницы иметь не только переход на следующую, но и на предыдущую. Ну или на начало статьи. Потому как намереваюсь читать весь цикл.
З.Ы. Сам то я разыщу начало в любом случае. Просто хотелось так сказать поднять градус эффективности материала.
Но способ вообщем то есть. Обратите внимание на адресную строку. Если номер в адресной строке поменять то мы попадем на нужный нам материал, на предыдущий, либо которой интересует дальше.
У меня ".ifndef @0" что то не сработало.