jinfeng_wang

          G-G-S,D-D-U!

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

          公告

          歡迎交流鏈接,給我留言

          常用鏈接

          留言簿(40)

          隨筆分類(lèi)(592)

          隨筆檔案(400)

          Domestic

          Foreign

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          http://www.aygfsteel.com/Files/jinfeng_wang/Endian.rar


          Endian 
          介紹

          1.       Endian簡(jiǎn)介

          Endian可以看作是系統(tǒng)的一種屬性, 它指示多字節(jié)整數(shù)是從左向右放, 還是從右向左放. 它有兩種形式:

          ?           Big Endian

          ?           Little Endian

           

          BE把多字節(jié)整數(shù)的MSB(Most Significant Byte)存儲(chǔ)在最低的地址上, LSB(Least Significant Byte)順序存放在最高的地址上, LE正好相反.

           

          4-bytes數(shù)據(jù)0x01020304以?xún)煞N不同的方式存儲(chǔ)如下:

          00000001 00000010 00000011 00000100

          Address

          00

          01

          02

          03

          Big-Endian

          00000001

          00000010

          00000011

          00000100

          Little-Endian

          00000100

          00000011

          00000010

          00000001

           

          所有的處理器必須指定它用Big Endian還是Little Endian. Intel's 80x86 processor

          little endian. Sun's SPARC, Motorola's 68K, PowerPC系列是big endian. 有些處理器甚至設(shè)置了一個(gè)標(biāo)志位可以選擇所需要的Endian.

           

          2.       出現(xiàn)的問(wèn)題

          如果我們不了解Endian在數(shù)據(jù)存儲(chǔ)上的差異, 使用的時(shí)候就有可能出現(xiàn)問(wèn)題, 比如我們想要的是0x01020304,但是在little endian的情況下, 就有可能得到0x04030201.

          如何避免錯(cuò)誤的數(shù)據(jù)呢? 首先先看一下系統(tǒng)是如何存取數(shù)據(jù)的.


          下面是同一組數(shù)據(jù)在兩種endian下的memory dump:

          char              c1 = 1;
          char       c2 = 2;
          short     s  = 255; // 0x00ff
          long       l  = 0x11223344;

          Offset    :      Memory dump
          0x0000 :    
          01 02 00 FF
          0x0004 :     11 22 33 44

          A Big-Endian memory dump

           

          char              c1 = 1;
          char       c2 = 2;
          short     s  = 255; // 0x00ff
          long       l  = 0x11223344;

          Offset    :      Memory dump
          0x0000 :    
          01 02 FF 00
          0x0004 :     44 33 22 11

          A Little-Endian memory dump

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           

           


          上圖表示了數(shù)據(jù)的存放方式, 雖然s, l在兩種endina下的存儲(chǔ)方式不同, 但取出s, l的時(shí)候系統(tǒng)還是會(huì)還原成原來(lái)的值, 數(shù)據(jù)是不會(huì)改變的. 就是說(shuō)平常使用的過(guò)程中, 我們不必關(guān)心這種存取的過(guò)程.

           

          那么在什么情況下會(huì)造成數(shù)值的改變呢? 我們從存數(shù)據(jù)和取數(shù)據(jù)兩個(gè)方面進(jìn)行說(shuō)明

          2.1.      存數(shù)據(jù)

          有一些接口和規(guī)范規(guī)定了必須以某種Endian的格式進(jìn)行通訊, 大多數(shù)都規(guī)定以Big Endian的格式. 比如SCSI command數(shù)據(jù)的傳輸, TCP/IP網(wǎng)絡(luò)協(xié)議等.

                

                 下面是10 字節(jié)的Read command, CDB格式如下:

          Bit

          Byte

          Operation Code (28h)

          1

          Reserved

          ( 0 0 0 )b

          DPO

          FUA

          ( 0 )b

          Reserved

          ( 0 0 0 )b

          RelAdr ( 0 )b

          (MSB)

          LBA

           

          (LSB)

          Reserved  ( 00 h)

          (MSB)                                                         

           Transfer Length                        (LSB)

          Controller

           

           

          我們定義如下的結(jié)構(gòu)體填充.

          typedef struct cdb1tag

          {

                        uchar_t         opcode;

                        uchar_t         lun;

                        uint_t           lba;

                        uchar_t         rsv1;

                        ushort_t     block;

                        uchar_t         cntl;

          } CDB1;

           

          假設(shè)要發(fā)行一個(gè)Read操作, LBA0x01020304. Transfer Length255(0x00ff).

          我們需要對(duì)CDB進(jìn)行填充. 賦值:

          lba=0x01020304;              block=0x00ff;      …(其他參數(shù)不討論)

           

          下面我們看看賦值后Big EndianLittle Endian是怎樣存儲(chǔ)這段數(shù)據(jù)的:

           

          Byte

          (BIG_ENDIAN)

          0

           

          1

           

          (MSB)    01

          02

          03

          04    (LSB)

          6

           

          (MSB)    00            

                    ff    (LSB)

          9

           

          Byte

          (LITTLE_ENDIAN)

          0

           

          1

           

          (LSB)    04

          03

          02

          01    (MSB)

          6

           

          (LSB)     ff

                    00    (MSB)

          9

           

           

           

           


          2.2.      取數(shù)據(jù)

          同上面講到的, 如果規(guī)定了必須以某種Endian通訊, 則必須按照規(guī)定的順序把數(shù)據(jù)取出來(lái), 這種情況同存數(shù)據(jù)的例子, 只不過(guò)一個(gè)是存, 一個(gè)是取.

           

          union{

          char  c_num[4]; // 01 02 03 04
          int i_num;

          }dev;

          Offset    :      Memory dump

          0x0000 :     01 02 03 04

          i_num=  0x04030201 (LE)  :  0x01020304 (BE)

          另外, 不按照系統(tǒng)存儲(chǔ)的方式取數(shù)據(jù), 有時(shí)會(huì)發(fā)生意外. 比如說(shuō)我們是以一個(gè)字節(jié)一個(gè)字節(jié)存儲(chǔ)的數(shù)據(jù), 卻以4個(gè)字節(jié)為一組取出.

           

           

           

           

           

           

          不過(guò)有的數(shù)據(jù)比較特殊, 即使顛倒字節(jié)順序,  數(shù)值也不發(fā)生改變

          例如:     0  0x1111  0x01020201

           

          3.       解決方法

          ?           多字節(jié)數(shù)據(jù)以單字節(jié)寫(xiě)入/讀出

          IN:

          (unsigned char)((lba & 0Xff000000) >> 24)  à MSB

          (unsigned char)((lba & 0X00ff0000) >> 16)

          (unsigned char)((lba & 0X0000ff00) >> 8)

          (unsigned char) (lba & 0X000000ff)                à LSB

          OUT:

          endian_dump()

           

          ?           交換字節(jié) byte_swap()

           

          posted on 2007-05-28 15:08 jinfeng_wang 閱讀(686) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): cppZZ
          主站蜘蛛池模板: 蓬莱市| 咸丰县| 安岳县| 昌乐县| 巴马| 阿城市| 高清| 达日县| 汤阴县| 甘泉县| 辽源市| 夏邑县| 防城港市| 调兵山市| 怀化市| 东乡县| 泰宁县| 通榆县| 萝北县| 康保县| 探索| 永寿县| 新余市| 山阴县| 达州市| 宁阳县| 新源县| 莱芜市| 榆中县| 嘉祥县| 郴州市| 巴彦淖尔市| 内丘县| 石台县| 大姚县| 沙田区| 和静县| 兴隆县| 莎车县| 丽江市| 西和县|