Примеры использования директивы org avr ассемблера. Директивы Ассемблера AVR. Программирование работы с дисплеем

Примеры использования директивы org avr ассемблера. Директивы Ассемблера AVR. Программирование работы с дисплеем

Модификатор static в Java напрямую связан с классом, если поле статично, значит оно принадлежит классу, если метод статичный, аналогично - он принадлежит классу. Исходя из этого, можно обращаться к статическому методу или полю используя имя класса. Например, если поле count статично в классе Counter , значит, вы можете обратиться к переменной запросом вида: Counter.count . Конечно, следует учитывать модификаторы доступа. Например, поля private доступны только внутри класса, в котором они объявлены. Поля protected доступны всем классам внутри пакета (package ), а также всем классам-наследникам вне пакета. Для более подробной информации ознакомьтесь со статьей “private vs protected vs public ”. Предположим, существует статический метод increment() в классе Counter , задачей которого является инкрементирование счётчика count . Для вызова данного метода можно использовать обращение вида Counter.increment() . Нет необходимости создавать экземпляр класса Counter для доступа к статическому полю или методу. Это фундаментальное отличие между статическими и НЕ статическими объектами (членами класса). Важное замечание. Не забывайте, что статические члены класса напрямую принадлежат классу, а не его экземпляру. То есть, значение статической переменной count будет одинаковое для всех объектов типа Counter . В этой статье мы рассмотрим основополагающие аспекты применения модификатора static в Java, а также некоторые особенности, которые помогут понять ключевые концепции программирования.

Что должен знать каждый программист о модификаторе Static в Java.

В этом разделе мы рассмотрим основные моменты использования статических методов, полей и классов. Начнём с переменных.

    Вы НЕ можете получить доступ к НЕ статическим членам класса, внутри статического контекста, как вариант, метода или блока. Результатом компиляции приведенного ниже кода будет ошибка:

    public class Counter { private int count; public static void main (String args ) { System. out. println (count) ; //compile time error } }

    Это одна из наиболее распространённых ошибок допускаемых программистами Java, особенно новичками. Так как метод main статичный, а переменная count нет, в этом случае метод println , внутри метода main выбросит “Compile time error”.

    В отличие от локальных переменных, статические поля и методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите - «залочивании» классом. Поэтому при использовании статических переменных, убедитесь, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких как «состояние гонки» (race condition).

    Статические методы имеют преимущество в применении, т.к. отсутствует необходимость каждый раз создавать новый объект для доступа к таким методам. Статический метод можно вызвать, используя тип класса, в котором эти методы описаны. Именно поэтому, подобные методы как нельзя лучше подходят в качестве методов-фабрик (factory), и методов-утилит (utility). Класс java.lang.Math - замечательный пример, в котором почти все методы статичны, по этой же причине классы-утилиты в Java финализированы (final).

    Другим важным моментом является то, что вы НЕ можете переопределять (Override) статические методы. Если вы объявите такой же метод в классе-наследнике (subclass), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса (superclass) вместо переопределения. Это явление известно как сокрытие методов (hiding methods). Это означает, что при обращении к статическому методу, который объявлен как в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:

    class Vehicle { public static void kmToMiles (int km) { System. out. println ("Внутри родительского класса/статического метода" ) ; } } class Car extends Vehicle { public static void kmToMiles (int km) { System. out. println ("Внутри дочернего класса/статического метода " ) ; } } public class Demo { public static void main (String args ) { Vehicle v = new Car () ; v. kmToMiles (10 ) ; } }

    Вывод в консоль:

    Внутри родительского класса/статического метода

    Код наглядно демонстрирует: несмотря на то, что объект имеет тип Car , вызван статический метод из класса Vehicle , т.к. произошло обращение к методу во время компиляции. И заметьте, ошибки во время компиляции не возникло!

    Объявить статическим также можно и класс, за исключением классов верхнего уровня. Такие классы известны как «вложенные статические классы» (nested static class). Они бывают полезными для представления улучшенных связей. Яркий пример вложенного статического класса - HashMap.Entry , который предоставляет структуру данных внутри HashMap . Стоит заметить, также как и любой другой внутренний класс, вложенные классы находятся в отдельном файле.class. Таким образом, если вы объявили пять вложенных классов в вашем главном классе, у вас будет 6 файлов с расширением.class. Ещё одним примером использования является объявление собственного компаратора (Comparator), например компаратор по возрасту (AgeComparator) в классе сотрудники (Employee).

    Модификатор static также может быть объявлен в статичном блоке, более известным как «Статический блок инициализации» (Static initializer block), который будет выполнен во время загрузки класса. Если вы не объявите такой блок, то Java соберёт все статические поля в один список и выполнит его во время загрузки класса. Однако, статичный блок НЕ может пробросить перехваченные исключения, но может выбросить не перехваченные. В таком случае возникнет «Exception Initializer Error». На практике, любое исключение возникшее во время выполнения и инициализации статических полей, будет завёрнуто Java в эту ошибку. Это также самая частая причина ошибки «No Class Def Found Error», т.к. класс не находился в памяти во время обращения к нему.

    Полезно знать, что статические методы связываются во время компиляции, в отличие от связывания виртуальных или не статических методов, которые связываются во время исполнения на реальном объекте. Следовательно, статические методы не могут быть переопределены в Java, т.к. полиморфизм во время выполнения не распространяется на них. Это важное ограничение, которое необходимо учитывать, объявляя метод статическим. В этом есть смысл, только тогда, когда нет возможности или необходимости переопределения такого метода классами-наследниками. Методы-фабрики и методы-утилиты хорошие образцы применения модификатора static . Джошуа Блох выделил несколько преимуществ использования статичного метода-фабрики перед конструктором, в книге «Effective Java », которая является обязательной для прочтения каждым программистом данного языка.

    Важным свойством статического блока является инициализация. Статические поля или переменные инициализируются после загрузки класса в память. Порядок инициализации сверху вниз, в том же порядке, в каком они описаны в исходном файле Java класса. Поскольку статические поля инициализируются на потокобезопасный манер, это свойство также используется для реализации паттерна Singleton . Если вы не используется список Enum как Singleton , по тем или иным причинам, то для вас есть хорошая альтернатива. Но в таком случае необходимо учесть, что это не «ленивая» инициализация. Это означает, что статическое поле будет проинициализировано ещё ДО того как кто-нибудь об этом «попросит». Если объект ресурсоёмкий или редко используется, то инициализация его в статическом блоке сыграет не в вашу пользу.

    Во время сериализации, также как и transient переменные, статические поля не сериализуются. Действительно, если сохранить любые данные в статическом поле, то после десериализации новый объект будет содержать его первичное (по-умолчанию) значение, например, если статическим полем была переменная типа int , то её значение после десериализации будет равно нулю, если типа float – 0.0, если типа Object – null . Честно говоря, это один из наиболее часто задаваемых вопросов касательно сериализации на собеседованиях по Java. Не храните наиболее важные данные об объекте в статическом поле!

    И напоследок, поговорим о static import . Данный модификатор имеет много общего со стандартным оператором import , но в отличие от него позволяет импортировать один или все статические члены класса. При импортировании статических методов, к ним можно обращаться как будто они определены в этом же классе, аналогично при импортировании полей, мы можем получить доступ без указания имени класса. Данная возможность появилась в Java версии 1.5, и при должном использовании улучшает читабельность кода. Наиболее часто данная конструкция встречается в тестах JUnit , т.к. почти все разработчики тестов используют static import для assert методов, например assertEquals() и для их перегруженных дубликатов. Если ничего не понятно – добро пожаловать за дополнительной информацией .

    На этом всё. Все вышеперечисленные пункты о модификаторе static в Java обязан знать каждый программист. В данной статье была рассмотрена базовая информация о статических переменных, полях, методах, блоках инициализации и импорте. В том числе некоторые важные свойства, знание которых является критичным при написании и понимании программ на Java. Я надеюсь, что каждый разработчик доведёт свои навыки использования статических концептов до совершенства, т.к. это очень важно для серьёзного программирования."

При написании программ на языке Ассемблер используются директивы, которые указывают компилятору положение программы в памяти, определяют макросы, инициализируют память и др. Список директив и их описание приведен в табл. 1.8. Запись всех директив начинается с точки. Кратко перечислим выполняемые директивами функции в каждом из сегментов.

Сегмент программы открывается директивой.CSEG. Если программа начинается с этого сегмента, директива может отсутствовать. В сегменте программы с помощью директивы.ORG можно указать начало сегмента.

Директива.DB в сегменте определяет один байт или группу байтов, констант, записываемых во Flash-память. Директива.DW определяет слово или группу слов, записываемых в память в качестве констант. Начало записи констант определяется меткой, стоящей перед соответствующей директивой. Перечисляемые константы разделяются запятыми.

Директива.DEF присваивает регистру символическое имя. Директивы.EQU, .SET присваивают значение имени. Имя, которому присвоено значение директивой.EQU, не может быть переназначено, и значение не может быть изменено. Имя, присвоенное директивой.SET, может быть изменено другой директивой.SET.

Директива.DEVICE определяет тип целевого микроконтроллера, который будет использован для выполнения программы. Наличие этой директивы подключает средства контроля инструкций программы по отношению к физическому устройству, предупреждая о невозможности выполнения некоторых инструкций, размеров используемой памяти и др.

Директива.INCLUDE с именем файла используется для включения в текст программы другого файла.

Таблица 1.8. Список директив

Директива

Описание

Резервировать байты в ОЗУ

Сегмент программы

Определить байт – константу во Flash-памяти или

Назначить регистру символическое имя

Определяет устройство, для которого компилируется

программа

Сегмент данных

Определяет слово во Flash-памяти или EEPROM

Конец макроса

Установить постоянное выражение

Сегмент EEPROM

Выход из файла

Вложить другой файл

Включить генерацию листинга

Включить разворачивание макросов в листинге

Начало макроса

Выключить генерацию листинга

Установить положение в сегменте

Установить для переменной эквивалентное выражение

Директивы.MACRO и.ENDMACRO обрамляют макроопределение. Макроопределение может иметь до 10 параметров с фиксированными именами @0,…,@9. При вызове макроопределения параметры задают в виде списка в порядке нумерации.

Сегмент данных начинается директивой.DSEG. В сегменте могут быть использованы директивы.ORG и.BYTE. Директива.BYTE определяет количество байтов, к которым будет производиться обращение при выполнении программы. Резервируемая область начинается по адресу, определяемому меткой перед директивой.

Сегмент типа EEPROM начинается директивой.ESEG. В сегменте могут быть использованы директивы.ORG, .DB, .DW. Директива.DB в сегменте определяет один или группу байтов, записываемых в EEPROM. Директива.DW определяет слово или группу слов, записываемых в память EEPROM парами по 2 байта. Начало записи байтов и слов определяется меткой, стоящей перед соответствующей директивой.

Директивы.LIST, .NOLIST, .LISTMAC используют для управления выводом листинга.

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

Компилятор поддерживает ряд директив. Директивы не транслируются непосредственно в код. Вместо этого они используются для указания положения в программной памяти, определœения макросов, инициализации памяти и т.д. Все директивы предваряются точкой.

Список директив приведён в следующей таблице.

Директива Описание
BYTE Зарезервировать байты в ОЗУ
CSEG Программный сегмент
DB Определить байты во флэш или EEPROM
DEF Назначить регистру символическое имя
DEVICE Определить устройство для которого компилируется программа
DSEG Сегмент данных
DW Определить слова во флэш или EEPROM
ENDM, ENDMACRO Конец макроса
EQU Установить постоянное выражение
ESEG Сегмент EEPROM
EXIT Выйти из файла
INCLUDE Вложить другой файл
LIST Включить генерацию листинга
LISTMAC Включить разворачивание макросов в листинге
MACRO Начало макроса
NOLIST Выключить генерацию листинга
ORG Установить положение в сегменте
SET Установить переменный символический эквивалент выражения

BYTE - зарезервировать байты в ОЗУ. Директива BYTE резервирует байты в ОЗУ. В случае если вы хотите иметь возможность ссылаться на выделœенную область памяти, то директива BYTE должна быть предварена меткой. Директива принимает один обязательный параметр, который указывает количество выделяемых байт. Эта директива может использоваться только в сегменте данных(смотреть директивы CSEG и DSEG). Выделœенные байты не инициализируются.

Синтаксис:

МЕТКА: .BYTE выражение

DSEG var1: .BYTE 1 ; резервирует 1 байт для var1

table: .BYTE tab_size ; резервирует tab_size байт

Ldi r30,low(var1) ; Загружает младший байт регистра Z

Ldi r31,high(var1) ; Загружает старший байт регистра Z

Ld r1,Z ; Загружает var1 в регистр 1

DB - определить байты во флэш или EEPROM. Директива DB резервирует крайне важно е количество байт в памяти программ или в EEPROM. В случае если вы хотите иметь возможность ссылаться на выделœенную область памяти, то директива DB должна быть предварена меткой. Директива DB должна иметь хотя бы один параметр.
Размещено на реф.рф

Параметры, передаваемые директиве - это последовательность выражений разделённых запятыми. Каждое выражение должно быть или числом в диапазоне (-128..255), или в результате вычисления должно давать результат в данном же диапазоне, в противном случае число усекается до байта͵ причём БЕЗ выдачи предупреждений.

В случае если директива получает более одного параметра и текущим является программный сегмент, то параметры упаковываются в слова (первый параметр - младший байт). В случае если число параметров нечётно, то последнее выражение будет усечено до байта и записано как слово со старшим байтом равным нулю, даже если далее идет ещё одна директива DB.

Синтаксис:

МЕТКА: .DB список_выражений

CSEG consts: .DB 0, 255, 0b01010101, -128, 0xaa

const2: .DB 1,2,3

DW - определить слова во флэш или EEPROM. Директива DW резервирует крайне важно е количество слов в памяти программ или в EEPROM. В случае если вы хотите иметь возможность ссылаться на выделœенную область памяти, то директива DW должна быть предварена меткой. Директива DW должна иметь хотя бы один параметр.
Размещено на реф.рф
Данная директива должна быть размещена только в сегменте программ (CSEG) или в сегменте EEPROM (ESEG).

Параметры, передаваемые директиве, - это последовательность выражений разделённых запятыми. Каждое выражение должно быть или числом в диапазоне (-32768..65535), или в результате вычисления должно давать результат в данном же диапазоне, в противном случае число усекается до слова, причем БЕЗ выдачи предупреждений.

Синтаксис:

МЕТКА: .DW expressionlist

varlist:═ .DW 0, 0xffff, 0b1001110001010101, -32768, 65535

eevarlst: .DW 0,0xffff,10

· Сегменты

DSEG - сегмент данных. Директива DSEG определяет начало сегмента данных. Исходный файл может состоять из нескольких сегментов данных, которые объединяются в один сегмент при компиляции. Сегмент данных обычно состоит только из директив BYTE и меток. Сегменты данных имеют свои собственные побайтные счётчики положения. Директива ORG должна быть использована для размещения переменных в крайне важно м месте ОЗУ. Директива не имеет параметров.

Синтаксис:

ldi r30,low(var1) ; Загрузить младший байт регистра Z

ldi r31,high(var1) ; Загрузить старший байт регистра Z

ld r1,Z ; Загрузить var1 в регистр r1

CSEG - программный сегмент. Директива CSEG определяет начало программного сегмента. Исходный файл может состоять из нескольких программных сегментов, которые объединяются в один программный сегмент при компиляции. Программный сегмент является сегментом по умолчанию. Программные сегменты имеют свои собственные счётчики положения, которые считают не побайтно, а по словно. Директива ORG должна быть использована для размещения кода и констант в крайне важно м месте сегмента. Директива CSEG не имеет параметров.

Синтаксис:

DSEG ; Начало сегмента данных

vartab: .BYTE 4 ; Резервирует 4 байта в ОЗУ

CSEG ; Начало кодового сегмента

const: .DW 2 ; Разместить константу 0x0002 в памяти программ

mov r1,r0 ; Выполнить действия

ESEG - сегмент EEPROM. Директива ESEG определяет начало сегмента EEPROM. Исходный файл может состоять из нескольких сегментов EEPROM, которые объединяются в один сегмент при компиляции. Сегмент EEPROM обычно состоит только из директив DB, DW и меток. Сегменты EEPROM имеют свои собственные побайтные счётчики положения. Директива ORG должна быть использована для размещения переменных в крайне важно м месте EEPROM. Директива не имеет параметров.

Синтаксис:

DSEG ; Начало сегмента данных

var1: .BYTE 1 ; зарезервировать 1 байт для var1

table: .BYTE tab_size ; зарезервировать tab_size байт.

eevar1: .DW 0xffff ; проинициализировать 1 слово в EEPROM

ORG - Установить положение в сегменте. Директива ORG устанавливает счётчик положения равным заданной величинœе, которая передаётся как параметр.
Размещено на реф.рф
Важно заметить, что для сегмента данных она устанавливает счётчик положения в SRAM (ОЗУ), для сегмента программ это программный счётчик, а для сегмента EEPROM это положение в EEPROM. В случае если директиве предшествует метка (в той же строке) то метка размещается по адресу указанному в параметре директивы. Перед началом компиляции программный счётчик и счётчик EEPROM равны нулю, а счётчик ОЗУ равен 32 (поскольку адреса 0-31 заняты регистрами). Обратите внимание что для ОЗУ и EEPROM используются побайтные счётчики а для программного сегмента - пословный.

Синтаксис:

ORG выражение

DSEG ; Начало сегмента данных

ORG 0x37 ; Установить адрес SRAM равным 0x37

variable: .BYTE 1 ; Зарезервировать байт по адресу 0x37H

CSEG .ORG 0x10 ; Установить программный счётчик равным 0x10

mov r0,r1 ; Данная команда будет размещена по адресу 0x10

Синтаксис:

· Макросы

MACRO - начало макроса. С директивы MACRO начинается определœение макроса. В качестве параметра директиве передаётся имя макроса. При встрече имени макроса позднее в тексте программы компилятор заменяет это имя на тело макроса. Макрос может иметь до 10 параметров, к которым в его телœе обращаются через @0-@9. При вызове параметры перечисляются через запятые. Определœение макроса заканчивается директивой ENDMACRO.

По умолчанию в листинг включается только вызов макроса, для разворачивания макроса крайне важно использовать директиву LISTMAC. Макрос в листинге показывается знаком +.

Синтаксис:

MACRO макроимя

MACRO SUBI16 ; Начало макроопределœения

subi @1,low(@0) ; Вычесть младший байт параметра 0 из параметра 1

sbci @2,high(@0) ; Вычесть старший байт параметра 0 из параметра 2

CSEG ; Начало программного сегмента

SUBI16 0x1234,r16,r17 ; Вычесть 0x1234 из пары r17:r16

ENDMACRO - конец макроса. Директива определяет конец макроопределœения, и не принимает никаких параметров. Для информации по определœению макросов смотрите директиву MACRO.

Синтаксис:

MACRO SUBI16 ; Начало определœения макроса

subi r16,low(@0) ; Вычесть младший байт первого параметра

sbci r17,high(@0) ; Вычесть старший байт первого параметра

LISTMAC - включить разворачивание макросов в листинге. После директивы LISTMAC компилятор будет показывать в листинге содержимое макроса. По умолчанию в листинге показывается только вызов макроса и передаваемые параметры.

Синтаксис:

MACRO MACX ; Определœение макроса

add r0,@0 ; Тело макроса

ENDMACRO ; Конец макроопределœения

LISTMAC ; Включить разворачивание макросов

MACX r2,r1 ; Вызов макроса (в листинге будет показано тело макроса)

· Выражения

EQU - установить постоянное выражение. Директива EQU присваивает метке значение. Эта метка может позднее использоваться в выражениях. Метка которой присвоено значение данной директивой не должна быть переназначена и её значение не должна быть изменено.

Синтаксис:

EQU метка = выражение

EQU io_offset = 0x23

EQU porta = io_offset + 2

CSEG ; Начало сегмента данных

clr r2 ; Очистить регистр r2

SET - Установить переменный символический эквивалент выражения. Директива SET присваивает имени неĸᴏᴛᴏᴩᴏᴇ значение. Это имя позднее должна быть использовано в выражениях. Причем в отличие от директивы EQU значение имени должна быть изменено другой директивой SET.

Синтаксис:

SET имя = выражение

SET io_offset = 0x23

SET porta = io_offset + 2

CSE ; Начало кодового сегмента

clr r2 ; Очистить регистр 2

out porta,r2 ; Записать в порт A

DEF - назначить регистру символическое имя. Директива DEF позволяет ссылаться на регистр через неĸᴏᴛᴏᴩᴏᴇ символическое имя. Назначенное имя может использоваться во всœей нижеследующей части программы для обращений к данному регистру. Регистр может иметь несколько различных имен. Символическое имя должна быть переназначено позднее в программе.

Синтаксис:

DEF Символическое_имя = Регистр

ldi temp,0xf0 ; Загрузить 0xf0 в регистр temp (R16)

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

push r30 ; инструкция вызовет предупреждение, AT90S1200 её не имеет

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 ; Вложить определœения портов

· Листинги

LIST - включить генерацию листинга. Директива LIST указывает компилятору на крайне важно сть создания листинга. Листинг представляет из себя комбинацию ассемблерного кода, адресов и кодов операций. По умолчанию генерация листинга включена, однако данная директива используется совместно с директивой NOLIST для получения листингов отдельных частей исходных файлов.

Синтаксис: .LIST

NOLIST - выключить генерацию листинга. Директива NOLIST указывает компилятору на крайне важно сть прекращения генерации листинга. Листинг представляет из себя комбинацию ассемблерного кода, адресов и кодов операций. По умолчанию генерация листинга включена, однако должна быть отключена данной директивой. Кроме того данная директива должна быть использована совместно с директивой LIST для получения листингов отдельных частей исходных файлов

Синтаксис: .NOLIST

Пример: .NOLIST ; Отключить генерацию листинга

INCLUDE "macro.inc" ; Вложенные файлы не будут

INCLUDE "const.def" ; отображены в листинге

LIST ; Включить генерацию листинга

Директивы ассемблера - понятие и виды. Классификация и особенности категории "Директивы ассемблера" 2017, 2018.



© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows