Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 使用AVR反转字节中的位_Assembly_Bit Manipulation_Avr_Atmega - Fatal编程技术网

Assembly 使用AVR反转字节中的位

Assembly 使用AVR反转字节中的位,assembly,bit-manipulation,avr,atmega,Assembly,Bit Manipulation,Avr,Atmega,我目前正在解决一个问题,希望我构建一个子程序,将R16中的位反转 00000011 => 11000000 or 10101000 => 00010101 对于类,我们使用AVR子集,子例程需要在norfair中工作 这就是我目前所拥有的,任何帮助都将不胜感激 ldi r16,3 ;00000011 简单的解决方案是使用移位运算符循环位并检查。但是请注意,AVR没有偏移,所以它只能偏移1。这里有一个来自著名的bithacks页面 uint8\u t反向明显(uint8\u t v

我目前正在解决一个问题,希望我构建一个子程序,将R16中的位反转

00000011 => 11000000
or
10101000 => 00010101
对于类,我们使用AVR子集,子例程需要在norfair中工作

这就是我目前所拥有的,任何帮助都将不胜感激

ldi r16,3 ;00000011

简单的解决方案是使用移位运算符循环位并检查。但是请注意,AVR没有偏移,所以它只能偏移1。这里有一个来自著名的bithacks页面

uint8\u t反向明显(uint8\u t v)
{
uint8_t r=v&1;//r将是v的反向位;首先得到v的LSB
uint8_t s=sizeof(v)*字符位-1;//结束时需要额外移位
对于(v>>=1;v;v>>=1)
{   

r>1)|((x&0x55U)>2)|((x&0x33U)>4)|((x&0x0fU)您可以使用
rol
ror
操作码(通过进位左右旋转)

**未经测试,但应能正常工作;-)**


您还可以通过循环来改进这一点!

AVR有
swap
指令,允许在寄存器中交换4位半字节。您可以使用它来缩短代码

mov r17, r16
ror r16  // rotate right, pushing bit 0 out to C flag
rol r17  // rotate left, moving C flag into bit 0 and pushing bit 7 out to C flag
ror r16
rol r17
ror r16
rol r17
ror r16
rol r17
ror r16
andi r16, 0xF0 // isolating bit 4 to 7
andi r17, 0x0F // isolating bit 0 to 3
or r16, r17    // combining
swap r16       // swapping the nibbles

你能使用查找表吗?例如,对于4位的一半。在没有位反转指令的ISA上,这通常是最快的。我不这么认为。你对算法有什么想法吗?对于初学者来说,我建议你右移R16,找出它的末尾移动了什么位,然后左移一个临时寄存器并放置它位在最低有效位置。你能看到完成程序后要做什么吗?这是在一个字节中反转位,而不是在字节中反转位。让我更改标题说明AVR移位指令一次只能执行1位。因此,整个字节的256字节查找表是好的,但半半字节的16字节LUT需要要使用的移位。我猜对于低半部和高半部的2x 16字节表,您只需要4个移位、2个加载和一个OR即可使用,这比在CF+8x ADC中进行8x操作+循环开销要好。相同,也就是ROL reg。但这意味着使用
(x&0xf0U)的版本>>4
等在AVR.IDK上可能很糟糕,如果你能说服编译器将代码移到CF并移回另一个寄存器。但这显然至少是实际操作的两倍,并且在移位之间有1和或另一个寄存器。如果还需要一个MOV来复制一个寄存器,则可能是3倍。@PeterCordes AVR一个
swap
指令,因此它可以用作快速移位4,如果您打开中的godbolt链接,编译器就会这样做。对于上面的第一个解决方案,编译器实际上不使用CF,而是使用一对SBRC/ORI,这对SBRC/ORI在每个SBRC/ORI之前/之后使用
mov
,但是对于带有
掩码的SBRC/ORIde>和
up
。这可能是一个遗漏的优化;我还没有摸索它在做什么。理想的情况是
mov r18,r24
然后8x
lsr r18
/
rol r24
/
ret
来实现该功能。感谢您指出
swap
;有这样的说明是有意义的。更难理解第二,但似乎有效。赢得3个周期也(14而不是17)。
mov r17, r16
ror r16  // rotate right, pushing bit 0 out to C flag
rol r17  // rotate left, moving C flag into bit 0 and pushing bit 7 out to C flag
ror r16
rol r17
ror r16
rol r17
ror r16
rol r17
ror r16
andi r16, 0xF0 // isolating bit 4 to 7
andi r17, 0x0F // isolating bit 0 to 3
or r16, r17    // combining
swap r16       // swapping the nibbles