全部博文(73)
分类: C/C++
2009-04-23 16:19:09
C中内嵌汇编进行字节序转换
前两天处理从网络上采集的数据,涉及到了对big-endian和litten-endian的转换,为了高效,同时正好那段
时间在看汇编与是用下面的例子来演示数据的大端与小端的区别,同时也告诉大家怎么将汇编嵌入到c中。
再对 big-endian和little-endian做个简明的解释:
little-endian 主机字节序 四个字节对称交换 低位在前高位在后
big-endian 网络字节序 四个字节顺序排列 高位在前低位在后
#include注意,这儿是个联合结构,主要是为了将一个长整型的数字(常见的也是4字节),以单字节的方式读取
#include
#include
#include
#include
#include
#include
#include
#include
//
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