Преобразование байта в три десятичные цифры
-
neitrino777
- Родился
- Сообщения: 19
- Зарегистрирован: Вс сен 09, 2018 06:42:27
Преобразование байта в три десятичные цифры
Всем привет ! прошу сильно меня не бить. Если создаю не нужную тему.
Искал я как то решение по отображению результатов работы ацп - на экране ТМ1637. И нужно было Преобразование байта в три десятичные цифры. Ответа не нашёл.
И просто сделал так. см. код. Не знаю насколько это оптимально - но мою задачу решает. Комментарии подробные писать не стал. На усмотрение модератора - можно удалить это.
; Редакция 27-05-19 - . Преобразуем 8 битное число в 3 десятичные цифры
;*******************************************
.include "tn13def.inc"
;****** РЕГИСТРЫ
.def ADCREZULT =r16 ; наши данные из ацп
.def dig0 =r17 ; результат для вывода на экран
.def dig1 =r18 ; результат для вывода на экран
.def dig2 =r19 ; результат для вывода на экран
rjmp RESET ;Reset Handle
reti ;External InterruptO Vector Address
reti ;External Interruptl Vector Address
reti ;Прерывание по переполнению таймера/счетчика 0
reti ;EE_READY_vect EEPROM готова
reti ;ANALOG_COMP_vect Аналоговый компаратор переключился
reti ;TIMER0_COMPA_vect Прерывание по сравнению, канал A таймера/счетчика 0
reti ;TIMER0_COMPB_vect Прерывание по сравнению, канал B таймера/счетчика 0
reti ;WDT_vect Сторожевой таймер (если используется в качестве источника прерывания)
reti ;ADC_vect Преобразование АЦП завершено
.cseg ; область команд
RESET:
clr dig0
clr dig1
clr dig2
clr ADCREZULT
ldi ADCREZULT,0xD3
povtor: subi ADCREZULT,100
brcs dalshe ;прекратить при установки флага переноса
inc dig2
rjmp povtor
dalshe: subi ADCREZULT,-100 ; компенсируем вычитание
povtor1: subi ADCREZULT,10
brcs dalshe2
inc dig1
rjmp povtor1
dalshe2: subi ADCREZULT,-10
povtor2: subi ADCREZULT,1
brcs dalshe3
inc dig0
rjmp povtor2
dalshe3: nop
nop
nop
Искал я как то решение по отображению результатов работы ацп - на экране ТМ1637. И нужно было Преобразование байта в три десятичные цифры. Ответа не нашёл.
И просто сделал так. см. код. Не знаю насколько это оптимально - но мою задачу решает. Комментарии подробные писать не стал. На усмотрение модератора - можно удалить это.
; Редакция 27-05-19 - . Преобразуем 8 битное число в 3 десятичные цифры
;*******************************************
.include "tn13def.inc"
;****** РЕГИСТРЫ
.def ADCREZULT =r16 ; наши данные из ацп
.def dig0 =r17 ; результат для вывода на экран
.def dig1 =r18 ; результат для вывода на экран
.def dig2 =r19 ; результат для вывода на экран
rjmp RESET ;Reset Handle
reti ;External InterruptO Vector Address
reti ;External Interruptl Vector Address
reti ;Прерывание по переполнению таймера/счетчика 0
reti ;EE_READY_vect EEPROM готова
reti ;ANALOG_COMP_vect Аналоговый компаратор переключился
reti ;TIMER0_COMPA_vect Прерывание по сравнению, канал A таймера/счетчика 0
reti ;TIMER0_COMPB_vect Прерывание по сравнению, канал B таймера/счетчика 0
reti ;WDT_vect Сторожевой таймер (если используется в качестве источника прерывания)
reti ;ADC_vect Преобразование АЦП завершено
.cseg ; область команд
RESET:
clr dig0
clr dig1
clr dig2
clr ADCREZULT
ldi ADCREZULT,0xD3
povtor: subi ADCREZULT,100
brcs dalshe ;прекратить при установки флага переноса
inc dig2
rjmp povtor
dalshe: subi ADCREZULT,-100 ; компенсируем вычитание
povtor1: subi ADCREZULT,10
brcs dalshe2
inc dig1
rjmp povtor1
dalshe2: subi ADCREZULT,-10
povtor2: subi ADCREZULT,1
brcs dalshe3
inc dig0
rjmp povtor2
dalshe3: nop
nop
nop
Работа - продажа электронных компонентов. А для души - есть Ассемблер, дочка и сын.
- Реклама
Re: Преобразование байта в три десятичные цифры
Если я ничего не напутал, то вам нужно преобразовать двоично-десятичный код в десятичный.
пример первый попавшийся
uint8_t hex = 0x11;
assert(((hex & 0xF0) >> 4) < 10); // More significant nybble is valid
assert((hex & 0x0F) < 10); // Less significant nybble is valid
int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
пример первый попавшийся
uint8_t hex = 0x11;
assert(((hex & 0xF0) >> 4) < 10); // More significant nybble is valid
assert((hex & 0x0F) < 10); // Less significant nybble is valid
int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
ZZZ С Нами Бог ZZZ
-
neitrino777
- Родился
- Сообщения: 19
- Зарегистрирован: Вс сен 09, 2018 06:42:27
Re: Преобразование байта в три десятичные цифры
спасибо за интерес. Здесь не преобразования bcd. Аппнот 204 - прочитал - не сильно внимательно. Но мою задачу он не решает быстро и просто. Я только учу ассемблер - ваш пример для меня
в диковинку - я таких команд не знаю. Пример у нас есть число 211 - нужно его вывести на экран ТМ1637 - там типа интерфейса I2C. Передаём весовые коды - обычные байты с кодом символа.
На нужно отдельно последовательно передать цифры 2---1---1. (начал изучать ацп attiny13 - интересно посмотреть на его показания в реальном времени)
в диковинку - я таких команд не знаю. Пример у нас есть число 211 - нужно его вывести на экран ТМ1637 - там типа интерфейса I2C. Передаём весовые коды - обычные байты с кодом символа.
На нужно отдельно последовательно передать цифры 2---1---1. (начал изучать ацп attiny13 - интересно посмотреть на его показания в реальном времени)
Работа - продажа электронных компонентов. А для души - есть Ассемблер, дочка и сын.
- ПростоНуб
- Собутыльник Кота
- Сообщения: 2723
- Зарегистрирован: Пт сен 07, 2018 20:20:02
- Откуда: деревня в Тульской губернии
Re: Преобразование байта в три десятичные цифры
[uquote="neitrino777",url="/forum/viewtopic.php?p=3641598#p3641598"]Ответа не нашёл.[/uquote]
Вот один из самых эффективных алгоритмов для этой цели.
Вот один из самых эффективных алгоритмов для этой цели.
Re: Преобразование байта в три десятичные цифры
Вот ещё способ: Допустим, нужно разложить однобайтовое число n на цифры. Обозначим их n1,n2,n3. Используем 8х8->16 перемножитель в AVR8.
1. Вычислить d = (n*205) >> 11. Умножение даст (в общем случае) 16-битное число, и на ассемблере сдвиг на 11 можно реализовать взяв старший байт полученного числа и сдвинув его вправо на 3 позиции.
Полученное число d равно целой части n / 10.
2. Вычислить n3 = n - d*10 - это будет младшая цифра.
3. Вычислить n1 = (d*26) >> 8, заменив сдвиг просто взятием старшего байта произведения.
4. Вычислить n2 = d - n1*10. Получим среднюю цифру.
Пример для n = 219:
1. d = (219*205) = 0xAF5F (в шестнадцатиричном обозначении). Старший байт = 0xAF = 175. Сдвинув его на 3 разряда вправо получим 21 (= целая часть 219/10)
2. n3 = 219 - 21*10 = 9 (последняя цифра)
3. n1 = (21*26) = 0x0222. Старший байт = 2 (первая цифра)
4. n2 = 21 = 2*10 = 1 (средняя цифра)
1. Вычислить d = (n*205) >> 11. Умножение даст (в общем случае) 16-битное число, и на ассемблере сдвиг на 11 можно реализовать взяв старший байт полученного числа и сдвинув его вправо на 3 позиции.
Полученное число d равно целой части n / 10.
2. Вычислить n3 = n - d*10 - это будет младшая цифра.
3. Вычислить n1 = (d*26) >> 8, заменив сдвиг просто взятием старшего байта произведения.
4. Вычислить n2 = d - n1*10. Получим среднюю цифру.
Пример для n = 219:
1. d = (219*205) = 0xAF5F (в шестнадцатиричном обозначении). Старший байт = 0xAF = 175. Сдвинув его на 3 разряда вправо получим 21 (= целая часть 219/10)
2. n3 = 219 - 21*10 = 9 (последняя цифра)
3. n1 = (21*26) = 0x0222. Старший байт = 2 (первая цифра)
4. n2 = 21 = 2*10 = 1 (средняя цифра)
- Реклама
- Ivanoff-iv
- Друг Кота
- Сообщения: 7077
- Зарегистрирован: Пт ноя 11, 2016 05:48:09
- Откуда: Сердце Пармы
Re: Преобразование байта в три десятичные цифры
это если мега... а тиня умножать не умеет
Для тех, кто не учил магию мир полон физики 
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Безграмотно вопрошающим про силовую или высоковольтную электронику я не отвечаю, а то ещё посадят за участие в (само)убиении оболтуса...
Re: Преобразование байта в три десятичные цифры
Тоже неплохой алгоритм, давным давно взятый с электроникса. Легко адаптируется для разложения больших чисел.
Добавлено after 6 minutes 55 seconds:
neitrino777 Замечу, что в коде ниже можно просто остаток единиц занести в dig0
Код: Выделить всё
BINBCD:
LDS R17,$70 ; HEX IN
CLR R30 ; BCD OUT 1'000,100
CLR R31 ; BCD OUT 10,1
LDI R28,8
bin8_bcd3:
subi r31,-0x33 ;add 0x33
sbrs r31, 3 ;if carry to bit 3
subi r31, 3 ;subtract 3
sbrs r31, 7 ;if carry to bit 7
subi r31, 0x30 ;subtract 0x30
subi r30,-0x33 ; \n" /*add 0x33*/
sbrs r30, 3 ; \n" /*if carry to bit 3,*/
subi r30, 3 ; \n" /*subtract 3*/
sbrs r30, 7 ; \n" /*if carry to bit 7,*/
subi r30, 0x30 ; \n" /*subtract 0x30*/
LSL R17 ;shift input*/
rol r31
rol r30 ; \n" /*shift out buffer*/
dec R28 ;\n"
brne bin8_bcd3 ;repeat for all bits*/
RET
neitrino777 Замечу, что в коде ниже можно просто остаток единиц занести в dig0
Код: Выделить всё
povtor2: MOV dig0,ADCREZULT
; subi ADCREZULT,1
;brcs dalshe3
;inc dig0
;rjmp povtor2
dalshe3: nop- Engineer_Keen
- Друг Кота
- Сообщения: 3872
- Зарегистрирован: Пт янв 29, 2010 10:27:40
- Откуда: Москва
Re: Преобразование байта в три десятичные цифры
Не знаю как для других вариантов преобразования, но для варианта "байт->3 десятичные цифры", оптимальным является именно вариант из первого поста, т.е. последовательное вычитание 100,10, с учетом последнего замечания akl (остаток единиц, получается автоматом). Его преимущество и в размере (меньше на полтора десятка байт) и в скорости выполнения.
Достоинство метода "сдвиг-сложение с 3" (double-dabble), в том, что этот алгоритм выполняется всегда за почти одинаковое время, например для 16МГц это примерно 8мкс, не зависимо от числа на входе. Дело конечно в заранее известном количестве циклов, но при этом занята +1 переменная под счетчик цикла, и в конце еще надо распихивать нибблы, в отдельные байты, так как там в каждом байте результата получается по 2 разряда десятичного числа.
Для метода последовательных вычитаний время выполнения от 750нс (на входе 0), до 4мкс (на входе 199, максимальное количество вычитаний), и каждый байт в итоге уже содержит один разряд десятичного числа.
Достоинство метода "сдвиг-сложение с 3" (double-dabble), в том, что этот алгоритм выполняется всегда за почти одинаковое время, например для 16МГц это примерно 8мкс, не зависимо от числа на входе. Дело конечно в заранее известном количестве циклов, но при этом занята +1 переменная под счетчик цикла, и в конце еще надо распихивать нибблы, в отдельные байты, так как там в каждом байте результата получается по 2 разряда десятичного числа.
Для метода последовательных вычитаний время выполнения от 750нс (на входе 0), до 4мкс (на входе 199, максимальное количество вычитаний), и каждый байт в итоге уже содержит один разряд десятичного числа.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Re: Преобразование байта в три десятичные цифры
Метод последовательного вычитания быстр и начинает проигрывать при преобразовании больших чисел, когда вес оных превышает возможности ассемблера (4 байта). Пользуюсь и тем и другим.
Например, преобразование 40 разрядного числа только на старшей части регистрового файла AVR.
Например, преобразование 40 разрядного числа только на старшей части регистрового файла AVR.
Спойлер
Код: Выделить всё
LDS R16,$70
LDS R17,$71
LDS R18,$72
LDS R19,$73 ; HEX IN
LDS R20,$74
CLR R25 ; BCD OUT 10'000'000'000'000,1'000'000'000'000
CLR R26 ; BCD OUT 100'000'000'000,10'000'000'000
CLR R27 ; BCD OUT 1'000'000'000,100'000'000
CLR R28 ; BCD OUT 10'000'000,1'000'000
CLR R29 ; BCD OUT 100'000,10'000
CLR R30 ; BCD OUT 1'000,100
CLR R31 ; BCD OUT 10,1
LDI R24,40
bin40bcd13:
subi r31,-0x33 ;add 0x33
sbrs r31, 3 ;if carry to bit 3
subi r31, 3 ;subtract 3
sbrs r31, 7 ;if carry to bit 7
subi r31, 0x30 ;subtract 0x30
subi r30,-0x33 ; \n" /*add 0x33*/
sbrs r30, 3 ; \n" /*if carry to bit 3,*/
subi r30, 3 ; \n" /*subtract 3*/
sbrs r30, 7 ; \n" /*if carry to bit 7,*/
subi r30, 0x30 ; \n" /*subtract 0x30*/
subi r29,-0x33 ;\n" /*add 0x33*/
sbrs r29, 3 ;\n" /*if carry to bit 3,*/
subi r29, 3 ;\n" /*subtract 3*/
sbrs r29, 7 ;\n" /*if carry to bit 7,*/
subi r29, 0x30 ;\n" /*subtract 0x30*/
subi r28,-0x33 ;\n" /*add 0x33*/
sbrs r28, 3 ;\n" /*if carry to bit 3,*/
subi r28, 3 ;\n" /*subtract 3*/
sbrs r28, 7 ;\n" /*if carry to bit 7,*/
subi r28, 0x30 ;\n" /*subtract 0x30*/
subi r27,-0x33 ;\n" /*add 0x33*/
sbrs r27, 3 ;\n" /*if carry to bit 3,*/
subi r27, 3 ;\n" /*subtract 3*/
sbrs r27, 7 ;\n" /*if carry to bit 7,*/
subi r27, 0x30 ;\n" /*subtract 0x30*/
subi r26,-0x33 ;\n" /*add 0x33*/
sbrs r26, 3 ;\n" /*if carry to bit 3,*/
subi r26, 3 ;\n" /*subtract 3*/
sbrs r26, 7 ;\n" /*if carry to bit 7,*/
subi r26, 0x30 ;\n" /*subtract 0x30*/
subi r25,-0x33 ;\n" /*add 0x33*/
sbrs r25, 3 ;\n" /*if carry to bit 3,*/
subi r25, 3 ;\n" /*subtract 3*/
sbrs r25, 7 ;\n" /*if carry to bit 7,*/
subi r25, 0x30 ;\n" /*subtract 0x30*/
lsl R20
rol R19
rol R18
rol R17 ;shift input*/
rol R16
rol r31
rol r30
rol r29
rol r28 ; \n" /*shift out buffer*/
rol r27
rol r26
rol r25
dec R24 ;\n"
brne bin40bcd13 ;repeat for all bits*/
RET-
neitrino777
- Родился
- Сообщения: 19
- Зарегистрирован: Вс сен 09, 2018 06:42:27
Re: Преобразование байта в три десятичные цифры
test
Добавлено after 13 minutes 21 second:
Спасибо всем за предложенные варианты. Особое спасибо за подсказку after 6. Буду дальше изучать тиньку - что из нее можно выжать. Для моих экспериментов её более чем достаточно.
Добавлено after 13 minutes 21 second:
Спасибо всем за предложенные варианты. Особое спасибо за подсказку after 6. Буду дальше изучать тиньку - что из нее можно выжать. Для моих экспериментов её более чем достаточно.
Работа - продажа электронных компонентов. А для души - есть Ассемблер, дочка и сын.
Re: Преобразование байта в три десятичные цифры
[uquote="akl",url="/forum/viewtopic.php?p=3641961#p3641961"]Например, преобразование 40 разрядного числа...[/uquote] Знакомые строки
Пользуясь случаем, еще раз спасибо akl за конкурсный LC-метр, в особенности за выложенные исходники. До сих пор приятно в них покопаться и переиначить на очередное устройство. Два здесь публиковались, одно на конкурсе даже до 5 места (или 6, не припомню) добралось. Создается и третье, вполне себе оригинальное. Кроме того, те исходники - отличный образец многоразрядной арифметики.
Пользуясь случаем, еще раз спасибо akl за конкурсный LC-метр, в особенности за выложенные исходники. До сих пор приятно в них покопаться и переиначить на очередное устройство. Два здесь публиковались, одно на конкурсе даже до 5 места (или 6, не припомню) добралось. Создается и третье, вполне себе оригинальное. Кроме того, те исходники - отличный образец многоразрядной арифметики.
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Преобразование байта в три десятичные цифры
Спойлер
Код: Выделить всё
;-------------------------------------------------------------------------
#define BCD YES
;===================
.macro ldx
ldi XH,High(@0)
ldi XL,Low(@0)
.endmacro
.macro ldy
ldi YH,High(@0)
ldi YL,Low(@0)
.endmacro
.macro ldz
ldi ZH,High(@0)
ldi ZL,Low(@0)
.endmacro
;-------------------------------------------------------------------------
#define tab_h(x) HIGH(x), LOW(x)
#define tab_l(x) LOW(x), HIGH(x)
;-------------------------------------------------------------------------
;----------------------------- Отладка -----------------------------------
rcall Clr_Hex_Dex_Buffer
ldi r16, 199
rcall Hex_Dec_8_Bit
rcall Clr_Hex_Dex_Buffer
ldi r16, LOW (64999)
ldi r17, HIGH (64999)
rcall Hex_Dec_16_Bit
;-------------------------------------------------------------------------
/************************************************************************/
#if (BCD == YES)
.dseg
HEX_DEC_BUFFER:
.equ HEX_DEC_BUFFER_LENGHT = 5
.byte HEX_DEC_BUFFER_LENGHT
.cseg
Clr_Hex_Dex_Buffer:
ldx HEX_DEC_BUFFER
clr r16
ldi r17, HEX_DEC_BUFFER_LENGHT
Clr_Hex_Dex_Buffer_Cycle:
st X+, r16
dec r17
brne Clr_Hex_Dex_Buffer_Cycle
ret
//==================
// r16 - hex data
// r17 - вычитаемое число из таблицы
// r18 - cnt_1
// r19 - cnt_2
Hex_Dec_8_Bit:
ldx HEX_DEC_BUFFER
ldz TAB_HEX_DEC_8_BIT*2
ldi r18, 2
Hex_Dec_8_Bit_Cycle_1:
lpm r17, Z+
ldi r19, -1
Hex_Dec_8_Bit_Cycle_2:
inc r19
sub r16, r17
brsh Hex_Dec_8_Bit_Cycle_2
add r16, r17
ori r19, 0x30
st X+, r19
dec r18
brne Hex_Dec_8_Bit_Cycle_1
ori r16,0x30
st X+, r16
Hex_Dec_8_Bit_End:
ret
//------------------------------------------------------------------------
//------------------------------------------------------------------------
TAB_HEX_DEC_8_BIT:
.db 100, 10
//==================
//==================
// r16, r17 - hex data
// r18, r19 - вычитаемое число из таблицы
// r20 - cnt_1
// r21 - cnt_2
Hex_Dec_16_Bit:
ldx HEX_DEC_BUFFER
ldz TAB_HEX_DEC_16_BIT*2
ldi r20, 4
Hex_Dec_16_Bit_Cycle_1:
lpm r18, Z+
lpm r19, Z+
ldi r21, -1
Hex_Dec_16_Bit_Cycle_2:
inc r21
sub r16, r18
sbc r17, r19
brsh Hex_Dec_16_Bit_Cycle_2
add r16, r18
adc r17, r19
ori r21, 0x30
st X+, r21
dec r20
brne Hex_Dec_16_Bit_Cycle_1
ori r16,0x30
st X+, r16
Hex_Dec_16_Bit_End:
ret
//------------------------------------------------------------------------
//------------------------------------------------------------------------
TAB_HEX_DEC_16_BIT:
.db tab_l (10000)
.db tab_l (1000)
.db tab_l (100)
.db tab_l (10)
//==================
#endif
/************************************************************************/
- B@R5uk
- Собутыльник Кота
- Сообщения: 2896
- Зарегистрирован: Сб ноя 13, 2010 12:53:25
- Откуда: приходит весна?
Re: Преобразование байта в три десятичные цифры
[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3641953#p3641953"]Не знаю как для других вариантов преобразования, но для варианта "байт->3 десятичные цифры", оптимальным является именно вариант из первого поста, т.е. последовательное вычитание 100,10, с учетом последнего замечания akl (остаток единиц, получается автоматом). Его преимущество и в размере (меньше на полтора десятка байт) и в скорости выполнения.[/uquote]
Долго мучил голову в попытках опровергнуть это утверждение. Этого, конечно, сделать не удалось, но в результате всех мучений родилось такое вот извращение:
Основная идея была в том, что код топикстартера имеет линейную сложность и её можно улучшить до логарифмической небольшим усложнением кода. Деление с остатком методом вычитания заменяется побитовым делением с остатком. Однако, усложнение приводит к большей константе перед логарифмом (по сравнению с константой перед линейным членом в "примитивном" алгоритме) и, поскольку под логарифмом стоит число от 1 до 10 (то есть слишком маленькое, чтобы была принципиальная разница между аргументом логарифма и его значением), в результате ускорения добиться не получается.
Думаю, все остальные алгоритмы (какими бы они не были) обладают той же проблемой даже при больших разрядностях исходного числа. Вот, если бы мы пользовались бы не 10-ой системой, а какой-нибудь 24-ой или ещё лучше 60-ой, то было бы совсем другое дело!!!
На всякий случай модифицированный код топикстартера. Время выполнения варьируется от 11 тактов (для байтов, меньших 10) до 61 такта (для байтов, начинающихся на 19).
Долго мучил голову в попытках опровергнуть это утверждение. Этого, конечно, сделать не удалось, но в результате всех мучений родилось такое вот извращение:
Код: Выделить всё
;==============
.def cntr = r16
.def dig1 = r17
.def dig2 = r18
.def dig3 = r19
.def sbtr = r20
;==============
; Время выполнения 65 тактов
ldi dig3, 0xFF ; Преобразуемое в десятичный вид число
ldi cntr, 0x02 ; Выделяется 2 бита первой цифры
ldi sbtr, 0xC8 ; 100 * 2 ^ (2 - 1)
clr dig1 ; Подготовка искомой цифры
loop_1: lsl dig1 ; Удвоение искомой цифры
sub dig3, sbtr ; Выделение очередного бита
brcs loop_1a
inc dig1 ; Бит 1: увеличить искомую цифру
loop_1a: brcc loop_1b
add dig3, sbtr ; Бит 0: восстановить аргумент
loop_1b: lsr sbtr ; Значение следующего бита искомой цифры
dec cntr
brne loop_1 ; Повтор для всех битов
ldi cntr, 0x04 ; Выделяется 4 бита второй цифры
ldi sbtr, 0x50 ; 10 * 2 ^ (4 - 1)
clr dig2 ; Подготовка искомой цифры
loop_2: lsl dig2 ; Удвоение искомой цифры
sub dig3, sbtr ; Выделение очередного бита
brcs loop_2a
inc dig2 ; Бит 1: увеличить искомую цифру
loop_2a: brcc loop_2b
add dig3, sbtr ; Бит 0: восстановить аргумент
loop_2b: lsr sbtr ; Значение следующего бита искомой цифры
dec cntr
brne loop_2 ; Повтор для всех битов
; Третья цифра получается автоматически
;==============
Думаю, все остальные алгоритмы (какими бы они не были) обладают той же проблемой даже при больших разрядностях исходного числа. Вот, если бы мы пользовались бы не 10-ой системой, а какой-нибудь 24-ой или ещё лучше 60-ой, то было бы совсем другое дело!!!
На всякий случай модифицированный код топикстартера. Время выполнения варьируется от 11 тактов (для байтов, меньших 10) до 61 такта (для байтов, начинающихся на 19).
Код: Выделить всё
;==============
.def dig1 = r17
.def dig2 = r18
.def dig3 = r19
;==============
; Время выполнения 11 + 5 * {сумма первой и второй цифр} тактов
ldi dig3, 0xFF ; Преобразуемое в десятичный вид число
clr dig1 ; Подготовка первой цифры
loop_1: subi dig3, 0x64 ; Цикл вычитания 100
brcs loop_1a ; Окончание цикла, когда остаток меньше 100
inc dig1 ; Инкремент первой цифры
rjmp loop_1
loop_1a: subi dig3, 0x9C ; Коррекция остатка
clr dig2 ; Подготовка второй цифры
loop_2: subi dig3, 0x0A ; Цикл вычитания 10
brcs loop_2a ; Окончание цикла, когда остаток меньше 10
inc dig2 ; Инкремент второй цифры
rjmp loop_2
loop_2a: subi dig3, 0xF6 ; Коррекция остатка, являющ. третьей цифрой
;==============
Re: Преобразование байта в три десятичные цифры
Если честно "стандартное преобразование" данных 0-99 (типовые часики, считалки)
наиболее просто решаются табличным способом.
А уже куда побольше - за сотню - там математика.
Однако это уже потребует заготовок не только на один байт.
Ибо 999 это 0х3E7 - а 3 знакоместа подразумевают 0-999.

наиболее просто решаются табличным способом.
А уже куда побольше - за сотню - там математика.
Однако это уже потребует заготовок не только на один байт.
Ибо 999 это 0х3E7 - а 3 знакоместа подразумевают 0-999.
- Starichok51
- Модератор
- Сообщения: 19049
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Преобразование байта в три десятичные цифры
вот еще один немудреный алгоритм.
исходное число в R10.
исходное число в R10.
Код: Выделить всё
clr R12
ldi R26, 100
test_100:
cp R10, R26
brcs test_10_1
sub R10, R26
inc R12
rjmp test_100
test_10_1:
ldi R26, 10
test_10:
cp R10, R26
brcs end_test
sub R10, R26
inc R11
rjmp test_10
end_test:Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Re: Преобразование байта в три десятичные цифры
Нужно почистить ещё и регистр десятков R11.
Код: Выделить всё
CLR R11
clr R12
ldi R26, 100
test_100:
cp R10, R26
brcs test_10_1
sub R10, R26
inc R12
rjmp test_100
test_10_1:
ldi R26, 10
test_10:
cp R10, R26
brcs end_test
sub R10, R26
inc R11 ; при входе этот регистр должен очищаться
rjmp test_10
end_test:
RJMP PC- Starichok51
- Модератор
- Сообщения: 19049
- Зарегистрирован: Сб авг 14, 2010 15:05:51
- Откуда: г. Озерск, Челябинская обл.
Re: Преобразование байта в три десятичные цифры
в данном случае (с одним байтом) да, нужно очистить R11.
это я взял свой кусок текста, где вычитались тысячи и сотни, и исходное число было в R10 и R11.
поспешил скопировать и вставить, а про очистку R11 забыл...
и после вычитания сотен R11 сам очистится, предварительно его чистить не надо.
это я взял свой кусок текста, где вычитались тысячи и сотни, и исходное число было в R10 и R11.
поспешил скопировать и вставить, а про очистку R11 забыл...
и после вычитания сотен R11 сам очистится, предварительно его чистить не надо.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
-
Frogfot
- Мучитель микросхем
- Сообщения: 443
- Зарегистрирован: Ср окт 19, 2011 08:48:27
- Откуда: Мать городов русских
Re: Преобразование байта в три десятичные цифры
[uquote="akl",url="/forum/viewtopic.php?p=3641961#p3641961"]Метод последовательного вычитания быстр и начинает проигрывать при преобразовании больших чисел, когда вес оных превышает возможности [/uquote]
Кто подскажет, как работает этот метод - добавляем к ниблу число 3, и если нибл становится больше 7, то отнимаем 3, а если не больше 7, то не отнимаем ???
Код: Выделить всё
bin40bcd13:
subi r31,-0x33 ;add 0x33
sbrs r31, 3 ;if carry to bit 3
subi r31, 3 ;subtract 3
sbrs r31, 7 ;if carry to bit 7
subi r31, 0x30 ;subtract 0x30Кто подскажет, как работает этот метод - добавляем к ниблу число 3, и если нибл становится больше 7, то отнимаем 3, а если не больше 7, то не отнимаем ???
Хорошему коту и в декабре - март 
-
Demiurg
- Это не хвост, это антенна
- Сообщения: 1480
- Зарегистрирован: Ср июн 25, 2008 15:19:44
- Контактная информация:
Re: Преобразование байта в три десятичные цифры
Чем мой пример не угодил?
Re: Преобразование байта в три десятичные цифры
[uquote="Frogfot",url="/forum/viewtopic.php?p=3655792#p3655792"]Кто подскажет, как работает этот метод - добавляем к ниблу число 3, и если нибл становится больше 7, то отнимаем 3, а если не больше 7, то не отнимаем ???[/uquote]Не забывайте, что преобразование идет побитно в цикле. Для лучшего понимания можно в симуляторе погонять преобразование байта в двоично-десятичный код.
Код: Выделить всё
;Преобразование 8bin-3dec
BINBCD:
LDS R17,$70 ; HEX IN
CLR R30 ; BCD OUT 1'000,100
CLR R31 ; BCD OUT 10,1
LDI R28,8
bin8_bcd3:
subi r31,-0x33 ;add 0x33
sbrs r31, 3 ;if carry to bit 3
subi r31, 3 ;subtract 3
sbrs r31, 7 ;if carry to bit 7
subi r31, 0x30 ;subtract 0x30
subi r30,-0x33 ; \n" /*add 0x33*/
sbrs r30, 3 ; \n" /*if carry to bit 3,*/
subi r30, 3 ; \n" /*subtract 3*/
sbrs r30, 7 ; \n" /*if carry to bit 7,*/
subi r30, 0x30 ; \n" /*subtract 0x30*/
LSL R17 ;shift input*/
rol r31
rol r30 ; \n" /*shift out buffer*/
dec R28 ;\n"
brne bin8_bcd3 ;repeat for all bits*/
RJMP BINBCD
.EXIT


