Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1514474
  • 博文数量: 129
  • 博客积分: 1449
  • 博客等级: 上尉
  • 技术积分: 3048
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 18:36
文章分类

全部博文(129)

文章存档

2015年(3)

2014年(20)

2013年(65)

2012年(41)

分类: LINUX

2012-08-01 08:13:58

小端存储:较高的有效字节存放在较高的的存储器地址,较低的有效字节存放在较低的存储器地址。
大端存储:较高的有效字节存放在较低的存储器地址,较低的有效字节存放在较高的存储器地址。以前常用的卡上存储数据即此. !!!!
如果将一个16位的整数0x1234存放到一个短整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示。
地址偏移 大端模式 小端模式
0x00 12(OP0) 34(OP1)
0x01 34(OP1) 12(OP0)
bool IsBig_Endian()
{
unsigned short test = 0x1234;
if(*( (unsigned char*) &test ) == 0x12)
  return TRUE;
else
  return FALSE;
}//IsBig_Endian()

//0x12, htons = 0x1200, htonl = 0x12000000
bool IsLittle_Endian(void)
{
static union {
char c[4];
unsigned long l;
} endian_test = { { 'l','?','?','b' } };
u8 ucTmp = (char)endian_test.l;

if (ucTmp == 'b') {
   return(_FALSE);
}
else if(ucTmp == 'l') {
   return(_TRUE);
}
}
成员变量c和l公用一段内存,当系统为32位系统时,unsigned long类型占4个字节,char为一个字节
我们假设从左到右内存地址依次增高,那么'l', '?', '?', 'b' 这四个字符在不同的系统将会这样放置:
'l','?', '?', 'b' ------ 小端(little-endian)系统(低低模式,即低字节放在低地址)
'b','?', '?', 'l' ------ 大端(big-endian)系统(高低模式,即高字节放在低地址)
那么宏中的这条语句((char)endian_test.l)很明显是取long变量的第一个字节

VC中文件中读写多字节时, 低字节在前(低地址),高字节在后(高地址, 小端模式). UE中查看此文件: 78 56 34 12
FILE *fp = NULL;
unsigned long ulData = 0x12345678;
fp = fopen("filetest(0x12345678).dat", "w+");
fwrite(&ulData, sizeof(long), 1, fp);
fclose(fp);

//判断起始地址, 原值 = 0x000080F1, 按字节读取后的判断
if ( (ReadData[4] != 0xf1) || (ReadData[5] != 0x80) || (ReadData[6] != 0x00) || (ReadData[7] != 0x00) ){
sprintf(pcStr, "%02X %02X %02X %02X", ReadData[4], ReadData[5], ReadData[6], ReadData[7]);
MessageBox(pcStr, "File Data Invalid", MB_ICONSTOP);
  return;
}

--- u-boot:
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
# else
#  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
# endif

--- LWIP中参考
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif

#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif

#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif

#if BYTE_ORDER == LITTLE_ENDIAN
  u8_t *lsb_ptr = (u8_t*)value;
#endif
#if BYTE_ORDER == BIG_ENDIAN
  u8_t *lsb_ptr = (u8_t*)value + sizeof(s32_t) - 1;
#endif

#if (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN)
u16_t htons(u16_t n)
{
  return ((n & 0xff) << 8) | ((n & 0xff00) >> 8);
}

u16_t ntohs(u16_t n)
{
  return htons(n);
}

u32_t htonl(u32_t n)
{
  return ((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000UL) >> 8) | ((n & 0xff000000UL) >> 24);
}

u32_t ntohl(u32_t n)
{
  return htonl(n);
}
#endif /* (LWIP_PLATFORM_BYTESWAP == 0) && (BYTE_ORDER == LITTLE_ENDIAN) */

void GetIP(char *pucBuf)
{
  unsigned long ulIPAddress;
  unsigned char *pucTemp;
  //unsigned char pucTemp[4];

  ulIPAddress = lwIPLocalIPAddrGet(); //获取IP;
  DEBUGP("ulIPAddress = 0x%08X\n", ulIPAddress);

#if 1
  pucTemp = (unsigned char *)&ulIPAddress;
  usprintf(pucBuf, "%d.%d.%d.%d", pucTemp[0], pucTemp[1], pucTemp[2], pucTemp[3]);
  //ulIPAddress = 0x9608A8C0, IP = 192.168.8.150. pucTemp[0]为低地址数据, pucTemp[3]为高地址数据.

#else
  pucTemp[0] = (ulIPAddress >> 24) & 0xff;
  pucTemp[1] = (ulIPAddress >> 16) & 0xff;
  pucTemp[2] = (ulIPAddress >>  8) & 0xff;
  pucTemp[3] = (ulIPAddress >>  0) & 0xff;
  sprintf(pucBuf, "%d.%d.%d.%d", pucTemp[0], pucTemp[1], pucTemp[2], pucTemp[3]);
  //ulIPAddress = 0x9608A8C0, IP = 150.8.168.192
#endif
}

//网际协议在处理多字节整数时使用, 大端字节序. 如: 192.168.8.9, 192为高字节在低地址
#define IP4ADDR(ipaddr, a,b,c,d) *ipaddr = (((u32)((d) & 0xff) << 24) | ((u32)((c) & 0xff) << 16) | \
                    ((u32)((b) & 0xff) << 8)  | ((u32)((a) & 0xff)) )
void ByteOrderTest(void)
{
  u32 ulIPAddress;
  unsigned char *pucTemp;

  IP4ADDR(&ulIPAddress, 192, 168, 8, 9);
  pucTemp = (unsigned char *)&ulIPAddress;
DEBUGP("0x%08X = %d.%d.%d.%d\n", ulIPAddress, pucTemp[0], pucTemp[1], pucTemp[2], pucTemp[3]);
//0x0908A8C0 = 192.168.8.9
}

htonl(): 本函数将一个32位无符号数数从主机字节顺序转换成网络字节顺序。
网际协议在处理多字节整数时, 使用大端字节序。在主机本身就使用大端字节序时, 这些函数通常被定义为空宏。
  在Linux系统下:
  #include
  uint32_t htonl(uint32_t hostlong);
  hostlong:主机字节顺序表达的32位数。
  返回值:htonl()返回一个网络字节顺序的值。

  相关函数:
  uint16_t htons(uint16_t hostshort);
  uint32_t ntohl(uint32_t netlong);
  uint16_t ntohs(uint16_t netshort);
阅读(1527) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~