Ассемблер (ASM) для AVR в вопросах и ответах
- Necroteeth
- Потрогал лапой паяльник
- Сообщения: 362
- Зарегистрирован: Вс окт 10, 2010 17:43:48
- Откуда: Воронеж
Re: Ассемблер (ASM) для AVR в вопросах и ответах
хм... завтра поэкспериметирую. спасибо за наводку!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
По сути, при такой записи не делается никакого сдвига так как такая запись выполняется за 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 в вопросах и ответах
ploop писал(а):А как тогда сбросить эти биты (я имею ввиду так же наглядно)
Код: Выделить всё
cbr temp,(1<<BIT1)|(1<<BIT2)Код: Выделить всё
andi temp,~((1<<BIT1)|(1<<BIT2))Ставим плюсы: )
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
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!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
У меня прекрасно всё работает с такой записью, как я указывал в примере выше.
Угу. При инициализации. Когда там и так стандартные режимы - всё в нуле.
В вашем примере процесс сдвига делается в МК и является лишним.
И где же вы это увидели??? (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 в вопросах и ответах
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!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
И запись (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 в вопросах и ответах
Но не выставляет же его в единицу и компилятор не ругается и в месте этого бита ставится 0. В этом случае, если попытаться изменить 1 бит, то меняется всё число. Вы правы. Но я такое применяю при вылизывании программы, чтобы типа отключить запись в скобках, чтобы не мешала на время. Для этого я просто меняю 1 на 0. Если мне надо будет опять изменить строчку, то снова заменю, если надо будет. В конце отладки уже стираю все записи в виде (0<<BIT), чтобы привести код в нормальный вид.
I am DX168B and this is my favourite forum on internet!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Короче разобрался. Это всё-таки простой битовый сдвиг, а ноль куда ни сдвигай - будет ноль. Этот приём просто позволяет использовать имена битов, вместо номеров, для формирования маски.
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ну да. И я про это-же. Только процесс сдвига производит компилятор и результат кидает в HEX файл в виде готового числа. Таким макаром формируют либо маску, либо байт. Короче, так компилятору указывают, какие биты должны быть единицами в байте либо маске или в константе.
I am DX168B and this is my favourite forum on internet!
- Necroteeth
- Потрогал лапой паяльник
- Сообщения: 362
- Зарегистрирован: Вс окт 10, 2010 17:43:48
- Откуда: Воронеж
Re: Ассемблер (ASM) для AVR в вопросах и ответах
DX168B писал(а):В этом случае, если попытаться изменить 1 бит, то меняется всё число. Вы правы.
у меня в общем-то в том и была суть вопроса, который я задавал выше - если в регистре было, например, 0b00010101, но я где-то в листинге проимел это место и просто хочу включить еще один бит, НЕ ТРОГАЯ другие и при этом не ища, какие на данный момент биты в точности выставлены. в общем, можно ли одной командой 0b00010101 превратить в 0b10010101?
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
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!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Для наглядности можно использовать битовые маски напрямую. К примеру, такая запись установит третий бит в "1" не тронув остальные:
in temp,REG
ori temp, 0b00001000
out REG,temp
А эта сбросит третий бит:
in temp,REG
andi temp, 0b11110111
out REG,temp
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 в вопросах и ответах
Эти варианты тоже годятся, в случае, если МК не поддерживает команды sbr и cbr
I am DX168B and this is my favourite forum on internet!
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
DX168B, ОЧЕНЬ РАСПРОСТРАНЕННАЯ ОШИБКА:
Тут дело в том, что команды cbr и sbr практически аналогичны командам andi и ori и для них также нужно использовать
маску. сами проверьте результат в эти примерах:
в каком из этих случаев ДЕЙСТВИТЕЛЬНО УСТАНОВИТСЯ 7ой БИТ?
PS я из-за этоих команд словил нефиговый баг, при этом девайс чуть не сгорел.
Код: Выделить всё
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 я из-за этоих команд словил нефиговый баг, при этом девайс чуть не сгорел.
Ставим плюсы: )
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Тут дело в том, что команды cbr и sbr практически аналогичны командам andi и ori и для них также нужно использовать
маску.
Именно. Поэтому я пользуюсь только командами установки битов в IO-порты: sbi, cli. В остальных случаях применяю маску.
А cbr и sbr, если не ошибаюсь, даже код одинаковый имеют с ori, andi.
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
ploop писал(а):А cbr и sbr, если не ошибаюсь, даже код одинаковый имеют с ori, andi.
Да, так и есть. Хорошо, что я ими не пользовался
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Кстати, в даташите на мегу 48 я таковых не обнаружил. Ну оно и к лучшему 
- DX168B
- Друг Кота
- Сообщения: 4468
- Зарегистрирован: Вс янв 24, 2010 19:19:52
- Откуда: Главный Улей России (Moscow)
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
И 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!
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Интересно, а в чём баг, если у них коды одинаковые?
Баг??? Так это фича! Или маркетинговый ход Атмела.
По секрету - реально команд (по кодам) чуть ли не в полтора раза меньше, чем их мнемоник. Какие-то действительно удобней использовать в зависимости от ситуации, какие-то просто путают (как эта cbr-sbr)