[uquote="Engineer_Keen",url="/forum/viewtopic.php?p=3641953#p3641953"]Не знаю как для других вариантов преобразования, но для варианта "байт->3 десятичные цифры",
оптимальным является именно вариант из первого поста, т.е. последовательное вычитание 100,10, с учетом последнего замечания
akl (остаток единиц, получается автоматом). Его преимущество и в размере (меньше на полтора десятка байт) и
в скорости выполнения.[/uquote]
Долго мучил голову в попытках опровергнуть это утверждение. Этого, конечно, сделать не удалось, но в результате всех мучений родилось такое вот извращение:
Код: Выделить всё
;==============
.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 ; Повтор для всех битов
; Третья цифра получается автоматически
;==============
Основная идея была в том, что код топикстартера имеет линейную сложность и её можно улучшить до логарифмической небольшим усложнением кода. Деление с остатком методом вычитания заменяется побитовым делением с остатком. Однако, усложнение приводит к б
ольшей константе перед логарифмом (по сравнению с константой перед линейным членом в "примитивном" алгоритме) и, поскольку под логарифмом стоит число от 1 до 10 (то есть слишком маленькое, чтобы была принципиальная разница между аргументом логарифма и его значением), в результате ускорения добиться не получается.
Думаю, все остальные алгоритмы (какими бы они не были) обладают той же проблемой даже при б
ольших разрядностях исходного числа. Вот, если бы мы пользовались бы не 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 ; Коррекция остатка, являющ. третьей цифрой
;==============