Chinaunix首页 | 论坛 | 博客
  • 博客访问: 192485
  • 博文数量: 73
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 1160
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 15:53
文章分类

全部博文(73)

文章存档

2011年(1)

2009年(72)

我的朋友

分类: C/C++

2009-04-23 16:19:09

C中内嵌汇编进行字节序转换
 
前两天处理从网络上采集的数据,涉及到了对big-endianlitten-endian的转换,为了高效,同时正好那段

时间在看汇编与是用下面的例子来演示数据的大端与小端的区别,同时也告诉大家怎么将汇编嵌入到c中。

再对 big-endianlittle-endian做个简明的解释:

little-endian   
主机字节序      四个字节对称交换     低位在前高位在后

big-endian      
网络字节序      四个字节顺序排列     高位在前低位在后



#include
#include
#include
#include
#include
#include
#include
#include
#include

//
注意,这儿是个联合结构,主要是为了将一个长整型的数字(常见的也是4字节),以单字节的方式读取

typedef union

{

        long Long;

        char Char[sizeof(long) ];

}ByteOrder;


ByteOrder u;

ByteOrder n;


//
下面的函数利用C中内嵌的汇编代码将little-endian转为big-endian,再转为little-endian

int main()

{

//      ByteOrder u;

        u.Long = 1;



        printf( "the lenght of long type data %d\n", sizeof( long ) );

        if ( u.Char[ 0 ] == 1 )

        {

               printf( "!!right-to-left\n" );

        }

        else if ( u.Char[ sizeof(long) - 1 ] == 1 )

        {

               printf( "!!left-to-right\n" );

        }

#if 1

        //
下面的方法利用扩展asm格式:asm( "assembly code":output:input:changed regiested);

        asm( "bswap %1\n\t"

                "movl %1, %0\n\t"

                :"=m"(n):"a"(u) );    //"="
表示只能写入操作数,可以从寄存器和内存位置给输入/出值赋值

                               //n,u
不要求是全局的(当然,在这儿的确是全局的:-) )

#endif

       

        if ( n.Char[ 0 ] == 1 )

        {

               printf( "##right-to-left\n" );

        }

        else if (n.Char[ sizeof(long) - 1 ] == 1 )

        {

               printf( "##left-to-right\n" );

        }



#if 1

        //"voliatile"
关键字禁止对内联汇编代码的优化

        asm volatile (

                                "pusha\n\t"   //
保存环境

                                "movl n, %eax\n\t"    //
将内存中的值放读入寄存器,n必须为全局变量,才能这样用

                                "bswap %eax\n\t"      //
对寄存器中的值进行swap操作

                                "movl %eax, u\n\t"    //
将结果保存到内存中,u必须为全局变量才能这样用

                                "popa"                //
恢复环境

                                );

#endif



        if ( u.Char[ 0 ] == 1 )

        {

               printf( "@@right-to-left\n" );

        }

        else if ( u.Char[ sizeof(long) - 1 ] == 1 )

        {

               printf( "@@left-to-right\n" );

        }

        return 0;

}

输出:
dongq@DongQ_Lap ~/workspace/test/byteOrder $ ./run

the lenght of long type data 4

!!right-to-left     //
判断发现是little-endian

##left-to-right  //
转为big-endian

@@right-to-left   //
转回little-endian

 

阅读(1177) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~