Форум проекта "Минилаб-Мастер"
Клуб по интересам - отдыхаем от фотобизнеса => Программирование => Тема начата: Andy от 16 Января 2013, 16:03:05
-
Нужен очень простой и быстрый алгоритм - отзеркалить биты в байте - так, чобы самый старший стал малдшим и так далее. В интернете примеры все какие то громоздкие, неужели нет простого и красивого решения?
Например здесь - http://forum.sources.ru/index.php?showtopic=49181
-
Самый быстрый алгоритм - готовый массив уже реверснутых байт. Занимает 256 байт, но работает чертовски быстро:
Y = Rev[X]
А так? вот вполне компактный и код, и довольно быстрый (57 команд на один байт). Синтаксис Паскаля:
function Rev(B:Byte):Byte;
var
i: Integer;
begin
Result := 0;
for i := 0 to 7 do
Result := Result or (((B and (1 shl i)) shr i) shl (7-i));
end;
// ---------------------------
Y := Rev(X);
На баскоме:
$regfile = "m48def.dat"
$crystal = 4000000
$baud = 19200
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Dim X As Byte
Dim Y As Byte
Dim I As Byte
Dim Ix As Byte
Dim K As Byte
X = 77 \'будет 178
Gosub Rev
Print Y
End
Rev:
Y = 0
For I = 0 To 7
K = 1
Shift K , Left , I
K = K And X
Shift K , Right , I
Ix = 7 - I
Shift K , Left , Ix
Y = Y Or K
Next I
Return
-
176 байт, неплохо. У меня идея появилась пихать биты в каким либо образом в стек, а потом забирать отуда. Можно в цикле, можно напрямую. Типа такого примера - (он нерабочий).
Mirror:
push r31
For J = 0 To 7
Nm = A_week.j
ldi r31,{Nm}
push r31
Next
For J = 0 To 7
pop r31
sts {Nm} ,r31
A_week.j = Nm
Next
pop r31
Return
Он занимает 162 байта, и его надо написать польностью на асме, проблема как из регистра с переменной выщелкнуть нужный бит в младший бит следующего регистра, чтобы сохранить в стек, и сделать обратную процедуру. Иногда мне кажется что работа с битами - черезмерные наклодные расходы, проще сделать восмибайтный массив и работать с ним.
-
Да, попробовал.. Действительно, работа с байтами куда короче. Массив из 8 байт работает быстрее и код короче получился. 125 байт.
Dim N As Byte
Dim K As Byte
Dim Cik As Byte
Dim Weekly(8) As Byte
Mirror:
Cik = 8
For J = 1 To 4
K = Weekly(j)
Weekly(j) = Weekly(cik)
Weekly(cik) = K
Decr Cik
Next
Return
Просто была идея использовать один байт для хранения дней недели когда срабатывать будильнику и собственно включен ли будильник, там он очень красиво разворачивался одной строкой на дисплей командой
Stroka = Bin(a_week)
Lcd Stroka
но строка красиво все развернула - самый старший бит впереди, а цикл против шерсти идет, вот и была идея быстро его зеркалить туда и обратно. Но видимо с битами - не судьба, предется массивом делать, там и зеркала не надо будет....
-
У процессора нет команд для работы с конкретными битами. Надо самому выковыривать нужный бит, сдвигами и логическими опеациями.
Поэтому, если необходимости нет, лучше оперировать байтами, словами и т.д. И код будет понятнее, и потом его модифицировать будет проще.
Еще минус 10 байт :) :
Mirror:
For I = 1 To 4
Cik = 9 - I
Swap Weekly(i) , Weekly(cik)
Next I
Return
-
:) Чувствуется программистская смекалка :)