Директивы ассемблера

Директивы ассемблера

Директивы представляют собой команды управления компилятором. Объявление каждой из них должно начинается с точки. Практика показывает, что в любом ассемблере наиболее интенсивно используется только порядка 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  {начальный адрес}

Пример использования:

.equSRAM_START = 0x60 .equRAMEND = 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 мс

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


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

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

*
= 4 + 9

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

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