Ассемблер (ASM) для AVR в вопросах и ответах
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
В результате выполнения команды, содержимое не изменится. Только установятся флаги.
А в том первоначальном вариенте декремента, с проверкой на минус R1 будет декрементирован и при R0 = -1 и при -2... если его не "обнулить" то максимум за 256 тактов R1 в любом случае досчитает до нуля. получится фигня...
В конечном варианте, все пучком.
А в том первоначальном вариенте декремента, с проверкой на минус R1 будет декрементирован и при R0 = -1 и при -2... если его не "обнулить" то максимум за 256 тактов R1 в любом случае досчитает до нуля. получится фигня...
В конечном варианте, все пучком.
- Реклама
- afz
- Опытный кот
- Сообщения: 744
- Зарегистрирован: Сб дек 22, 2012 08:17:42
- Откуда: Караганда, Казахстан
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Alexeyslav писал(а):В результате выполнения команды, содержимое не изменится. Только установятся флаги.
А в том первоначальном вариенте декремента, с проверкой на минус R1 будет декрементирован и при R0 = -1 и при -2... если его не "обнулить" то максимум за 256 тактов R1 в любом случае досчитает до нуля. получится фигня...
В конечном варианте, все пучком.
Угу. Итого.
Код: Выделить всё
or r0,r0
brne 1$
dec r1
1$:dec r0
or r0,r1
breq SecOK ; секунда кончилась
Вывод: не высыпаться - вредно.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
-
Alexeyslav
- Друг Кота
- Сообщения: 4550
- Зарегистрирован: Чт май 05, 2011 21:26:34
- Откуда: Украина, Славутич
- Контактная информация:
Re: Ассемблер (ASM) для AVR в вопросах и ответах
У тебя в конце первой же итерации содержимое R0 разрушается, для сравнения с нулем надо какой-то другой регистр использовать чтобы R0 не запортить. Иначе 100% шансов получить бесконечный цикл или очень короткий.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
afz писал(а):aklА теперь, пожалуйста, то же самое для (R0, R1).
X-Y-Z заняты. И R24-R25 трогать нельзя. То есть, конечно, можно сохранить их, а потом восстановить, но меня интересует именно прямой вариант вычислений в (R0, R1)...
У меня получилось как то так. Длинновато, зато работает во всем диапазоне 0...65535. Формат R0:R1 (старший: младший)
Спойлер
Код: Выделить всё
TEST_R0_R1:
LDI XH,HIGH(65535) ; для проверки
LDI XL,LOW(65535) ; для проверки
; LDI XH,HIGH(0) ; для проверки
; LDI XL,LOW(0) ; для проверки
; LDI XH,HIGH(2304) ; для проверки когда младший байт =0
; LDI XL,LOW(2304) ; для проверки когда младший байт =0
STS $60,XH
STS $61,XL
GO_TEST:
LDS R0,$60 ; для проверки
LDS R1,$61 ; для проверки
LDS XH,$60 ; для проверки
LDS XL,$61 ; для проверки
;*************************************************
CLR R3
TEST10:
SBIW XL,1 ; для проверки
CPSE R1,R3
RJMP TEST2
CPSE R0,R3
RJMP TEST0
RJMP OUT
TEST0:
DEC R0
TEST2:
DEC R1
RJMP TEST10
OUT:
RJMP GO_TEST- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: Ассемблер (ASM) для AVR в вопросах и ответах
afz писал(а):А как принято делать двухбайтовые счетчики? Вот мне понадобилось в таймерном прерывании 2400 Гц отсчитать секунду. Я, как на нормальных системах, загрузил в пару регистров 2400 (hi , low), но что-то мне подсказало заглянуть в описание команды DEC. Ага, так и ждал подляны: DEC не взводит бит C. Ну и как прикажете считать? Нет, конечно, мне не составило труда посчитать в одном регистре 100 и во втором 24, но это удобный частный случай, а понадобись посчитать простое число, не влезающее в один регистр, хотя бы 2437 и как тогда принято делать?
Тогда принято первый младший брать с остатком, а старший так и останется, в вашем случае превый младший брать 137, старший 24, остальные младшие грузить по 100, итого 137*1+100*23=2437
- Реклама
Re: Ассемблер (ASM) для AVR в вопросах и ответах
На DEC свет клином не сошелся, команда SUBI Rx,1 делает все то же самое, но при этом изменяет бит С.
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Совершенно верно, но эти команды (SUBI, SBCI) работают только со старшей частью регистрового файла, а afz загнал себя в угол
По мне, налицо, неправильное распределение вычислительных возможностей и мощности регистрового файла AVR, приводящее к таким заявлениям
и оставил себе толькоafz писал(а):X-Y-Z заняты. И R24-R25 трогать нельзя...
afz писал(а):вариант вычислений в (R0, R1).
По мне, налицо, неправильное распределение вычислительных возможностей и мощности регистрового файла AVR, приводящее к таким заявлениям
afz писал(а):Блин, ну до чего корявая и дилетантская система команд. 32 общих регистра, да. Нагло врут! ОБЩИХ (действительно общих) регистров всего 6 - R26-R31. Почти общих - еще 2: добавляются R24, R25, с остальными не работают команды ADIW/SBIW. Более-менее общих - еще 8: R16-R23. С остальными R0-R15 не работает половина команд. Бить лицо. Ногами.
- afz
- Опытный кот
- Сообщения: 744
- Зарегистрирован: Сб дек 22, 2012 08:17:42
- Откуда: Караганда, Казахстан
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Alexeyslav писал(а):У тебя в конце первой же итерации содержимое R0 разрушается, для сравнения с нулем надо какой-то другой регистр использовать чтобы R0 не запортить. Иначе 100% шансов получить бесконечный цикл или очень короткий.
Угу. Я же говорю, не высыпаться вредно. Но смысл ясен.
akl
Не то, чтобы я загнал себя в угол - у меня изначально была частота прерываний 150 Гц, я спокойно считал секунду в R15 и не жужжал. Позже, в попытке приспособить этот же проект для чуть-чуть другой задачи, пришлось поднять частоту прерываний. Для счета секунды я, по-простому, взял второй регистр - R11, посмотрел, что для прямого счета арифметика оказывается какой-то непонятной, сделал в R15 счетчик до 24, а в R11 - до 100, а для прояснения вопроса с арифметикой задал вопрос здесь.
Тема прояснена полностью. Выводы:
- для регистров первой половины регистрового файла не существует решения, использующего менее трех регистров;
- на будущее подобный счетчик следует располагать в R24:R25 или в неиспользуемой паре X-Y-Z;
- ну и на хрена эти R0-R15, если в них ничего хорошего не сделаешь? И кто посмел сказать что они общие?
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Re: Ассемблер (ASM) для AVR в вопросах и ответах
А чем предложенное мной и Alexeyslav-ом не подходит? 
Без дополнительных регистров и не длинно.
R1:R0 - старший:младший
Без дополнительных регистров и не длинно.
R1:R0 - старший:младший
Код: Выделить всё
tst r0
brne L1
dec r1
L1:
dec r0
brne notZero
cpi r1,0
brne notZero
Zero:
notZero:
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
- afz
- Опытный кот
- Сообщения: 744
- Зарегистрирован: Сб дек 22, 2012 08:17:42
- Откуда: Караганда, Казахстан
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Да все нормально, не считая того, что вместо CPI r1,0 надо писать tst r1. Но, по-любому 7 команд вместо одной sbwi r24,1 - это наглядная демонстрация корявости системы команд. Вот у Системы-360 действительно 16 общих регистров. Или у PDP-11 - 7 общих регистров. Из контроллеров - у MSP-430 тоже общие регистры, точное число не помню, 13 кажется. Но 430-й с самого начала проектировался с оглядкой на PDP-11. А у AVR - пшик, а не общие регистры. Или взять команды SBI/CBI. Готовлю к работе таймер 0, взвести бит TOIE0 в порту TIMSK - сам Бог велел использовать команду SBI. Ага, щаззз! Operand 1 out of range. Оказывается, TIMSK Оказывается, адрес TIMSK больше, чем 0x1F. Регистр, состоящий из отдельных битов, которыми надо управлять по-отдельности, расположен в недоступной для SBI/CBI зоне. Это хорошая система команд, да?
Я бы, при проектировании такого процессора плюнул на байтовую организацию программной памяти и сделал командное слово шириной битов 20, и все бы сошлось - для Гарвардской архитектуры это вполне допустимо, память данных байтовая, а как там выглядит командное слово - дело 25-е.
Я бы, при проектировании такого процессора плюнул на байтовую организацию программной памяти и сделал командное слово шириной битов 20, и все бы сошлось - для Гарвардской архитектуры это вполне допустимо, память данных байтовая, а как там выглядит командное слово - дело 25-е.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Только tst r1 (r0 уже проверен, после dec r0)
В данном случае (проверка на равенство нулю) никакой разницы:
cpi r1,0
tst r1
or r1,r1
and r1,r1
Более того, tst и and, в данном случае, будут иметь одинаковый машинный код.
В данном случае (проверка на равенство нулю) никакой разницы:
cpi r1,0
tst r1
or r1,r1
and r1,r1
Более того, tst и and, в данном случае, будут иметь одинаковый машинный код.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Kavka писал(а):Gudd-Head, то что в ОЗУ получилось это то что ты хотел? Или я неправильно понял постановку задачи?
Похоже да. Фантастика
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Ага. Свойство такое у двоичного представления получается. Вот, как-то так.
Спойлер
Код: Выделить всё
mask[]={0b11111111,0b11111110,0b11111100,0b11111000,0b11110000,0b11100000,0b11000000,0b10000000};
F = ( (x & mask[pos]) << 1 ) | (x & ~mask[pos])
L = (x & mask[pos]) << 1 )
R = (x & ~mask[pos])
F = L | R
XM = x & mask[pos], тогда L = XM << 1 = XM * 2 = XM + XM
очевидно, что XM | R = XM + R = x
Соберая всё. Получаем: F = L + R = XM + XM + R = XM + x = (x & mask[pos]) + x
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Re: Ассемблер (ASM) для AVR в вопросах и ответах
akl писал(а):Совершенно верно, но эти команды (SUBI, SBCI) работают только со старшей частью регистрового файла
Совершенно верно, но если , к примеру, SBIW работает только с одной из четырех регистровых пар, то SUBI, SBCI - с любыми 16 старшими регистрами, причем не обязательно рядом расположенными, и если грамотно распорядиться ресурсами, не придется выдумывать сложные извраты с длинными числами. Создаем себе проблему, а потом ее героически борем -- это так по-нашему.
- Engineer_Keen
- Друг Кота
- Сообщения: 3871
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Jack_A писал(а):Создаем себе проблему, а потом ее героически борем -- это так по-нашему.
Дело опыта. Я когда с mcs51 перелезал по началу ругался на систему команд авр (нельзя напрямую отдельные биты копировать, для разных типов памяти разные команды, нельзя за одну команду сравнить и сделать переход и т.д.), а потом как разобрался, обратно не хочется возвращаться, хотя по работе иногда нужно
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Gudd-Head писал(а):Похоже да. ФантастикаДаже не жо конца догоняю как это работает. Сдвигается через удвоение посредством сложения с частью исходного байта?
...нда, кодик выглядит симпотно и даже ПОЧТИ рабочий
- Gudd-Head
- Друг Кота
- Сообщения: 20092
- Зарегистрирован: Чт сен 18, 2008 12:27:21
- Откуда: Столица Мира Санкт-Петербург
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Прогнал.

В первом байте ноль вставлен в конец, 1110111 (0х77) сдвинулось влево и получилось 0b11101110.
Во втором байте ноль влез во второй бит, получилось 0b11101101.
....
под конец получили исходное 0b01110111. Видно как нолик двигается справа налево:
0b11101110 EE
0b11101101 ED
0b11101011 EB
0b11100111 E7
0b11100111 E7
0b11010111 D7
0b10110111 B7
0b01110111 77
Думаю, если заполнять маску наоборот единицами, то получим нужный порядок. Но можно и этим обойтись.
В первом байте ноль вставлен в конец, 1110111 (0х77) сдвинулось влево и получилось 0b11101110.
Во втором байте ноль влез во второй бит, получилось 0b11101101.
....
под конец получили исходное 0b01110111. Видно как нолик двигается справа налево:
0b11101110 EE
0b11101101 ED
0b11101011 EB
0b11100111 E7
0b11100111 E7
0b11010111 D7
0b10110111 B7
0b01110111 77
Думаю, если заполнять маску наоборот единицами, то получим нужный порядок. Но можно и этим обойтись.
- Вложения
-
- Безымянный.GIF
- (1.88 КБ) 532 скачивания
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Re: Ассемблер (ASM) для AVR в вопросах и ответах
...вообщет да, всё похоже очень даже не плохо ..по ходу я стормозил
респект Kavka
респект Kavka

Re: Ассемблер (ASM) для AVR в вопросах и ответах
Я тоже об этом думал. Добавили бы пару битов - и система команд сразу стала бы приятнее. Но мне-то приходилось программировать и i8048, а после этого АВР - сказка. Еще, может, они думали, что все на Си будут писать, а уж компилятор со всем разберется.afz писал(а):Я бы, при проектировании такого процессора плюнул на байтовую организацию программной памяти и сделал командное слово шириной битов 20
Re: Ассемблер (ASM) для AVR в вопросах и ответах
Если ещё остались не "въехавшие"
- проверьте перебором.
Не забываем ставить плюсы.
Спойлер
Код: Выделить всё
#include <stdio.h>
unsigned char mask[]={0b11111111,0b11111110,0b11111100,0b11111000,0b11110000,0b11100000,0b11000000,0b10000000};
// вариант с двумя масками (прямой и инверсной)
unsigned char izb(unsigned char x,unsigned char pos) {
return ( ( (x & mask[pos]) << 1 ) | (x & ~mask[pos]) );
}
// вариант со сложением
unsigned char izb2(unsigned char x,unsigned char pos) {
return ( x + (x & mask[pos]) );
}
void main() {
int i,j;
unsigned char t1,t2;
for (i=0; i<256; i++) {
for (j=0; j<8; j++) {
t1 = izb(i,j);
t2 = izb2(i,j);
if ( t1 != t2 ) {
printf("Error\n");
}
}
}
}
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)


