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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Necroteeth
Потрогал лапой паяльник
Сообщения: 362
Зарегистрирован: Вс окт 10, 2010 17:43:48
Откуда: Воронеж

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

Сообщение Necroteeth »

хм... завтра поэкспериметирую. спасибо за наводку!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

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

Именно делается. Только делает её компилятор.
Путь BITNAME0 = 3, BITNAME1 = 5. Тогда (1<<3) даст нам число 0b00001000, а (1<<5) даст 0b00100000. Делаем побитовое ИЛИ (символ "|") и получаем 0b00101000. И это число тупо загоняем в регистр, через ldi, при этом перетерев всё, что там было.

Тогда по идее правильно так:
in temp,TIMSK
ori temp,(1<<TOIE1)|(1<<TOIE0)
out TIMSK,temp

А с нулём мне всё равно не понятно...
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

ploop писал(а):А как тогда сбросить эти биты (я имею ввиду так же наглядно)

Код: Выделить всё

cbr temp,(1<<BIT1)|(1<<BIT2)
или

Код: Выделить всё

andi temp,~((1<<BIT1)|(1<<BIT2))
Ставим плюсы: )
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

ploop писал(а):
Тогда по идее правильно так:
in temp,TIMSK
ori temp,(1<<TOIE1)|(1<<TOIE0)
out TIMSK,temp

А с нулём мне всё равно не понятно...

У меня прекрасно всё работает с такой записью, как я указывал в примере выше.
В вашем примере процесс сдвига делается в МК и является лишним. А в моём примере всё просчитывает компилятор и вставляет вместо записи уже готовое число. В АСМе так указывают имена битов, в которые нужно положить нули или единицы, в зависимости от того, что укажут. (1<<BITNAME) или (0<<BITNAME) И никакого сдвига не происходит, если оно применяется совместно с LDI
Кстати, такие записи применимы и для массивов. Даже в сегменте EEPROM.

Код: Выделить всё

.eseg
.db (1<<1)|(1<<3), (1<<0)|(1<<2)

В итоге у меня родился *.eep файл с байтами 0x0A и 0x05 :)
Последний раз редактировалось DX168B Ср янв 26, 2011 23:02:07, всего редактировалось 1 раз.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

У меня прекрасно всё работает с такой записью, как я указывал в примере выше.

Угу. При инициализации. Когда там и так стандартные режимы - всё в нуле.

В вашем примере процесс сдвига делается в МК и является лишним.

И где же вы это увидели??? (1<<TOIE1)|(1<<TOIE0) - КОНСТАНТА, вычисляемая компилятором.
А на счет (0<<BITNAME) ща проверю. Не верится мне, что эта конструкция будет работать...

ibiza11 писал(а):
ploop писал(а):А как тогда сбросить эти биты (я имею ввиду так же наглядно)

Код: Выделить всё

cbr temp,(1<<BIT1)|(1<<BIT2)
или

Код: Выделить всё

andi temp,~((1<<BIT1)|(1<<BIT2))

ВОТ! Вторая строка - то, что меня интересовало! Спасибо.
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

ploop писал(а):И где же вы это увидели??? (1<<TOIE1)|(1<<TOIE0) - КОНСТАНТА, вычисляемая компилятором.

Вот:
ploop писал(а):ori temp,(1<<TOIE1)|(1<<TOIE0)

Зачем, спрашивается?
BITNAME - это я образно. :)
И запись (0<<BITNAME) работает. Я лично сам проверял. :)
Кстати, такие записи применимы и для массивов. Даже в сегменте EEPROM.

Код: Выделить всё

.eseg
.db (1<<1)|(1<<3), (1<<0)|(1<<2)

В итоге у меня родился *.eep файл с байтами 0x0A и 0x05 :)
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

И запись (0<<BITNAME) работает. Я лично сам проверял.

Угу. Ничего не делает в сочетании с (1<<BITNAME). Я проверил. :)
Если в регистре было 0b1111111 то (1<<3) даст 0b00001000, соответственно (0<<5)||(1<<3) даст тоже 0b00001000 :)
Просто (0<<BITNAME) возвращает 0
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

Но не выставляет же его в единицу и компилятор не ругается и в месте этого бита ставится 0. В этом случае, если попытаться изменить 1 бит, то меняется всё число. Вы правы. Но я такое применяю при вылизывании программы, чтобы типа отключить запись в скобках, чтобы не мешала на время. Для этого я просто меняю 1 на 0. Если мне надо будет опять изменить строчку, то снова заменю, если надо будет. В конце отладки уже стираю все записи в виде (0<<BIT), чтобы привести код в нормальный вид.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Короче разобрался. Это всё-таки простой битовый сдвиг, а ноль куда ни сдвигай - будет ноль. Этот приём просто позволяет использовать имена битов, вместо номеров, для формирования маски.
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

Ну да. И я про это-же. Только процесс сдвига производит компилятор и результат кидает в HEX файл в виде готового числа. Таким макаром формируют либо маску, либо байт. Короче, так компилятору указывают, какие биты должны быть единицами в байте либо маске или в константе.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
Necroteeth
Потрогал лапой паяльник
Сообщения: 362
Зарегистрирован: Вс окт 10, 2010 17:43:48
Откуда: Воронеж

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

Сообщение Necroteeth »

DX168B писал(а):В этом случае, если попытаться изменить 1 бит, то меняется всё число. Вы правы.

у меня в общем-то в том и была суть вопроса, который я задавал выше - если в регистре было, например, 0b00010101, но я где-то в листинге проимел это место и просто хочу включить еще один бит, НЕ ТРОГАЯ другие и при этом не ища, какие на данный момент биты в точности выставлены. в общем, можно ли одной командой 0b00010101 превратить в 0b10010101?
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

Necroteeth писал(а): в общем, можно ли одной командой 0b00010101 превратить в 0b10010101

Да, если Ваш МК поддерживает команды sbr и cbr
Например у вас в r16 есть значение 0b00010101 и Вам его надо превратить в 0b10010101
Для этого это делается так:

Код: Выделить всё

sbr r16, 7 ;Устанавливаем 7й бит в единицу.
cbr r16, 7 ;Сбросим 7й бит в ноль.

Если у Вас значение в регистре ввода\вывода (порт), то так:

Код: Выделить всё

sbi PORTD, PD7 ;Установим единицу на ноге PD7
cbi PORTD, PD7 ;Сбросим ногу PD7 в ноль

Если у Вас значение в каком-то из прочих регистров, например в каком-то из регистров таймера, то Вам надо сначала считать его содержимое в один из свободных регистров РОН, потом изменить его, как в первом примере и отправить назад. Изменится только тот бит в регистре, который Вы изменили.

Код: Выделить всё

in r16, TIMSK ;Считаем содержимое изменяемого регистра.
sbr r16, 7 ;Устанавливаем 7й бит в единицу.
out TIMSK, r16 ;Вернём изменённый байт обратно.

Всё дело в том, что перечисленные выше команды не работают для некоторых регистров специального назначения. И по этому делать приходится так.
Так как большинство команд у нас выполняется за 1 такт, а тактовая у нас бывает и 8МГц, то эти операции будут просто незаметными. При 8 МГц микроконтроллер успеет выполнить до 8 миллионов команд. Но может и немного меньше, потому, что некоторые команды выполняются и за 2, 3, 4 и т.д. такта.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Для наглядности можно использовать битовые маски напрямую. К примеру, такая запись установит третий бит в "1" не тронув остальные:
in temp,REG
ori temp, 0b00001000
out REG,temp

А эта сбросит третий бит:
in temp,REG
andi temp, 0b11110111
out REG,temp
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

Эти варианты тоже годятся, в случае, если МК не поддерживает команды sbr и cbr
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

DX168B, ОЧЕНЬ РАСПРОСТРАНЕННАЯ ОШИБКА:

Код: Выделить всё

sbr r16, 7 ;Устанавливаем 7й бит в единицу.
cbr r16, 7 ;Сбросим 7й бит в ноль.

Тут дело в том, что команды cbr и sbr практически аналогичны командам andi и ori и для них также нужно использовать
маску. сами проверьте результат в эти примерах:

Код: Выделить всё

clr tmp
sbr tmp,7

clr tmp
sbr tmp,(1<<7)

в каком из этих случаев ДЕЙСТВИТЕЛЬНО УСТАНОВИТСЯ 7ой БИТ?

PS я из-за этоих команд словил нефиговый баг, при этом девайс чуть не сгорел.
Ставим плюсы: )
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Тут дело в том, что команды cbr и sbr практически аналогичны командам andi и ori и для них также нужно использовать
маску.

Именно. Поэтому я пользуюсь только командами установки битов в IO-порты: sbi, cli. В остальных случаях применяю маску.
А cbr и sbr, если не ошибаюсь, даже код одинаковый имеют с ori, andi.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

ploop писал(а):А cbr и sbr, если не ошибаюсь, даже код одинаковый имеют с ori, andi.

Да, так и есть. Хорошо, что я ими не пользовался :)))
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Кстати, в даташите на мегу 48 я таковых не обнаружил. Ну оно и к лучшему :)
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

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

Сообщение DX168B »

И ATTINY26 их вообще не поддерживает. Я с этими командами никогда не работал, но знаю, что они есть. Разве, что в протеусе на 2313м испытывал. Интересно, а в чём баг, если у них коды одинаковые? К стати, я в своих программах даже масками редко пользуюсь. Ноги проверяю с помощью sbis и sbic, дёргаю ногами с помощью sbi и cbi. Если мне надо в регистре добавить единицы, то строго add и если сбросить несколько битов в нули, то sub. Маски применяю только совместно с andi при чтении с порта, чтобы лишнее отбросить. Но раз эти команды вызывают баги, то намотаю себе на ус. :)

Код: Выделить всё

ldi r16, 0b11111111
sub r16, 0b00001001 ;Вычтем из r16 это число
; В r16 останется 0b11110110
add r16, 0b00001001 ;Теперь добавим это же число
; В r16 получится 0b11111111

Арифметика бинарных чисел. :)
Последний раз редактировалось DX168B Чт янв 27, 2011 11:18:27, всего редактировалось 1 раз.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
ploop
Модератор
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

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

Сообщение ploop »

Интересно, а в чём баг, если у них коды одинаковые?

Баг??? Так это фича! Или маркетинговый ход Атмела.
По секрету - реально команд (по кодам) чуть ли не в полтора раза меньше, чем их мнемоник. Какие-то действительно удобней использовать в зависимости от ситуации, какие-то просто путают (как эта cbr-sbr)
Ответить

Вернуться в «AVR»