Обсуждаем контроллеры компании Atmel.
Ответить

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн авг 28, 2017 17:41:46

Ну.. на побитовое И он тоже не особо был похож :)

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн авг 28, 2017 19:15:21

Всем спасибо за ответы, но все таки хотелось бы задать еще несколько уточняющих вопросов если позволите.
это понятно, что биты USIWMO, USICS1, USICLK и USITC принадлежат регистру USICR, но если я правильно понял в каждом из этих выражений 1<<USIWMO, 1<<USICS1, 1<<USICLK и 1<<USITC единица или или сдвинется на один разряд в лево или нет (в зависимости от установок битов USIWMO, USICS1, USICLK и USITC) затем между выражениями произведена операция побитового "или" и в результате константа может принять одно из трех значений 1, 2 или 3. (Для чего попытаюсь разобраться).

на сколько я знаю в ассемблере AVR нет таких операторов "<<" и "|" там они пишутся по другому и компилятор эти начертания по логике не должен понять (или я не прав??)

COKPOWEHEU пишет "Полностью аналогичен x = x*2^y не совсем понятно аналогичен чему. Насколько я понимаю х умножается на 2, а затем проводится "исключающее или" между произведением и "у" , но это опять операторы СИ
Спасибо

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн авг 28, 2017 19:45:12

Всё просто. Например, для ATtiny2313 (для номеров битов смотрим либо даташит, либо соответствующий инклюд:
Код:
ldi r16, (1<<USIWMO)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)
ldi r16, (1<<4)     |(1<<3)     |(1<<1)     |(1<<0)
ldi r16, 0b00010000 |0b00001000 |0b00000010 |0b00000001
ldi r16, 0b00011011

Все записи полностью идентичны, но первая гораздо понятнее, чем "магическое" число в последней.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн авг 28, 2017 21:01:13

sibiryak69 писал(а):на сколько я знаю в ассемблере AVR нет таких операторов "<<" и "|" там они пишутся по другому и компилятор эти начертания по логике не должен понять (или я не прав??)
ассемблер состоит из двух частей: мнемокодов команд и операций ассемблера (терминология моя). мнемокод - это символьный аналог команды ALU, например, mov, ldi или rol. разумеется, последний мнемокод означает "сдвиг влево", т.к. вроде бы является аналогом оператора Си <<, и это на самом деле так. но есть еще операция языка ассемблера <<, которая означает ровно то же самое, но выполняется ассемблером на этапе компиляции. то есть не ALU микроконтроллера делает этот сдвиг, а сам ассемблер все двигает, подставляя в команду уже готовый результат этих сдвигов.
улавливаете разницу?

rol r3, 4 в этом случае полностью эквивалентно rol r3, 1<<2, т.к. 1<<2 это и будет 4. таким образом, во время написания программы вы пользуетесь удобными вам константами, компилятор ассемблера делает необходимые вычисления сам, и подставляет в мнемокоды уже готовые числа.

итак, разница в операторе << языка Си и ассемблера в том, что в Си этот оператор может выполняться либо на этапе компиляции (макросы), либо на этапе исполненияя программы, а в ассемблере этот оператор всегда выполняется на этапе компиляции. и, естественно, оба операнда этого оператора должны быть константами, иначе компилятор не сможет выполнить эту работу - попробуйте написать что-то типа ldi r17, 1<<r6 - получите ошибку компиляции.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт авг 29, 2017 07:21:37

У АВРок системой команд официально не предусматривается прямое указание в команде количества сдвигов в случае с командами циклического сдвига / вращения (ROL\ROR и подобное).
Это преимущество только за системой команд 8088/8086 и выше (и то, там еще регистр-счетчик вроде задействуется, ежли шклерозь не изменяет...).
Конструкция rol rn,x скорее всего должна быть заменена препроцессором на цепочку из х команд rol rn, воспринимаемых самим МК... (если вообще будет пропущена компилятором - сам так "заворачивать" не пробовал)...
:dont_know:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вт авг 29, 2017 07:33:21

COKPOWEHEU пишет "Полностью аналогичен x = x*2^y не совсем понятно аналогичен чему. Насколько я понимаю х умножается на 2, а затем проводится "исключающее или" между произведением и "у" , но это опять операторы СИ
^ в смысле возведение в степень а не XOR.
WiseLord писал(а):Ну.. на побитовое И он тоже не особо был похож :)
Да, что-то я там совсем странное написал... хотя бы исправленная версия нормально?
sibiryak69 писал(а):на сколько я знаю в ассемблере AVR нет таких операторов "<<" и "|" там они пишутся по другому и компилятор эти начертания по логике не должен понять (или я не прав??)
ARV уже ответил, но продублирую. Сборка программы состоит из 2-х этапов: препроцессирование и компиляция (вообще-то есть еще линковка, но родной AVR ассемблер этого напрямую не умеет). На первом этапе препроцессор анализирует текст программы, не глядя на синтаксис целевого языка и обрабатывая только свои конструкции. Например, подставляет макросы прямо в текст программы, заменяет .def и .equ на соответствующие значения, подставляет вместо .include содержимое файла, и так далее. Примерно таким образом:
Код:
.def temp=r16
.macro outi
  ldi temp, @1
  out @0, temp
.endm
outi PORTB, 1
это разворачивается последовательно в
Код:
ldi temp, (1<<2)
out PORTB,temp

Код:
ldi r16,0b00000100;основание системы счисления я оставил наиболее наглядным, компилятору-то без разницы
out 0x18, r16

Точно также Си-подобные операторы |, &, << и т.п. относятся к препроцессору и выполняются перед запуском компилятора, которому в результате достаются готовые вычисленные константы и адреса.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Чт авг 31, 2017 16:15:30

Всё просто. Например, для ATtiny2313 (для номеров битов смотрим либо даташит, либо соответствующий инклюд:
Код:
ldi r16, (1<<USIWMO)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)
ldi r16, (1<<4)     |(1<<3)     |(1<<1)     |(1<<0)
ldi r16, 0b00010000 |0b00001000 |0b00000010 |0b00000001
ldi r16, 0b00011011

Все записи полностью идентичны, но первая гораздо понятнее, чем "магическое" число в последней.


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

Добавлено after 13 minutes 38 seconds:
sibiryak69 писал(а):на сколько я знаю в ассемблере AVR нет таких операторов "<<" и "|" там они пишутся по другому и компилятор эти начертания по логике не должен понять (или я не прав??)
ассемблер состоит из двух частей: мнемокодов команд и операций ассемблера (терминология моя). мнемокод - это символьный аналог команды ALU, например, mov, ldi или rol. разумеется, последний мнемокод означает "сдвиг влево", т.к. вроде бы является аналогом оператора Си <<, и это на самом деле так. но есть еще операция языка ассемблера <<, которая означает ровно то же самое, но выполняется ассемблером на этапе компиляции. то есть не ALU микроконтроллера делает этот сдвиг, а сам ассемблер все двигает, подставляя в команду уже готовый результат этих сдвигов.
улавливаете разницу?

rol r3, 4 в этом случае полностью эквивалентно rol r3, 1<<2, т.к. 1<<2 это и будет 4. таким образом, во время написания программы вы пользуетесь удобными вам константами, компилятор ассемблера делает необходимые вычисления сам, и подставляет в мнемокоды уже готовые числа.

итак, разница в операторе << языка Си и ассемблера в том, что в Си этот оператор может выполняться либо на этапе компиляции (макросы), либо на этапе исполненияя программы, а в ассемблере этот оператор всегда выполняется на этапе компиляции. и, естественно, оба операнда этого оператора должны быть константами, иначе компилятор не сможет выполнить эту работу - попробуйте написать что-то типа ldi r17, 1<<r6 - получите ошибку компиляции.


Насколько я знаю в ассемблере есть два вида команд.
1 Как выше указал "ARV" мнемокод. Мнемокод по терминологии называется оператором
2 Второй вид команд это "дерективы". как выше указал ARV "дерективы" выполняются компилятором (как в языках программирования высокого уровня тот же "СИ") , примеры приводить не буду "COKPOWEHEU" привел хороший пример

но я такой команды "дерективы" как << в AVR не видел
Если я не прав пожалуйста растолкуйте :shock:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Чт авг 31, 2017 17:45:09

sibiryak69 писал(а):но я такой команды "дерективы" как << в AVR не видел
теперь видели. еще и >> есть тоже. читайте документацию на avrassembler2

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Чт авг 31, 2017 20:18:13

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


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


Ну вот, высказался. Вроде легче стало :)

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пт сен 01, 2017 07:04:03

Всё просто. Например, для ATtiny2313 (для номеров битов смотрим либо даташит, либо соответствующий инклюд:
Код:
ldi r16, (1<<USIWMO)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)
ldi r16, 0b00011011
Все записи полностью идентичны, но первая гораздо понятнее, чем "магическое" число в последней.
не совсем понятно для чего в выше приведенном выражении использовать название разрядов регистра управления и что под этими названиями в данном случае подразумевается или номер разряда или содержимое разряда. Если номер разряда, то смысл в написании названия пропадает, и для меня более понятной будет последняя запись (все как говорится на месте, в регистр записывается конкретная константа) Если под названием разряда подразумевается его содержимое то это уже не константа.

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

Последний вариант - магическое число, непонятно откуда взявшееся в программе. Понять, почему использовано именно это число невозможно, не заглядывая дальше по коду. Нужно обязательно смотреть, в какой регистр этот r16 будет записан и лезть в даташит смотреть биты этого регистра.

Если же писать по первому варианту, то с первого взгляда на имена битов становится понятно, что они относятся к одному из регистров USI.

Далее, при переносе кода на другой МК все эти магические числа испортят немало нервных клеток, так как нет гарантии, что в новом МК эти биты не поменяли свою позицию в регистре. А если использовать имена - эта проблема практически исчезает.

Микроконтроллеру всё равно - в обоих случаях в регистр записывается конкретная константа и бинарный код будет одинаков. Другое дело, что в первом случае эту константу вычисляет препроцессор/компилятор, а не сам программист.

Jetetex писал(а):Возникла у меня недавно необходимость деления целых чисел
Судя по коду, Вы реализовывали деление любого числа на любое число, поэтому получилось что-то довольно громоздкое.

Часто возникает необходимость деления на некоторую константу. Обычно это 10 (развёртка числа в строку для индикации). В таком случае (делитель - константа) удобен следующий принцип.

Скажем, нужно быстро разделить некоторое 8-битное (0..255) число на 10. Как правило, обычные алгоритмы сначала выясняют, что число больше 100 но меньше тысячи, вычитают (дважды) сотню - получают число 2, затем пять раз вычитают 10 (5) и остаётся ещё 5 единиц. Довольно долго.

Есть немного другой подход. Разделить на 10 - это то же самое, что и 1) умножить на x и 2) разделить на 10x. Умножать многие МК умеют аппаратно (да и программно это легче чем делить), а вот второй пункт можно обойти хитростью - сделать так, чтобы 10x было близко (чуть больше) к некоторой степени двойки. Для константы 10 наиболее удобно число 2050 (чуть больше 2048). Получаем:

N / 10 = N * 205 / 2050 ~= N * 205 / 2048 = (N * 205) >> 11;

Да, при делении на 2050 получится число немного меньшее, чем при делении на 2048, но для однобайтных чисел от 0 до 255 результат (за счёт отбрасывания при целочисленном делении) будет одинаковый.

А умножить байт на 205, а потом сдвинуть вправо на 11 - это гораздо быстрее ряда вычитаний, да и выполняется это за константное время.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пт сен 01, 2017 08:22:47

По мне, проще как здесь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пт сен 01, 2017 18:11:23

Если правильно понял два последних алгоритма, то в них пренебрегаем остатком после деления, принимая во внимание только целую часть (может конечно и ошибаюсь). В некоторых случаях это критично. К примеру в моем случае нужно сначала 1440 (2 рег) / 24 получаем на выходе 2 рег ответа (целое и остаток), после этого каждый из них разделить на 10 (привести в знаки индикатора). То есть остаток имеет довольно важное значение.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сб сен 02, 2017 07:39:46

Ну, так никто не мешает после получения результата (целого частного) быстро вычислить и остаток.
N / 24 = X, в остатке Y. В вашем случае Вы путём долгих вычислений получаете сразу оба числа. Но ведь если X получен быстрым способом, то уже не проблема так же быстро получить: Y = N - 24*X;

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вс сен 03, 2017 15:57:29

WiseLord спасибо за объяснение. Если я правильно понял, данный вид записи (ldi r16, (1<<USIWMO)|(1<<USICS1)|(1<<USICLK)|(1<<USITC)) универсален тем, что в разных МК биты с одним названием могут находиться в разных разрядах, и при переносе с одного МК на другой, компилятор сам вычислит число необходимое для выставления нужных разрядов, а программисту не надо парится :))

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вс сен 03, 2017 16:00:54

Не вычислит, а согласно заголовочному файлу соответствующего МК.

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Вс сен 03, 2017 20:42:58

Важнее другое. При взгляде на такую запись сразу понятно что хотел сделать программист.
Сравните эти две записи: какую проще понять?
Код:
ldi temp, (1<<OCIE1A)
out TIMSK, temp

Код:
ldi r16, 16
out 0x39, r16

"Любой дурак может написать программу, понятную машине. Настоящие программисты пишут программы, понятные людям" (с) Мартин Фаулер

Пн сен 11, 2017 13:59:12

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

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Пн сен 11, 2017 16:03:53

В обработчике запустили таймер или сделали отсечку уже запущенного таймера. Ждете отпускания кнопки и в обработчике сделали следующую отсечку. Разница покажет длительность нажатия на кнопку.

Re:

Пн сен 11, 2017 16:08:26

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

1 - Подключение кнопок к внешнему прерыванию требуется только в единственном случае - если устройству требуется энергосбережение.
2 - Кнопки - человеко-интерфейс. Это значит, что вам не нужна реакция в нано, микро и даже миллисекунды.
3 - У кнопок есть дребезг контактов (спросить у гугла).

Есть цикл статей Татарчевского. Там отлично расписано, как сделать опрос кнопок. Пусть си вас не смущает. Главное понять алгоритм.

Добавлено after 1 minute 19 seconds:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
В обработчике запустили таймер или сделали отсечку уже запущенного таймера. Ждете отпускания кнопки и в обработчике сделали следующую отсечку. Разница покажет длительность нажатия на кнопку.

Пусть он сразу ознакомится, что такое программные таймеры. И автоматное программирование.

Re:

Вт сен 12, 2017 08:31:00

Зачем уводить от конкретно заданного вопроса
... как с помощью внешнего прерывания улавливать длинное и короткое нажатие на кнопку?

может radio-fan вырос из программных таймеров и переходит на более высокий уровень, задействуя аппаратную периферию и прерывания от оной для опроса кнопок в фоновом режиме.
Ответить