| Автор |
Съобщение |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
 Превъртащ се брояч
Дайте да видим кой как е решил този често срещан проблем.  Имаме превъртащ се брояч, размер 1 байт, стойности от 0 до 5, примерно. При достигане на 5 трябва да се нулира. Да кажем, че сме притиснати до стената и трябва да пестим всеки машинен цикъл.  Няма ли начин да стане с 2-3 аритметични операции, без да се ползват усл. оператори?
|
| Сря Фев 08, 2006 11:19 am |
|
 |
|
Wise
Ранг: Форумен бог
Регистриран на: Нед Дек 19, 2004 6:26 pm Мнения: 1628 Местоположение: Сливен
|
Аз обикновено го броя обратно - от 5 към 0 за да се ползва breq или brne
инструкции. А при 0 го зареждам с константата.
Така се избягва compare .
С аритметични операции не виждам как ще стане.
|
| Сря Фев 08, 2006 11:30 am |
|
 |
|
nickich
Ранг: Почетен член
Регистриран на: Вто Ное 01, 2005 10:23 am Мнения: 704 Местоположение: Limerick, Ireland
|
count++;
count %=5;
_________________ "640 К са достатъчни на всеки за всичко." Бил Гейтс
|
| Сря Фев 08, 2006 11:57 am |
|
 |
|
bateAz
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 4:11 pm Мнения: 3750 Местоположение: София
|
nickich, знаеш ли %= за колко цикъла се изпълнява? 
|
| Сря Фев 08, 2006 12:02 pm |
|
 |
|
nickich
Ранг: Почетен член
Регистриран на: Вто Ное 01, 2005 10:23 am Мнения: 704 Местоположение: Limerick, Ireland
|
bateAz, в интерес на истината не съм гледал какво генерира компилатора  , но на С изглежда добре 
_________________ "640 К са достатъчни на всеки за всичко." Бил Гейтс
|
| Сря Фев 08, 2006 12:21 pm |
|
 |
|
breeze
Ранг: Минаващ
Регистриран на: Пет Май 27, 2005 1:32 pm Мнения: 40 Местоположение: Sofia
|
В общия случай за N (но ако е допустимо броене назад вместо напред) няма по-прост начин от този, който предлага Wise. Иначе ако е задължително да се брои напред, не може да се избегне сравнението, условния преход и зареждането с по малък брой цикли. Все пак това са 3 инструкции.
Ако става дума за индекс към циркулярен буфер (най често за това ползваме такъв брояч) и ако имаме известна свобода да изберем дължина равна на точна степен на двойката, тогава ето какво е решението на Атмел (взето например от тяхната имплементация на UART управление с прекъсвания)
/* UART Buffer Defines */
#define UART_RX_BUFFER_SIZE 128 /* 2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_SIZE 128
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif
И после вече е лесно, след инкрементиране на брояча правим counter &= UART_RX_BUFFER_MASK, което съдържа само единици. По просто от това не може.
|
| Сря Фев 08, 2006 12:49 pm |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
По принцип xor със себе си дава 0, ще се помъча да измисля нещо в тая насока.
Другото, което може да се използва, е възможността за директен jump към адрес при някои процесори, което в комбинация с обратното броене, предложено от Wise, също може да даде добър резултат.
|
| Сря Фев 08, 2006 1:03 pm |
|
 |
|
Цецо
Ранг: Форумен бог
Регистриран на: Пон Сеп 27, 2004 9:22 am Мнения: 15501 Местоположение: София
|
Всички процесори имат инструкция Jump при 0. Така че наистина по оптимално от броенето назад невиждам.
_________________ "Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.
|
| Сря Фев 08, 2006 1:22 pm |
|
 |
|
Gogo
Ранг: Форумен бог
Регистриран на: Чет Фев 24, 2005 11:41 pm Мнения: 1049 Местоположение: Pz
|
Точно... По-бързо и по-малко едва ли може да стане по друг начин
|
| Сря Фев 08, 2006 6:03 pm |
|
 |
|
velio
Ранг: Форумен бог
Регистриран на: Вто Юни 07, 2005 6:20 pm Мнения: 3532
|
Ако трябва да брои напред (и ако) може да се ползва още един байт. Просто ще си брои назад по нормалния начин, а в допълнителния байт ще натрупва напред. Обаче инструкциите стават повечко.
|
| Сря Фев 08, 2006 9:55 pm |
|
 |
|
ToHu
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 9:21 pm Мнения: 30685 Местоположение: София
|
Ами зависи от поцесора, може да с еползва ако има флаг вдигащ се при пренос от FF към 0, или ако рзултата от операцията е нула, в тоя случай зреждаш допулнението до FF, но пак губиш възможността от директно ползване на брояча, т.е. стойността му няма да е реалния брой цикли.
|
| Пет Фев 10, 2006 9:46 am |
|
 |
|
Реконструктор
Ранг: Форумен бог
Регистриран на: Съб Сеп 25, 2004 12:32 pm Мнения: 8382 Местоположение: София
|
Вече почвам да си мисля, че ако някой производител на микроконтролери я направи тази екстра с брояча хардуерно, ще спечели доста пари.  В AVR-а (а предполагам и на други места) е направено, но само за таймерите.
|
| Пет Фев 10, 2006 9:55 am |
|
 |
|
bateAz
Ранг: Форумен бог
Регистриран на: Нед Сеп 26, 2004 4:11 pm Мнения: 3750 Местоположение: София
|
В i8051 има CJNE - с една инструкция: проверява дали операнд1 = операнд2 и ако не е, прави преход. Аз защо казвам, че 8051 е класика, а?
Например: CJNE R1, #5, loop_proc
|
| Пет Фев 10, 2006 10:37 am |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
малко офтопик: присъединявам се към батето с аргумента че поне на мен това е единствения ми познат ЦПУ който може да прави "mov [addr], [addr]" с една инструкция 
|
| Пет Фев 10, 2006 12:31 pm |
|
 |
|
mitko
Ранг: Минаващ
Регистриран на: Пет Фев 10, 2006 2:10 am Мнения: 19 Местоположение: Sofia
|
Само не разбрах памет ли се пести или скорост
ако е скорост и стойностите са само 0-5 можеш да скочиш по таблица с индекс брояча ти
в някои процесори има много бързи команди за такива преходи
|
| Пет Фев 10, 2006 1:10 pm |
|
|