找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3813|回复: 28
打印 上一主题 下一主题
收起左侧

1个字节数据 怎么把高八位和低八位对称换位?

  [复制链接]
跳转到指定楼层
楼主
ID:1030798 发表于 2023-4-29 19:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
比如1000 0000变成0000 0001
1100 0101变成1010 0011
这样对称换位,大佬们
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:235200 发表于 2023-4-30 00:31 | 只看该作者
数据存dat1,换位结果存dat2
for (i=0;i<8;i++)
{
   j=(bit)(dat1&0x80);
    if (j)
       dat2=dat2+0x80;
    dat1=dat1<<1;
    dat2=dat>>1;
}
回复

使用道具 举报

板凳
ID:1074756 发表于 2023-4-30 09:10 来自手机 | 只看该作者
在C语言中,可以使用位运算符对二进制数进行位反转操作。  对于将二进制数1100 0101变成1010 0011,可以这么实现:  c unsigned char x = 0xC5; // 将16进制数0xC5赋值给无符号字符变量x x = ((x & 0x55) << 1) | ((x & 0xAA) >> 1); // 与0x55做与操作得到奇数位,与0xAA做与操作得到偶数位,然后将奇偶位的结果进行交换 x = ((x & 0x33) << 2) | ((x & 0xCC) >> 2); // 与0x33做与操作得到8位中的4位一组的左侧4位,与0xCC做与操作得到右侧4位,然后将每组4位的位置互换 x = ((x & 0x0F) << 4) | ((x & 0xF0) >> 4); // 与0x0F做与操作得到低4位,与0xF0做与操作得到高4位,然后将低高位的结果进行交换 最终得到的x的值为十六进制数0xA3,即二进制数1010 0011
回复

使用道具 举报

地板
ID:1030798 发表于 2023-4-30 09:26 来自手机 | 只看该作者
csmyldl 发表于 2023-4-30 00:31
数据存dat1,换位结果存dat2
for (i=0;i

大佬我能说没看懂吗
回复

使用道具 举报

5#
ID:883242 发表于 2023-4-30 09:47 | 只看该作者
召唤兽 发表于 2023-4-30 09:10
在C语言中,可以使用位运算符对二进制数进行位反转操作。  对于将二进制数1100 0101变成1010 0011,可以这 ...

是的,hacker's delight这本书第7章说的就是这种蝶形算法。
回复

使用道具 举报

6#
ID:420836 发表于 2023-4-30 09:49 | 只看该作者
要将高位位置与低位位置交换,您可以使用以下代码并获得二进制格式。
char new_byte;
bool new_bit[8];
char byte1;
bool bit[8];
for(int i= 0; i<8; i++)
{
        bit[i] = ((byte1>>i) & 0x01);
        new_bit[7-i] = bit[i];
}
如果要获取新字节,请使用以下代码:
unsigned int bitsToBytes(unsigned char *bits)
{
  unsigned int sum = 0;
  for (int i = 0; i < 8; i++)
  {
    sum += bits[i] - '0';
    sum<<=1;
  }
  return sum;

}

new_byte = bitToByte(*new_bit);
回复

使用道具 举报

7#
ID:277550 发表于 2023-4-30 10:37 | 只看该作者
这样


#include<stdio.h>

int main(int argc, char*argv[]){
        unsigned char a=0xab, b;
       
        printf("%02x\r\n", a);

        b = (a>>4)&0xf;
        a = (a<<4) | b;         //这2行

        printf("%02x\r\n", a);

        return 0;
}
回复

使用道具 举报

8#
ID:277550 发表于 2023-4-30 10:58 | 只看该作者
上一帖确实看错,不管管理员确认了,直接补一楼


#include<stdio.h>

void printBin(unsigned char a){
        int i;
        for(i=0; i<8; i++){
                printf("%d", a&0x80?1:0);
                a=a<<1;
        }
}

int main(int argc, char*argv[]){
        unsigned char a=0xab, b, i, j;
        for(i=0x79; i<0x8f; i++){//测试几个数,看结果是否对
                a=i;
                printBin(a);
                printf(" ");
        }
        printf("\r\n");
       
        for(i=0x79; i<0x8f; i++){
                a=i;
               
                //对称调换---begin
                b=0;
                for(j=0; j<8; j++){
                        b=b | ((a&1)<<(7-j)) ;
                        a=a>>1;
                }                                       
                //对称调换---end
                printBin(b);
                printf(" ");
        }
        printf("\r\n\r\n");
       
       
        //=================================
        a=0xab;
        printf("%02x\r\n", a);
        b=(a>>4) | (a<<4);  //高低对调
        printf("%02x\r\n", b);
       
        return 0;
}


// http://www.51hei.com/bbs/dpj-228623-1.html
//VC2008测试过。
回复

使用道具 举报

9#
ID:291668 发表于 2023-4-30 11:02 | 只看该作者
先做高低字节交换,再按位取反。
回复

使用道具 举报

10#
ID:1034262 发表于 2023-4-30 11:45 | 只看该作者
查表最快
回复

使用道具 举报

11#
ID:491577 发表于 2023-4-30 13:19 | 只看该作者
用二楼的程序简化一下:
数据存dat1,换位结果存dat2
dat2=0; //开始要先清零
for (i=0;i<8;i++)
{
    if (dat1&0x80)  //判断dat1最高位是否=1
    dat2=dat2+1;  //如果dat1最高位=1,将dat2最低位+1,相当于将dat1高位移到dat2低位。
    dat1=dat1<<1;
    dat2=dat2<<1;
}
回复

使用道具 举报

12#
ID:163285 发表于 2023-4-30 15:25 | 只看该作者
分别提取各位,然后用堆栈。
回复

使用道具 举报

13#
ID:57657 发表于 2023-4-30 16:41 | 只看该作者
查表浪费内存空间,循环语句浪费时间,还是Verilog划算:
  1. module main(                                //对称换位模块
  2.         input [7:0] in,                //[8位宽]输入
  3.         output [7:0] out                //[8位宽]输出

  4. );
  5. genvar i;
  6. generate
  7. for(i=0;i<8;i=i+1) begin:gen
  8.         assign out[i] = in[7-i];
  9. end
  10. endgenerate
  11. endmodule
复制代码
回复

使用道具 举报

14#
ID:213173 发表于 2023-4-30 16:48 | 只看该作者
写一个简单函数,容易理解些。
unsigned char Conversion(unsigned char dat)
{
        unsigned char i,temp;
        for(i=0;i<8;i++)
        {
                temp|=((dat&0x01)<<(7-i));
                dat>>=1;
        }
        return temp;
}
回复

使用道具 举报

15#
ID:688692 发表于 2023-4-30 22:23 | 只看该作者
老问题了,论坛有讨论过这个,8位查表速度最快,移位蝶形也不见得省程序空间(可以自己对比一下编译出来的code空间和跑完函数花的机器周期state),4位查表综合代码长度和执行速度折中最好。
回复

使用道具 举报

16#
ID:73992 发表于 2023-4-30 23:39 | 只看该作者
将值存入位寻址区,然后cy取位。acc移位。以 51为例
mov 20h,#00110110b  //假设值为00110110b
mov cy,07h   //20h最高位
RR a        //ACC右移
mov cy,06h   //20h次高位
RR a        //ACC右移
.......      ..........
八次过后,结果存在acc中。 嵌入到C语言中
回复

使用道具 举报

17#
ID:491577 发表于 2023-5-1 01:14 | 只看该作者
npn 发表于 2023-4-30 16:41
查表浪费内存空间,循环语句浪费时间,还是Verilog划算:

Verilog还没有了解过,要认真学习一下。不过下面的语句好像也是循环:
for(i=0;i<8;i=i+1) begin:gen
        assign out = in[7-i];
回复

使用道具 举报

18#
ID:57657 发表于 2023-5-1 08:15 | 只看该作者
hhh402 发表于 2023-5-1 01:14
Verilog还没有了解过,要认真学习一下。不过下面的语句好像也是循环:
for(i=0;i

Verilog是一种并行语言,与串行语言不同,这里的循环是将8根导线接上。
回复

使用道具 举报

19#
ID:989772 发表于 2023-5-1 08:31 | 只看该作者
   int dat1 = 0xc5;
   int dat2 = 0;
   for(int l=0, d4 =128; l<8; l++ )
   {   
           dat2 += dat1%2*d4;
           dat1/=2;
           d4/=2;          
   }
回复

使用道具 举报

20#
ID:1030798 发表于 2023-5-2 13:46 | 只看该作者
wulin 发表于 2023-4-30 16:48
写一个简单函数,容易理解些。
unsigned char Conversion(unsigned char dat)
{

如果是0xAA他就不行呀
回复

使用道具 举报

21#
ID:883242 发表于 2023-5-2 15:02 | 只看该作者
cnos 发表于 2023-4-30 22:23
老问题了,论坛有讨论过这个,8位查表速度最快,移位蝶形也不见得省程序空间(可以自己对比一下编译出来的c ...

蝶形算法在32位机对换32位数据的高低位还是很有性价比的,楼主连自己的单片机型号什么的都不说,谁也没法猜出最佳方案,大家散了吧。
回复

使用道具 举报

22#
ID:213173 发表于 2023-5-2 15:14 | 只看该作者
231244234 发表于 2023-5-2 13:46
如果是0xAA他就不行呀

0xAA转换后0x55,你没有验证怎么说不行?
回复

使用道具 举报

23#
ID:1073399 发表于 2023-5-2 23:02 | 只看该作者
  1. unsigned char swapBits(unsigned char data)
  2. {
  3.   return ((data >> 4) & 0x0F) | ((data << 4) & 0xF0);
  4. }
复制代码
这里使用了右移和左移操作来将高八位和低八互换位置。首先将数据向高四清,只低四位的数据。然后再将数据向左移动4位(低四位移到高四位),与0xF0进行按位与运算,将低四位清零,只留下高四位的数据。最后将这两位或运算合并起来,就完成了高八位和对称互换位置的操作。
回复

使用道具 举报

24#
ID:491577 发表于 2023-5-2 23:41 | 只看该作者
23楼的转换错了吧,楼主意思是ABCDEFG变成GFEDCBA。不是高四位与低四位互换。
回复

使用道具 举报

25#
ID:401564 发表于 2023-5-3 19:59 | 只看该作者
什么代码简单,容易理解,就用这个代码,什么占内存,速度快的.压根就不需要考虑
我公司之前用的是512B内存的单片机,随便写点代码就用完了
我也曾经想过所谓的"优化代码"
折腾了好久,才发现,1K内存单片机的价格仅仅高了一分钱而已
得多少量才把这1分钱省回来呀,干脆就不折腾了,直接换1K的
回复

使用道具 举报

26#
ID:77589 发表于 2023-5-4 11:57 | 只看该作者
Y_G_G 发表于 2023-5-3 19:59
什么代码简单,容易理解,就用这个代码,什么占内存,速度快的.压根就不需要考虑
我公司之前用的是512B内存的 ...

有道理!!!!!!!!!
回复

使用道具 举报

27#
ID:1073939 发表于 2023-5-4 15:30 | 只看该作者
wulin 发表于 2023-4-30 16:48
写一个简单函数,容易理解些。
unsigned char Conversion(unsigned char dat)
{

你的代码改成这样,效率更高。
  1. unsigned char Conversion(unsigned char dat)
  2. {
  3.     unsigned char i, r = 0;
  4.     for (i = 0; i < 8; i++)
  5.     {
  6.         r <<= 1;
  7.         r += dat & 0x01;
  8.         dat >>= 1;
  9.     }
  10.     return r;
  11. }
复制代码
回复

使用道具 举报

28#
ID:1074495 发表于 2023-5-4 15:48 | 只看该作者
用汇编的话,直接选择带进位的左右循环,CY标志位做中转站就可以

      
回复

使用道具 举报

29#
ID:824490 发表于 2023-5-5 11:36 | 只看该作者
召唤兽 发表于 2023-4-30 09:10
在C语言中,可以使用位运算符对二进制数进行位反转操作。  对于将二进制数1100 0101变成1010 0011,可以这 ...

好一只漂亮、轻灵的蝴蝶!!
学习了~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表