日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈大小端(Endian)与位域

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈大小端(Endian)与位域 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

字節序

位序

常見位序的錯誤理解

以太網的大小端

以太網的字節序

以太網的位序

位域中的大小端

位域遇上大小端以太網通信

大端CPU發送

小端CPU發送

位域大小端問題的解決措施


大小端問題浪費了太多應用、驅動、邏輯工程師太多的時間,無時無刻都有人正在被大小端坑,正好比此時的我在浪費時間談論大小端。

如果學過計算機原理、編程等知識,都知道課本里對大小端的一段描述:

小端模式:數據的高字節,存放在高地址中。計算機讀取數據的方向,是從高地址開始讀取的;
大端模式:數據的高字節,存放在低地址中。計算機讀取數據的方向,是從低地址開始讀取的;

注意這里只提到了字節序,并未提及到位序問題。

常見大小端CPU如下:

大端cpu:PowerPC

小端cpu:x86、arm(內核支持大端但從未見過大端)

注:

·MSB/LSB:

????????用于描述寄存器的各個位域含義時:MSB(Most Significant Bit 最高有效),LSB(Least Significant Bit 最低有效)。0b10010100,無論在大端還是小端機中,MSB為1,LSB為0。

????????用于描述整形數據時:指數學層面的高權重字節與低權重字節,如0x12345678,無論在大端還是小端機中,MSB都是指的0x12,LSB指0x78。

·Big Endian/Little Endian:指兩種端序。

·用[a:b]的方式表示多個bit位,如:[3:0]表示bit3?bit2 bit1?bit0,[0:3]表示bit0?bit1?bit2 bit3。

·為了視覺效果會把0寫成00,把1寫成01。

·文章中提到的高位低位均指內存或寄存器的地址的高位與低位,如果是數字的高字節與低字節,會強調為數學概念高權重的位與低權重的位,以防止教科書上的數字字節、存儲器字節傻傻分不清楚。


字節序

從字節序的視角一個多字節數0x12345678。

存放在大端CPU的RAM時: Byte0????????Byte1????????Byte2????????Byte3 0x12 ????????0x34? ? ? ? 0x56 ????????0x78存放在小端CPU的RAM時: Byte3????????Byte2????????Byte1???????Byte0 0x12 ????????0x34? ? ? ? 0x56 ???????0x78

位序

?從位序的視角看一個單字節數0x12。

存放在大端CPU的RAM時,[0:7] = 0x12(0b00010010): bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7 0? ? 0? ??0?? ?1 ? ?0? ??0? ? 1? ?0存放在小端CPU的RAM時,[7:0] = 0x12(0b00010010): bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0? ?0? ??0?? ?1? ??0? ??0?? ?1 ? ?0

?從位序的視角看一個多字節數0x12345678。

存放在大端CPU的RAM時,[0:31] = 0x12345678(0b0001 0010 0011 0100 0101 0110 0111 1000) bit: 00 01 02 03? ?04 05 06 07? ?08 09 10 11? ?12 13 14 15? ?16 17 18 19? ?20 21 22 23? ?24 25 26 27? ?28 29 30 31 val:? 0? 0? 0? 1? ??0??0??1??0? ?0? 0??1??1 ? ?0 ?1??0 ?0? ? 0? 1? 0??1?? ?0 ?1??1? 0? ??0??1? 1??1?? ?1? 0??0??0存放在小端CPU的RAM時,[31:0] = 0x12345678(0b0001 0010 0011 0100 0101 0110 0111 1000) bit: 31 30 29 28? ?27 26 25 24? ?23 22 21 20? ?19 18 17 16? ?15 14 13 12? ?11 10 09 08? ?07 06 05?04? ?03 02 01 00 val:? 0? 0??0 ?1? ?0? 0? 1??0? ?0 ?0??1??1? ?0 ?1??0??0? ??0? 1??0? 1? ?0??1? 1??0 ? ?0??1??1 ?1 ? ?1??0??0 ?0

常見位序的錯誤理解

如果不知道位序這個概念,很可能會把多字節在RAM中存儲的順序弄錯,如對多字節數0x12345678的錯誤理解

在大端系統中,存儲順序錯理解為: bit:??07 06 05?04? ?03 02 01 00 ?15 14 13 12? ?11 10 09 08? ?23 22 21 20? ?19 18 17 16? ?31 30 29 28? ?27 26 25 24 val:? 0? 0? 0? 1? ??0??0??1??0? ?0? 0??1??1 ? ?0 ?1??0 ?0? ? 0? 1? 0??1?? ?0 ?1??1? 0? ??0??1? 1??1?? ?1? 0??0??0在小端系統中,存儲順序錯理解為: bit: 24 25 26 27? ?28 29 30 31? ?16 17 18 19? ?20 21 22 23? ?08 09 10 11? ?12 13 14 15? ?00 01 02 03? ?04 05 06 07 val:? 0? 0??0 ?1? ?0? 0? 1??0? ?0 ?0??1??1? ?0 ?1??0??0? ??0? 1??0? 1? ?0??1? 1??0 ? ?0??1??1 ?1 ? ?1??0??0 ?0

以太網的大小端


以太網的字節序

無論大端CPU還是小端CPU,一定是先收發低字節,再收發高字節。


以太網的位序

參考文章:Ethernet下字節序和bit序的總結_shaohui973的博客-CSDN博客_bit0和bit7的順序,根據個人理解有所修改。(由于筆者未專門研究以太網物理層邏輯,若文章中存在錯誤,請一定要幫忙指出)

網絡接口要遵從的一個原則:在發送bit數據的時候,先發送MSB,最后發送LSB,即最先發送數學層面上權重最大的位,即最左邊的bit數據;接收bit數據的時候,先收到MSB,最后收到LSB,即將最先收到的bit數據,移位存儲到數學層面上權重最大的位所在存儲器中,即最左邊的bit中。在計算機中表現如下:(注意此處提到的MSB和LSB并非存儲意義上的大小端,而是數字層面上高位與低位,權重高的為高位,權重低的為低位。計算機的存儲空間并不存在上下左右,此處的“左邊”,指人類對數字或地址的書寫習慣上的描述,如數字0x112233中,0x11就是該數字權重最高的字節,位于最左邊)

在大端系統中,網卡發送bit數據bit[0:7] = 0x55(0b01010101)時,依次發送bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7,即發送01010101。

在小端系統中,網卡發送bit數據bit[7:0] = 0x55(0b01010101)時,依次發送bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0,即發送01010101。

在大端系統中,網卡收到bit數據時,依次存放在bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7,得到數據bit[0:7] = 0x55(0b01010101) 。

在小端系統中,網卡收到bit數據時,依次存放在bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0,得到數據bit[7:0] = 0x55(0b01010101)。

同樣是以太網發送端口,在大端系統與小端系統中邏輯電路設計并不相同,才能滿足大小端系統通信發送的數據和收到的數據值相同的基本要求。

不僅以太網接口原理如此,很多單通道串行通信都是如此,在大端系統與小端系統中收發的位序并不相同,在這些標準通信協議規范中提到的先發送高位中的“位”并不是指地址的位,而是數字含義中的位置,這里的高位指高權重的數字位,即左邊的值。


位域中的大小端

在寄存器定義、通信協議中經常會看到位域定義,在C/C++的結構體中可定義與之對應的位域結構體,以方便解析及組包。位域定義方式如下:

struct 位域結構名?
{
? ? type [member_name] : width ;
};

本文為了方便,將存儲到同一個標準數據類型的所有成員稱為一個域,同一個域內的成員稱為域成員。如下面的結構體中a1和a2屬于同一個域,a1和a2是這個域的域成員;b1、b2、b3、b4屬于同一個域,b1、b2、b3、b4是這個域的域成員;

有如下C/C++結構體struct st1及變量data:

struct st1 {uint8_t? a1 : 2;uint8_t? a2 : 6;uint16_t b1 : 3;uint16_t b2 : 4;uint16_t b3 : 5;uint16_t b4 : 4; };struct st1 data ={.a1 = 0x1,.a2 = 0x3,.b1 = 0x4,.b2 = 0x8,.b3 = 0xb,.b4 = 0x3 };

結構體成員.a1和.a2屬于同一個域,域大小為8bit。.b1、.b2、.b3、.b4屬于同一個域,域大小為16bit。

域的定義一般要遵循如下原則:域大小可以是8/16/32/64bit,域之間不可交叉,域的所有成員總大小必須等于所屬域大小,必要時加入保留(reserved)位來填補。

C/C++的結構體有一個規定,無論大端還是小端,先定義的成員一定是低字節和低位。

在大端系統中,結構體變量及其成員的存儲情況如下:

? ? ? ? .a1? ? ? ?? ?.a2? ? ? ???? ?.b1? ? ? ? ?.b2? ?? ? ? ?.b3? ? ? ? ?.b4 bit? ? ? [00:01]? ? ?[02:07]? ? ? ? ?[08:10]? ? ? [11:14]? ? ? [15:19]? ? ? [20:23] data? ?01? ? ? ? ? 000011? ? ? ? 100? ?? ? ? ?1000? ? ? ? ?01011? ? ? ?0011.a1[0:1] = 0b01(0x1); .a2[0:5] = 0b000011(0x3); .b1[0:2] = 0b100(0x4); .b2[0:3] = 0b1000(0x8); .b3[0:4] = 0b01011(0xb); .b4[0:3] = 0b0011(0x3);

?在小端系統中,各個結構體成員的存儲情況如下:

? ? ? ? ?.a1? ? ? ? ?.a2? ? ? ? ? ? ?.b1? ? ? ? ??.b2? ? ? ? ? .b3? ? ? ? ? ?.b4 bit? ? ? [01:00]? ? ?[07:02]? ? ? ? ?[10:08]? ? ? [14:11]? ? ? [19:15]? ? ? [23:20] data? ? 01? ? ? ? ? 000011? ? ? ? 100? ? ? ? ?1000? ? ? ? ?01011? ? ? ?0011.a1[1:0] = 0b01(0x1); .a2[5:0] = 0b000011(0x3); .b1[2:0] = 0b100(0x4); .b2[3:0] = 0b1000(0x8); .b3[4:0] = 0b01011(0xb); .b4[3:0] = 0b0011(0x3)

位域&大小端&以太網通信

位域可以2bit、5bit等不規則的多個bit來描述一個成員,但單通道串行通信接口只能以8bit為單位進行逐位發送,且從高bit發送還是低bit發送取決于CPU的大小端模式,大端CPU先發送bit0,小端CPU先發送bit7.

使用上文提到的結構體struct st1 data進行網絡發送時會出現如下有趣現象:


大端CPU發送

發送上述數據,網絡端口發送的順序將會是(從左到右的發):01? 000011? 100? 1000? 01011? 0011(為方便區分字節,同一個byte的位背景顏色相同;為方便區分結構體成員,成員間用空格隔開)。

如果接收端為大端CPU,針對每個字節的接收,收到的第一個bit放到bit0,最后一個bit放到bit7,最終收到的數據將是:bit[0:23]??01? 000011? 100? 1000? 01011? 0011。如果接收端程序定義的結構體與發送端完全相同,則每個成員剛好對應上,數據解析正確。

如果接收端為小端CPU,針對每個字節的接收,收到的第一個bit放到bit7,最后一個bit放到bit0,最終收到的數據將是:bit[23:0]? 1011? 00111? 0010? 000??010000? 11。如果接收端程序定義的結構體與發送端完全相同,則由于發送位序顛倒,數據已經完全紊亂。根據C/C++的規定:無論大端還是小端CPU,先定義的結構體成員一定位于低位或低字節,解析出來的數據如下:

.a1[1:0] = 0b11(0x3);

.a2[5:0] = 0b010000(0x10);

.b1[2:0] = 0b000(0x0);

.b2[3:0] = 0b0010(0x2);

.b3[4:0] = 0b00111(0x7);

.b4[3:0] = 0b1011(0xb);

和源數據相比,已經面目全非了。


小端CPU發送

小端發送問題與大端發送原理相同,讀者可自己分析,加深印象。


位域大小端問題的解決措施

問題原因:位序的顛倒使得域內部數據存儲順序顛倒;如果域大于1個字節,且域成員間存在跨字節情況,則位序顛倒及字節序不顛倒特性,會使得域成員存在數據出現重組情況,進一步加重數據的紊亂。分析起來比較燒腦。

筆者總結了一套解決此問題的方法:

1、大端CPU程序與小端CPU程序中的位域結構體中各個域間順序相同

2、大端CPU程序與小端CPU程序中的位域結構體中相同域內部的域成員順序相反

3、大端CPU或小端CPU在發送或收到數據時,任意一方做域的大小端字節序轉換,如域為uint16_t則按照2字節大小端轉換,為uint32_t則按照4字節大小端轉換。

具體是大端CPU還是小端CPU做結構體定義修正發送時域大小端轉換,取決于項目定義的報文是大端模式還是小端模式。如果報文定義的文檔規定使用大端定義,則大端CPU按照文檔定義結構體既可,且發送時無需做大小端轉換;而小端CPU的程序則需要根據上述解決方法來處理。

驗證:

?假若報文協議規定使用大端模式,則大端CPU的結構體定義如下:

struct st1 {uint8_t? a1 : 2;uint8_t? a2 : 6;uint16_t b1 : 3;uint16_t b2 : 4;uint16_t b3 : 5;uint16_t b4 : 4; };struct st1 data ={.a1 = 0x1,.a2 = 0x3,.b1 = 0x4,.b2 = 0x8,.b3 = 0xb,.b4 = 0x3 };

?小端CPU的結構體定義如下:

struct st1 {uint8_t? a2 : 6;uint8_t? a1 : 2;uint16_t b4 : 4;uint16_t b3 : 5;uint16_t b2 : 4;uint16_t b1 : 3; };char buff[3]; struct st1 *p_data = (struct st1 *)buff;

大端CPU通過以太網發送數據順序:01? 000011? 100? 1000? 01011? 0011

小端CPU通過以太網收到數據:bit[23:0]? 101100111001000001000011

數據用存入buff后做域大小端轉換,得到數據bit[23:0]? 100100001011001101000011

p_data進行解析解析得到數據bit[23:0]? 100? 1000? 01011? 0011??01? 000011,各成員值如下:

.a1[1:0] = 0b01(0x1);

.a2[5:0] = 0b000011(0x3);

.b1[2:0] = 0b100(0x4);

.b2[3:0] = 0b1000(0x8);

.b3[4:0] = 0b01011(0xb);

.b4[3:0] = 0b0011(0x3);

解析得到的數據和發送端的數據完全一樣,數據解析正確。


大端ARM

ARM Cortex-M3的端模式。
ARM的小端模式和前面所講完全相同,但它的大端模式比較特殊,32bit的數據的位序并不是bit0-bit31,而是bit[7:0][15:8][23:16][31:24]。

CM3 同時支持小端模式和大端模式。但是,單片機其它部分的設計,包括總線的連接,內存控制器以及外設的性質等, 一定要先在單片機的數據手冊上查清楚可以使用的端。在絕大多數情況下,基于 CM3 的單片機都使用小端模式——為了避免不必要的麻煩,在這里推薦讀者清一色地使用小端模式。

CM3中對大端模式的定義還與ARM7的不同(小端的定義都是相同的)。在ARM7中,大端的方式被稱為“不變大端”,而在CM3中,使用的是“字節不變大端”。如表5.4所示。

?請注意:在 AHB 總線上的 BE‐8 模式下,數據字節 lane 的傳送格式是與小端模式一致的。
這是不同于 ARM7TDMI 的行為,它在大端模式下會有另一種總線 lane 安排,如表 5.6
所示。

在CM3中,是在復位時確定使用哪種端模式的,且運行時不得更改。指令預取永遠使用小端模式,在配置控制存儲空間的訪問也永遠使用小端模式(包括NVIC,FPB之流)。另外,外部私有總線地址區0xE0000000至0xE00FFFFF也永遠使用小端模式。

當 SoC 設計不支持大端模式,卻有一些外設包含了大端模式時,可以輕易地使用REV/REVH指令來完成端模式的轉換。


對ARM的大端不理解也并不影響我們對大小端的理解與實際應用,因為我還沒使用過大端ARM內核的芯片(個人能力有限)。

總結

以上是生活随笔為你收集整理的浅谈大小端(Endian)与位域的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 成人一区在线观看 | 国产一区二区三区在线视频观看 | a级黄色网址 | 成年人看的网站 | 国产又粗又猛视频 | 91香蕉视频在线观看免费 | 成人毛片在线 | 国产女人叫床高潮大片免费 | 亚洲视频2 | 波多野结衣一二区 | 91在线视频观看 | 丁香av| 日韩免费黄色 | 黄色片网战 | 一级片免费观看 | 99热在线看| 中文字幕在线观看视频网站 | 国产午夜av | 国产精品毛片视频 | 日本在线不卡一区二区 | 最新在线黄色网址 | 日韩精品成人在线 | 欧美亚洲日本 | 在线观看亚洲天堂 | 去毛片 | 爱情岛论坛亚洲线路一 | 老鸭窝视频在线观看 | 久久精品国产免费 | 免费毛片av | 国产日韩第一页 | 国产中文字幕在线播放 | 18禁网站免费无遮挡无码中文 | 日韩欧美一二三 | 偷偷操网站| 蜜桃视频久久一区免费观看入口 | 亚洲黄一区 | 精品国产一区二区三区性色 | 日韩欧美99 | 91九色国产视频 | 六月综合 | 91caob| 中文字幕黄色片 | 少妇精品高潮欲妇又嫩中文字幕 | 欧美视频在线免费看 | 午夜色福利| 欧美激情精品久久久久久变态 | 国产绳艺sm调教室论坛 | 成人区人妻精品一区二区网站 | 黄色小视频链接 | 亚洲精品一二三区 | 日本变态折磨凌虐bdsm在线 | 国产一区久久久 | 国产尤物视频 | 国产精品美女av | 欧美午夜性春猛交 | www.av88 | 成人高清视频免费观看 | 天堂中文在线看 | 国产又猛又粗 | 中文字幕资源站 | 交视频在线播放 | 97se亚洲综合| 久久国产精品首页 | 刘亦菲久久免费一区二区 | 性xxxx欧美老肥妇牲乱 | 欧美日韩黄色网 | 91麻豆蜜桃一区二区三区 | 国产成人在线影院 | 国产aⅴ精品一区二区三区久久 | 亚洲最大成人av | 天天久| 欧美精品日韩在线观看 | 亚洲a图| 国产精品jizz在线观看老狼 | 久久r这里只有精品 | 伦伦影院午夜理论片 | 春色校园激情 | a级一级片 | 男男啪啪网站 | 精品亚洲aⅴ无码一区二区三区 | 全部孕妇毛片 | 日韩a级一片 | 丰满少妇在线观看资源站 | 国产乱人伦 | 日韩av在线播放观看 | 免费国产黄色 | 11孩岁女毛片 | 公车乳尖揉捏酥软呻吟 | 五月婷婷在线观看 | 都市激情国产精品 | 51av在线| 人人超碰在线 | 精品人妻久久久久久888不卡 | 激情综合av | 欧美人与性动交g欧美精器 国产在线视频91 | 日本一二三区视频在线 | 无码av免费毛片一区二区 | 婷婷五月小说 | 奇米影视四色7777 |