С чего начинается любая программа

Итак, наконец-то мы добрались до самого главного — разработки рабочей части программы, то есть до той части, которая, собственно, и будет решать поставленную задачу.

С чего начинается разработка программы? Естественно, разработка любой программы начинается с постановки задачи. Иначе что делать-то, вообще? Задачу нужно формулировать как можно более детально, потому что правильно и полно поставленная задача — это уже половина решения.

Здесь работа программиста сводится к тому, чтобы увидеть и сформулировать (или потребовать от заказчика, если программа пишется не для себя) все необходимые для решения данные. Естественно, в большинстве случаев всё сразу увидеть невозможно, поэтому в процессе разработки задача обычно обрастает дополнительными деталями и условиями, это нормально, но лучше сразу получить исходных данных по максимуму.

После того, как задача сформулирована, нужно в деталях проработать и описать её решение. Прямо по шагам расписать — что, зачем и при каких условиях нужно делать. Такая последовательность необходимых для решения задачи действий называется алгоритмом.

С чего начинается любое оздоровление? Система ABCD — к.м.н., врач-лечебник Антилевский В.В.

Этот очень важный этап (написание алгоритма) зачастую упускается, хотя на самом деле, достаточно детально прописанный алгоритм довольно легко преобразуется в программу на любом языке программирования. Даже если вы можете написать программу сходу, без всякого нарисованного на бумаге алгоритма, это вовсе не значит, что алгоритма нет. Он всё равно есть, но только он существует не на бумаге, а у вас в голове. Без алгоритма программу нельзя написать по определению.

Понятно, что детально проработать сразу всё решение (т.е. написать подробный алгоритм) — тоже довольно проблематично, поэтому сначала определяют основные крупные этапы, которые потом всё более и более детализируют и, в конце-концов, алгоритм становится настолько детальным, что остаётся только заменить описанные действия командами ассемблера (или любого другого языка программирования) и мы получим готовую программу.

Для удобства и наглядности отдельные действия алгоритма принято записывать в различные геометрические фигуры (некоторые из них показаны на рисунке слева). Вообще-то, этих обозначений гораздо больше и, по-моему, на них даже существует какой-то стандарт, если интересно — поищите в Интернете. В принципе, повторюсь, это нужно только для удобства, можете делать так, как вам нравится: каждый шаг записывать в прямоугольники, просто писать все шаги столбиком, это совершенно без разницы, главное — это чётко понимать какие именно нужно выполнить действия и в какой последовательности.

Последовательность выполнения шагов (направление обхода алгоритма) принято считать сверху — вниз и слева — направо. Если эта последовательность нарушается, то направление принято указывать стрелками.

Для того, чтобы всё вышесказанное стало более понятно, давайте разберём описанные этапы разработки программы на конкретном примере:

Пусть мы хотим организовать с помощью микроконтроллера PIC16F628A мигание обычным маломощным светодиодом. Это, собственно, и есть задача. Казалось бы всё понятно.

Любая болезнь начинается именно с этого

На самом деле, такая формулировка задачи достаточно размыта, и в таком виде задача не решаема, поскольку не ясно — с какой частотой мы хотим мигать, какова скважность импульсов, как светодиод подключен. Можно, например, подключить анод светодиода к плюсу (через ограничительный резистор, естественно), а катод — к контроллеру, тогда светодиод будет загораться при подаче низкого уровня сигнала на выход контроллера, а можно подключить катод светодиода к минусу, а анод — к контроллеру, тогда светодиод будет загораться при подаче высокого уровня на выход контроллера.

Итак, сначала нам надо максимально детализировать задачу (естественно, это касается того, что нужно для решения, например, то, каким лаком потом будет покрыта плата, нас на этапе программирования совершенно не волнует).

Пусть мы решили, что мигать мы будем с частотой 1 Гц (1 импульс в секунду), скважность импульсов будет равна 2 (время импульса равно времени паузы) и анод светодиода будет подключен к выходу контроллера RB3. Всё, теперь наша задача сформулирована достаточно детально для того, чтобы начать разрабатывать алгоритм её решения.

Сначала пишем просто крупные этапы:

  1. Включить светодиод
  2. Подождать 0,5 сек
  3. Выключить светодиод
  4. Подождать 0,5 сек
  5. Перейти к первому пункту

Теперь давайте каждый из этих этапов детализируем.

  1. Мы решили, что анод светодиода подключен к контроллеру, а катод к минусу питания, следовательно светодиод будет загораться при подаче на выход контроллера высокого уровня. В нашем случае светодиод подключен к выходу RB3, то есть первый пункт можно записать так: подать высокий уровень на выход RB3.
  2. Паузу нужной длительности можно организовать по разному — с помощью таймеров, с помощью пустых циклов и т.д. Как конкретно — решать вам. Пусть в данном случае мы решили сделать паузу с помощью пустых циклов. То есть нужно просто организовать цикл, который заданное количество раз выполняет какую-нибудь не влияющую на дальнейшую работу программы команду (в принципе можно выполнять любую команду, но в пиках есть специальная команда, которая ничем кроме траты времени не занимается — nop). Общее время, затраченное на выполнение этого цикла должно быть равно требуемому времени задержки. Зная время выполнения отдельных команд, общее время цикла нетрудно посчитать. Для увеличения времени задержки, можно вкладывать один цикл в другой. Ну ладно, об этом мы подробнее поговорим позднее, а пока вернёмся к нашему алгоритму.
  1. заносим в переменную A значение, равное количеству циклов, которые мы хотим отсчитать
  2. выполняем пустую команду
  3. уменьшаем значение переменной А
  4. проверяем, если А=0, значит мы отсчитали заданное время, выходим из цикла и продолжаем дальнейшее исполнение программы. Если А не равно 0, то переходим ко второму пункту.

Итак, окончательно алгоритм нашей основной программы выглядит так:

  1. Подать высокий уровень на выход RB3
  2. Вызвать подпрограмму паузы
  3. Подать низкий уровень на выход RB3
  4. Вызвать подпрограмму паузы
  5. Перейти к первому пункту

Ну вот, теперь наш алгоритм готов к тому, чтобы заменить обычный человеческий язык на язык ассемблера. Открываем доку на контроллер и смотрим. Сначала смотрим, как работает порт B. Видим, что для того, чтобы подать на выход RB3 высокий уровень, нужно установить третий бит в регистре PORTB в 1, чтобы подать на выход низкий уровень, нужно установить этот бит в 0. Вызов подпрограммы осуществляется командой Call, безусловный переход — командой goto.

Читайте также:
Программа жсс уралсиб отзывы

Открываем список команд и видим, что бит в регистре устанавливается командой bsf. То есть, команда установки в 1 будет выглядеть так: bsf PORTB,3. Сбрасывается бит командой bcf.

После перевода на язык ассемблера наша основная программа будет выглядеть так:

nachalo: это просто метка, чтобы было понятно, куда возвращаться командой goto. Компилятор вычислит адрес команды, на которую она указывает (адрес первой команды после метки) и подставит этот адрес в команду goto
bsf PORTB,3
Call pause pause — это метка, которая стоит перед подпрограммой (она указывает на первую команду подпрограммы)
bcf PORTB,3
Call pause
goto nachalo

Кроме того, раз мы используем порт B, то нужно посмотреть в доке, как происходит инициализация порта, настройка на выход канала RB3 и добавить соответствующий код в начало программы, плюс если вы используете имена регистров, а не сразу адреса, то в шапке программы нужно привести соответствие имён адресам.

Аналогично нужно составить алгоритм для подпрограммы паузы (выше мы уже фактически его написали) и перевести его на язык ассемблера, плюс, при необходимости, нужно дописать инициализацию и шапку, в зависимости от того, какие дополнительные модули и регистры мы использовали в подпрограмме.

Вот и всё! Именно таким способом обычно и пишутся программы, причём не только на ассемблере, но и на любых других языках программирования.

На этом закончим с вводной общей частью и далее рассмотрим очень важную задачу любых алгоритмов и программ — организацию циклов и ветвлений.

  1. Часть 1. Необходимые инструменты и программы. Основы MPLAB
  2. Часть 2. Что такое микроконтроллер и как с ним работать
  3. Часть 3. Структура программы на ассемблере
  4. Часть 4. Разработка рабочей части программы. Алгоритмы
  5. Часть 5. Ассемблер. Организация циклов и ветвлений
  6. Часть 6. Как перевести контроллер в режим программирования и залить в него прошивку

Понравилась статья? Поделись с друзьями!

Источник: radiohlam.ru

С чего начинается разработка программного обеспечения?

Это может быть листок бумаги исписанный разными почерками и с пятном от кофе в уголке, а может быть строгий документ в соответствие с ГОСТ «34.602-2020», подразумевающий подготовку документации в соответствие с ГОСТ «Р 59795-2021», включая программу и методику испытаний. Мы понимаем что тратить много времени, сил, а зачастую и денег на подготовку объемной документации мало кто хочет, поэтому подготовили облегчённый подход к разработке технического задания, в нём нет ничего нового, скорее тот минимум который поможет прозрачно донести требования до исполнителя.

  1. Цели. Во первых необходимо определить цели, это те программные решения которые ожидает получить заказчик от реализации проекта. Именно над реализацией целей должна фокусироваться разработка. Формулирование целей позволяет избежать избыточных, не способствующих достижению целей, требований, и не упустить ключевых.
  2. Задачи. Здесь описываются задачи разработки, которые потребуется решить для достижения конкретных целей (запросы на реализацию функций совокупность которых обеспечит заказчика необходимым и достаточным инструментарием).
  3. Требования к подсистемам. Здесь подробно описываются подсистемы в рамках которых должны реализовываться функции необходимые для достижения задач. Подсистема не обязательно должна быть отдельным модулем, скорее логическим блоком. Для каждой подсистемы описывается: назначение, полный перечень всех необходимых возможностей, способ доступа к ним, логика работы, требования к соответствующему интерфейсу (программному или пользовательскому), в т.ч. требования к входным и выходным данным (если имеются), вызываемые сервисы в рамках взаимодействия, условия применения, требования к внешней среде и состоянию прочих подсистем.
  4. Сценарии применения. Для представления о том как конкретно будет использоваться функционал в рамках решения задач, важно описать конкретные сценарии последовательного выполнения рабочих процессов с использованием разрабатываемого решения. Данные сценарии должны затронуть весь функционал, при этом нет нужды описывать комбинаторику всех возможных вариантов его применения, а только тот минимум который осветит каждую необходимую, для достижения целей, возможность и логику ее применения. Наличие сценариев применения уточняет требования к подсистемам, подсказывая как именно лучше реализовать функции и конкретизирует как будут выполняться задачи, позволяя на ранних этапах убедиться в эффективности разрабатываемого решения.
  5. Описание объекта автоматизации. Описание деятельности или технических решений, усовершенствование которых планируется произвести за счет достижения целей разработки. Как сейчас реализуются процессы подлежащие автоматизации, присущие проблемы.
  • Управление разработкой
  • Подготовка технической документации

Источник: habr.com

Програмирование в AVR Studio 5 с самого начала. Часть 5

Для того чтобы писать более сложные программы, нужно хорошо представлять структуру и взаимодействие разных узлов микроконтроллера между собой, но основные принципы сохраняются независимо от модели контроллера. В принципе человек, который изучил микроконтроллеры PIC, достаточно быстро осваивает AVR или ARM.
Управление микроконтроллером осуществляется изменением логического уровня ячеек (битов) в регистрах, расположенных в оперативной памяти. Конкретному устройству соответствует конкретный регистр, как правило 8-битный (1 байтный), состоящий из 8 ячеек памяти. В любую ячейку можно записать 0 или 1.

Создадим произвольную таблицу, где каждая строка состоит из 8 ячеек и имеет свой порядковый номер, соответствующий одному регистру. Пусть наша таблица состоит из 128 ячеек или из 16 восьмибитных регистров.

В микроконтроллере есть разные функциональные устройства – это порты, таймеры, АЦП, устройства ШИМ, устройства последовательного приема и передачи данных, и много еще чего. Кроме этого функции конкретного устройства могут меняться, например, сначала принять информацию, а затем переключиться на передачу. Как же они работают? Все проще, чем кажется! Функции определенного устройства жестко привязывается к конкретным ячейкам памяти. Например, если нам нужно на какую-то ножку подать напряжение, мы устанавливаем конкретную ячейку в 1.

Пусть, к примеру, за вывод положительного напряжения на 4 ножку отвечает ячейка 9h:3h. Значит, если мы пропишем в ячейку 9h:3h единицу, то на 4- ой ножке получим положительное напряжение. А как мы узнаем, что эта ячейка отвечает за эту функцию? Ячеек много и запомнить номер каждой ячейки очень сложно.

Читайте также:
Как обновить ярлык программы

Чтобы было легко работать, производители присвоили каждой строке с определенным порядковым номером, называемым адресом, свое имя, соответствующее устройству. Пусть у нас строка 9h, будет называться регистром PortB, строка 8h регистром PinB, а строка 7h регистром DdrB. Таким образом 7h, 8h, 9h – это адреса регистров с названиями PortB, PinB, DdrB.
Соответствующие регистры указываются в специальном файле с расширением .inc, в самом начале программы. Этот файл становится доступным с помощью директивы .include
Например для attiny2313:

.include «at2313def.inc»
Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.

В Ассемблере версии 2.1.9 директивы начинаются с точки, также как и директивы AVRASM.
Директивы не транслируются непосредственно в машинный код. Они используются для указания компилятору положения кода в программной памяти, для инициализации памяти и для других целей.

.CSEGSIZE – размер памяти программ
Устройства AT94K имеют раздел памяти, которую пользователь может присоединить к памяти программ AVR или памяти данных. Программа и данные SRAM подразделены на три блока: 10K x 16 память программ, 4K x 8 память данных и 6K x 16 или 12K x 8 перестраиваемой SRAM, которые могут быть распределены между программной памятью (до 4-х разделов по 2K x 16) и памятью данных (до 8-ми разделов по 4Kx8).
Эта директива используется, чтобы определять размер программного блока памяти.
Синтаксис:
.CSEGSIZE = 10 | 12 | 14 | 16

.CSEGSIZE = 12 ; Определить размер памяти программ как 12K x 16.

.DD – определяет двойное слово(а) в памяти программ и EEPROM.
.DQ – определяет четверное слово(а) в памяти программ и EEPROM.
Эти директивы подобно директиве .DW определяют нужное количест-во слов 32-битных (двойные слова) и 64-битных (четверные слова) соот-ветственно.

МЕТКА: .DD список выражений МЕТКА: .DQ список выражений
.CSEG varlist: .DD 0, 0xfadebabe, -2147483648, 1 << 30 .ESEG eevarlst: .DQ 0,0xfadebabedeadbeef, 1 << 62

#define – определить макрос препроцессора
Синтаксис:

1) #define имя [value] 2) #define имя(arg. ) [value]

Описание:
Определяет макрос препроцессора. Есть две формы макроса: (1) – объект, который в основном определяет константу, и (2) – функция, в которую делают подстановку параметра.
Value – величина (значение) может быть любой строкой, она не определена, пока макрос не будет распакован (расширен). Если величина не определена, она = 1.
Форма (1) макроса может быть определена из командной строки использованием опции -D.
Когда использована форма (2), макрос должен вызываться с тем же количеством аргументов, с которыми он определен. Любые arg. и value будут заменены соответствующими аргументами и значениями, когда макрос расширяется. Отметьте, что левые скобки должны идти сразу после имени (никаких пробелов между ними), в противном случае это будет интерпретировано как часть величины макроса формы (1).
Примеры:
Обратите внимание на размещение первой скобки ‘(‘ в примерах, приведенных ниже.

#define EIGHT (1 << 3) #define SQR(X) ((X)*(X))

.UNDEF – отменить определение символьного имени регистра
Описание:
Отмена определения имени, которое прежде определялось директивой .DEF или #define. Это позволит избежать сообщений об ошибке при многократном использовании регистра. Если имя прежде не определено, директива .undef будет проигнорирована, это в соответствии со стандартом ANSI C. То же можно сделать из командной строки, используя опцию -U.
Синтаксис:
.UNDEF символ
Пример:

.DEF var1 = R16 ldi var1, 0x20 . ; сделает что-то с использованием var1. .UNDEF var1 .DEF var2 = R16; теперь использование R16 не будет вызывать предупреж-дения.

#ifdef или .IFDEF – директива условной компиляции
Синтаксис:
#ifdef имя
Описание:
Сокращение от #if defined. Все следующие строки до соответствующего #endif, #else или #elif условно ассемблируются, если имя определено прежде.
Пример:
#ifdef FOO
……….. // делает что-то.
#endif

#ifndef – директива условной компиляции
Синтаксис:
#ifndef имя
Описание:
Сокращенная запись от #if not defined. Противоположность #ifdef. Все следующее строки до соответствующих #endif, #else или #elif условно ассемблируются, если имя не определено.

#if
#elif – директивы условной компиляции
Синтаксис:

#if условие #elif

Описание:
Все следующие строки до соответствующего #endif, #else или #elif условно ассемблируются, если условие является истиной (не равно 0). Условие – любое целое выражение, включая макросы препроцессора, которые расширены (распакованы). Препроцессор распознает оператор defined(name), который возвращает 1, если имя определено, и 0 – в противном случае. Любые не определенные символы, использованные в условии по умолчанию, = 0.
Условие может быть вложенным на произвольную глубину.
#elif оценивает условие так же, как #if, за исключением того, что только что оценено, и если никакой предшествующей ветвлению командой #if … #elif данное условие не было оценено как истина.
Примеры:

#if 0 ……….. // Здесь код никогда не компилируется. #endif #if defined(__ATmega48__) || defined(__ATmega88__) …………. // код специфичный для этих устройств. #elif defined (__ATmega169__) ………… // код специфичный для ATmega169. #endif

Препроцессор AVRASM2 не делает отдельный проход до вызова Ассемблера, он встроенная часть Ассемблера. Это может вызвать некоторую неразбериху, если препроцессор и Ассемблер создают аналогичные разнотипные объекты (например, #if и .if условия). Это также вызывает сбои препроцессора при использовании условий в макросах Ассемблера, которые нужно оценивать, когда макрос распакован, а не когда он определен. Условные выражения не могут распределять начало или конец макроопределения (но могут распределить целое макроопределение, включая начало и окончание).

.ENDIF – директива условного ассемблирования
Завершает условный блок кода после директив .IF, .IFDEF или .IFNDEF. Условные блоки (.IF. ELIF. .ELSE. ENDIF) могут быть вложенными, но все они должны быть выполнены до конца файла (условные блоки не могут работать в нескольких файлах).
Синтаксис:

.ENDIF .IFDEF |.IFNDEF

.ELIF, .ELSE– директивы условного ассемблирования
.ELIF включит в процесс ассемблирования код, следующий за ELIF, до соответствующего ENDIF или следующего ELIF, если expression явля-ется истиной. В противном случае этот код будет пропущен.
.ELSE включит код до .ENDIF, если условия в директиве .IF и условия во всех .ELIF были ложными.
Синтаксис:
.ELIF
.ELSE
.IFDEF |.IFNDEF
.
.ELSE | .ELIF
.
.ENDIF
Пример:

.IFDEF DEBUG .MESSAGE «Debugging..» .ELSE .MESSAGE «Release..» .ENDIF

Читайте также:
Программа для замера звука в децибелах

#else – директива условной компиляции
Синтаксис:
#else
Описание:
Все следующие строки до соответствующего #endif условно ассемблируются, если никакая предшествующая ветка в составе последовательности #if. #elif. не оценена как истина.
Пример:

#if defined(__ATmega48__) || defined(__ATmega88__) …………. // код специфичный для этих МК #elif defined (__ATmega169__) ………….. // код специфичный для ATmega169 #else #error «Unsupported part:» __PART_NAME__ // сообщение об ошибке. #endif

.IF, .IFDEF, .IFNDEF – директивы условного ассемблирования
Условное ассемблирование включает команды из исходного кода в процесс ассемблирования выборочно. Директива IFDEF включит код до соответствующей директивы ELSE, если определен. Символ должен быть определен директивами EQU или SET (не будет работать с директивой DEF). Директива IF, если отлично от 0, включит код до соответствующей директивы ELSE или ENDIF. Возможны до пяти уровней вложенности.
Синтаксис:
.IFDEF
.IFNDEF
.IF
.IFDEF |.IFNDEF
.
.ELSE | .ELIF
.
.ENDIF

.ERROR – вывод строки с сообщением об ошибке.
.WARNING – вывод строки с предупреждением.
.MESSAGE – вывод строки с сообщением.
Синтаксис:
.ERROR “строка”
.WARNING “строка”
.MESSAGE “строка”
Описание:
.ERROR – (ошибка) выдает сообщение об ошибке, останавливает компиляцию и увеличивает счетчик ошибок Ассемблера, тем самым помогает успешному ассемблированию программы. #error определена в стандарте ANSI C.

.IFDEF TOBEDONE .ERROR «Still stuff to be done..» .ENDIF

.WARNING – (предупреждение) выдает предупреждающее сообщение и увеличивает счетчик предупреждений Ассемблера. В отличие от error не останавливает компиляцию. Директива .warning не определена в стандарте ANSI C, но обычно реализована в препроцессорах, как, например, в препроцессоре GNU C.
Пример:
.IFDEF EXPERIMENTAL_FEATURE
.WARNING «This is not properly tested, use at own risk.»

.ENDIF
.MESSAGE – (сообщение) выдает сообщение и не влияет на счетчики ошибок и предупреждений Ассемблера. .message не определено в стандарте ANSI C.

.IFDEF DEBUG .MESSAGE «Debug mode» .ENDIF

Для всех директив сообщения включают файловое имя и номер строки, подобно нормальным сообщениям об ошибках и предупреждениях.
Макросы препроцессора распаковываются, кроме заключенного внутри двойных кавычек («).
Пример:
.error «Неподдерживаемый МК:» __PART_NAME__

#include или .INCLUDE – включение другого файла
Синтаксис:
1) » file «
2) #include
Описание:
Включение файла. Две формы отличаются тем, что (1) ищет сначала текущий рабочий директорий и функционально эквивалентна директиве .include Ассемблера. (2) ищет в установленном месте – обычно в директории C:Program FilesAtmelAVR ToolsAvrAssembler2Appnotes. Обе формы ищут включаемые файлы в известном месте установленным Ассемблером.
Лучше использовать абсолютные имена пути к файлу в директивах #include, так как поиск файлов затрудняется при перемещении проектов между другими директориями/компьютерами. Используйте опцию -I командной строки, чтобы определять путь, или установите его в AVR Studio — Project — Assembler Options, в окошке Additional include path.
Примеры:

#include; Ищет в каталоге Appnotes. #include «mydefs.inc» ; Ищет в рабочем каталоге. ; iodefs.asm: .EQU sreg = 0x3f ; Status register. .EQU sphigh = 0x3e ; Stack pointer high. .EQU splow = 0x3d ; Stack pointer low. ; incdemo.asm .INCLUDE iodefs.asm ; Include I/O definitions. in r0,sreg ; Read status register.

.OVERLAP – перекрытие
.NOOVERLAP – неперекрытие
Эти директивы нужны для проектов со специфическими особенностями и не должны использоваться в обычных случаях. Они к настоящему времени влияют только на активный сегмент (cseg/dseg/eseg).
Директивы .overlap/nooverlap выделяют секцию кода/данных, которой будет позволено перекрываться с кодом/данными, определенными где-нибудь еще, без генерации сообщения об ошибке или предупреждения. Это полностью независимо от того, что установлено с использованием директивы перекрытия #pragma. Атрибут допустимого перекрытия останется эффективным по директиве .org, но не последует по директивам .cseg/.eseg/.dseg (каждый сегмент выделяется отдельно).

.OVERLAP .NOOVERLAP Пример: .overlap .org 0 ; Секция #1. rjmp default .nooverlap.org 0 ; Секция #2. rjmp RESET ; Здесь нет ошибки. .org 0 ; Секция #3. rjmp RESET ; Ошибка, так как есть перекрытие с секцией #2.

Типичное использование этого – устанавливать некоторую форму кода или данных по умолчанию, которые позже могут модифицироваться перекрытием с другими кодом или данными без необходимости вывода сообщения о перекрытии.

#pragma общего назначения
Синтаксис:
1) #pragma warning range byte option – предупреждение о байтовом диапазоне;
2) #pragma overlap option – перекрытие;
3) #pragma error instruction – ошибки инструкций;
4) #pragma warning instruction – предупреждения по поводу инструкций.
Описание:
1. Ассемблер оценивает постоянные целые выражения как 64 — битные знаковые целые. Когда такие выражения использованы как непосредственные операнды, они должны быть включены в количество битов, требующихся команде. Для большинства операндов выход из диапазона вызовет сообщение ошибки «операнд из диапазона». Тем не менее непосредственные байтовые операнды для команд ldi, cpi, ori, andi, subi, sbci имеют несколько возможных интерпретаций, в зависимости от опции (option):
option = integer: операнд непосредственно оценен как целое, и если его значение за пределами диапазона (-128 . 255), будет дано предупреждение. Ассемблер не знает, что предполагает пользователь: операнд целым, со знаком или без знака, следовательно, он допускает любое значение со знаком или без знака, которое умещается в байт.
option = overflow (умолчание): операнд оценивается как байт без знака, и любые биты знака будут проигнорированы. Эта опция пригодна при работе с битовыми масками, когда интерпретация целого должна вызывать массу предупреждений, подобно ldi r16, ~ ((1 option = none: не выводится никаких предупреждений о диапазоне для байтовых операндов. Не рекомендуется.
2. Если две секции кода, размещенные в памяти директивой .org, перекрываются, передается сообщение об ошибке. Опции модифицируют это поведение следующим образом:
option = ignore: игнорирует условия перекрытия и не выдаются никакие ошибки, никакие предупреждения. Не рекомендуется.
option = warning: при обнаружении перекрытия выдается предупреждение.
option = error: считает перекрытие как ошибку, это рекомендовано устанавливать по умолчанию.
3. Использование инструкций, которые не поддерживаются на выбранном устройстве, вызывает ошибку Ассемблера (поведение по умолчанию).
4. Использование инструкций, которые не поддерживаются на выбранном устройстве, вызывает предупреждение Ассемблера.

Исключён фрагмент. Полный вариант доступен меценатам и полноправным членам сообщества.

Продолжение следует!
Дальше разберем выражения и функции ассемблера AVRASM2 и
определимся с инициализацией программ.

Источник: datagor.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru