2 MDenis, Romario, ReAl и остальным участникам недавней дискуссии Занятно было почитать и послушать треск ломающихся копий. Ради забавы накидал решение распаковочной задачки Romario в двух вариантах - рекурсивном и инлайн - на Атмеловском ассемблере AVR. Компиляторы в очередной раз утерлись рукавом:
;Input = 0:aaaaaaab 1:bbbbbbcc 2:cccccddd 3:ddddeeee 4:eeefffff 5:ffgggggg 6:ghhhhhhh
;Output = 0:0aaaaaaa 1:0bbbbbbb 2:0ccccccc 3:0ddddddd 4:0eeeeeee 5:0fffffff 6:0ggggggg 7:0hhhhhhh
;30 bytes, 84 cycles (5.25 uS @16 MHZ)
unpack_recursive:
ldi ZH,high(iter1) ;Initialize iteration entry address pointer
ldi ZL,low(iter1)
ldi r24,low(it_lim) ;Set recursion limit checkpoint
; Iter.1 Iter.2 Iter.3 Iter.4 Iter.5 Iter.6 Iter.7 Iter.8
iter1: lsr r16 ;0aaaaaaa --//-- --//-- --//-- --//-- --//-- --//-- --//--
iter2: ror r17 ;bbbbbbbc 0bbbbbbb --//-- --//-- --//-- --//-- --//-- --//--
iter3: ror r18 ;ccccccdd cccccccd 0ccccccc --//-- --//-- --//-- --//-- --//--
iter4: ror r19 ;dddddeee ddddddee ddddddde 0ddddddd --//-- --//-- --//-- --//--
iter5: ror r20 ;eeeeffff eeeeefff eeeeeeff eeeeeeef 0eeeeeee --//-- --//-- --//--
iter6: ror r21 ;fffggggg ffffgggg fffffggg ffffffgg fffffffg 0fffffff --//-- --//--
iter7: ror r22 ;gghhhhhh ggghhhhh gggghhhh ggggghhh gggggghh gggggggh 0ggggggg --//--
iter8: ror r23 ;h0000000 hh000000 hhh00000 hhhh0000 hhhhh000 hhhhhh00 hhhhhhh0 0hhhhhhh
it_lim: adiw ZH:ZL,1 ;Advance iteration entry pointer
cpse ZL,r24 ;Check for recursion limit, exit if reached
ijmp ;Do next iteration (iter+1) recursively
ret
;Input = 0:aaaaaaab 1:bbbbbbcc 2:cccccddd 3:ddddeeee 4:eeefffff 5:ffgggggg 6:ghhhhhhh
;Output = 0:0aaaaaaa 1:0bbbbbbb 2:0ccccccc 3:0ddddddd 4:0eeeeeee 5:0fffffff 6:0ggggggg 7:0hhhhhhh
;74 bytes, 40 cycles (2.5 uS @16 MHZ)
unpack_inline:
; Iter.1
lsr r16 ;0aaaaaaa
ror r17 ;bbbbbbbc
ror r18 ;ccccccdd
ror r19 ;dddddeee
ror r20 ;eeeeffff
ror r21 ;fffggggg
ror r22 ;gghhhhhh
ror r23 ;h0000000
; Iter.2
lsr r17 ;0bbbbbbb
ror r18 ;cccccccd
ror r19 ;ddddddee
ror r20 ;eeeeefff
ror r21 ;ffffgggg
ror r22 ;ggghhhhh
ror r23 ;hh000000
; Iter.3
lsr r18 ;0ccccccc
ror r19 ;ddddddde
ror r20 ;eeeeeeff
ror r21 ;fffffggg
ror r22 ;gggghhhh
ror r23 ;hhh00000
; Iter.4
lsr r19 ;0ddddddd
ror r20 ;eeeeeeef
ror r21 ;ffffffgg
ror r22 ;ggggghhh
ror r23 ;hhhh0000
; Iter.5
lsr r20 ;0eeeeeee
ror r21 ;fffffffg
ror r22 ;gggggghh
ror r23 ;hhhhh000
; Iter.6
lsr r21 ;0fffffff
ror r22 ;gggggggh
ror r23 ;hhhhhh00
; Iter.7
lsr r22 ;0ggggggg
ror r23 ;hhhhhhh0
; Iter.8
lsr r23 ;0hhhhhhh
ret
Для желающих проверить в работе - инициализация и вызов функции. После выполнения в соответствующем месте RAM появится слово "Keyboard" в ASCII-виде:
ldi r16,$FF&('K' << 1)|('e' >> 6)
ldi r17,$FF&('e' << 2)|('y' >> 5)
ldi r18,$FF&('y' << 3)|('b' >> 4)
ldi r19,$FF&('b' << 4)|('o' >> 3)
ldi r20,$FF&('o' << 5)|('a' >> 2)
ldi r21,$FF&('a' << 6)|('r' >> 1)
ldi r22,$FF&('r' << 7)|('d' >> 0)
ldi r23,0
rcall unpack_recursive
; rcall unpack_inline
foo:
rjmp foo