ReAl 0 30 апреля, 2008 Опубликовано 30 апреля, 2008 · Жалоба А что вас так смущает деление на 10? В пределах байта это 4 сдвига и 4 сложения Равно как и умножение Ну, тут плавно перешли к полуоффтопикув виде сравнения преобразования 16-битного числа в avr204.asm и на сайте atmel.ru. Там "деление" на 10 несколько подлиннее будет. Хотя с учётом наличия команд умножения у мег и для 16 бит "деление" на 10 по скорости гораздо выгоднее, чем avr204.asm, а в одном из вариантов выгоднее и чем вычитания, но длиннее по коду. Ну а avr204.asm для 16 бит соревнуется по тормознутости с именно делением на число, в качестве которого в процедуру передаётся 10. Кстати, для вывода как правило удобнее иметь сразу распакованный BCD или ASCII, это тоже можно сделать вычитаниями, там получается приблизительно те же числа (26 слов, от 32 до 183 циклов в зависимости от числа, исходник, кажется, от =AVR=, пробегал по форуму на телесисемамах лет 5 назад). Если слегка модифицировать алгоритм - убрать восстановление остатка после циклов вычитаний и циклы через один сделать циклами сложения, то это будет ещё короче при приблизительно тех же временах, только минимум будет не для 0, а для 9090..9099, а максимум не для 59999, а для 60900..60909. ;Converts unsigned integer value of bin_h:bin_l to ASCII or unpacked BCD ;Only upper registers can be used, bin_h/asc4 and bin_l/asc5 ;variable pairs must share common register each. ;21 words, max/min cycles with rcall/ret: 183(60900..60909)/27(9090..9099) ;No other registers used;) ; ascii/unpacked BCD in "reversed" order - leftmost digit stored in r20, rightmost one - in r16 ; use for BIN to ASCII .set ZERO='0' .set NINE='9' ; use for BIN to unpacked BCD ;.set ZERO=0 ;.set NINE=9 .def asc1 =r20 .def asc2 =r19 .def asc3 =r18 ; .def asc4 =r17 .def bin_h =r17 ; .def asc5 =r16 .def bin_l =r16 ; itoa: ldi asc1,ZERO-1;Will be '0' after 1st increment sub10k: inc asc1;'0','1','2','3','4','5','6' subi bin_l,low(10000) sbci bin_h,high(10000) brsh sub10k ; ldi asc2,NINE+1 add1k: dec asc2;'9','8','7','6','5','4','3','2','1','0' subi bin_l,low(-1000) sbci bin_h,high(-1000) brlo add1k ; ldi asc3,ZERO-1 sub100: inc asc3;'0','1','2','3','4','5','6','7','8','9' subi bin_l,low(100) sbci bin_h,high(100) brsh sub100 ; ldi asc4,NINE+1;Re-use bin_h as ASC4 add10: dec asc4;'9','8','7','6','5','4','3','2','1','0' subi bin_l,-10;Re-use bin_l as ASC5 brlo add10 subi asc5,-(ZERO);convert to ASCII ; ret Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 30 апреля, 2008 Опубликовано 30 апреля, 2008 · Жалоба После оцифровки сигнала в АЦП, в регистре имеется 8бит данных. Задача преобразовать этот двоичный регистр в три, Ну вот, такое отдающее "новизной" обсуждение, чуть было не прошло мимо меня :) Для одного байта я бы сделал как-нить так: ;Input: r16 - 8bit Binary ;Output: r18:r17:r16 unpacked BCD ldi r18,51 ldi r19,10 mov r17,r16 lsr r17 inc r17 mul r17,r18 mov r17,r1 mul r1,r19 sub r16,r0 mov r1,r17 lsr r1 inc r1 mul r1,r18 mov r18,r1 mul r1,r19 sub r17,r0 16 слов и 20 тактов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 30 апреля, 2008 Опубликовано 30 апреля, 2008 · Жалоба 16 слов и 20 тактовНе, чего-то первый раз не очень получилось, пробуем еще: ;Input: r16 - 8bit Binary ;Output: r18:r17:r16 unpacked BCD ldi r17,41 mul r16,r17 swap r0 swap r1 movw r16,r0 mov r18,r17 andi r18,0x0F andi r17,0xF0 andi r16,0x0F or r17,r16 inc r17 ldi r16,10 mul r16,r17 mov r17,r1 mul r0,r16 mov r16,r1 16 слов 19 тактов, ну и регистров меньше используем Нда..., подумал еще..., все нужно делать по-другому :( ;Input: r16 - 8bit Binary ;Output: r18:r17:r16 unpacked BCD ldi r17,164 mul r16,r17 clr r18 lsl r0 rol r1 rol r18 lsl r0 rol r1 rol r18 inc r1 ldi r16,10 mul r1,r16 mov r17,r1 mul r0,r16 mov r16,r1 15 слов 18 тактов Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuznec9999 0 30 апреля, 2008 Опубликовано 30 апреля, 2008 · Жалоба ;Input: r16 - 8bit Binary ;Output: r18:r17:r16 unpacked BCD ldi r17,164 mul r16,r17 clr r18 lsl r0 rol r1 rol r18 lsl r0 rol r1 rol r18 inc r1 ldi r16,10 mul r1,r16 mov r17,r1 mul r0,r16 mov r16,r1 15 слов 18 тактов Спасибо! Это именно то, что нужно! :beer: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 2 мая, 2008 Опубликовано 2 мая, 2008 · Жалоба ;Input: r16 - 8bit Binary ;Output: r18:r17:r16 unpacked BCD ldi r17,164 mul r16,r17 clr r18 lsl r0 rol r1 rol r18 lsl r0 rol r1 rol r18 inc r1 ldi r16,10 mul r1,r16 mov r17,r1 mul r0,r16 mov r16,r1 А нельзя ли пояснить вкратце? Начало я понял: деление на 100 осуществляется умножением на число 32768/100 и результат оказывается в третьем байте, а дальше? И как получается правильный результат несмотря на то что используется округленное частное - 328. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 2 мая, 2008 Опубликовано 2 мая, 2008 · Жалоба А нельзя ли пояснить вкратце? Начало я понял: деление на 100 осуществляется умножением на число 32768/100 и результат оказывается в третьем байте, а дальше? И как получается правильный результат несмотря на то что используется округленное частное - 328. после умножения на 164 и 2 сдвигов в r18 получаем количество сотен(X/100) результат для 2 сотен всегда правильный тк нужно было умножить на 163,84 а для всего 2 сотен достаточно округления до 164 после 2 сдвигов в r1:r0 получаем остаток от деления на 100 нормализованный к диапазону 0-65536, столько разрядов нам не нужно, хватит и 8 тк нам нужно получить всего 100 значений (0-99), остается r1 в котором значение 0-99 нормализованное до 0-256 нужно перевести его в десятки и единицы и это делается просто умножением 2 раза на 10, но для этого нужно скоректировать значение в r1, тк полученный остаток при первом делении и последующие умножения на 10 всегда отбрасывают младшие разряды, те принцип примерно как при получении среднего Smed = (Sum(X1,....XN)+N/2)/N для правильного округления в нужную сторону Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться