老地方冰果室交流區

歡迎冰果室讀者在此交流
現在的時間是 11/17/2019 8:56 pm

所有顯示的時間為 UTC + 8 小時




發表新文章 回覆主題  [ 7 篇文章 ] 
發表人 內容
 文章主題 : Endian Trouble...
文章發表於 : 02/03/2005 7:58 pm 
離線
討論區管理員
頭像

註冊時間: 05/18/2001 1:01 am
文章: 2475
來自: Forgotten Realm
最近在寫底層的通訊程式,用 ANSI C 寫,目標是 Porting 到不同平台,幾乎是立刻就碰到了 Endian 的問題。2 byte 以上的 short/int/long 型別都要轉換不說,最麻煩的就是這個狀況:

代碼:
unsigned char buffer[100];

void function1(...) {
   unsigned short a, b;
   unsigned short *ptr = &buffer[0];
   ...
   *ptr++ = a;
   *ptr++ = b;
   ...
}

void function2(...) {
   unsigned int c;
   c = *((int *)(&buffer[0]));
   if(c==SOME_CONSTANT) {
      function3 (c);
   }
}

void function3(unsigned int c) {
    unsigned short x = (unsigned short)(c & 0x0000FFFF); // 應該要等於 a 的
    unsigned short y = (unsigned short)(c>>16); // 應該要等於 b 的
}


程式碼要能夠直接搬到 X86 平台上 Compile,
不希望維護兩份程式碼,所以不能用 Darwin 特有的 endian.h。
現在是用了一堆 #define 的 Macro 來解決這個問題,
有沒有比較高明一點的方法呢?

_________________
ash nazg durbatuluk, ash nazg gimbatul,
ash nazg thrakatuluk agh burzum-ishi krimpatul.


回頂端
 個人資料  
 
 文章主題 :
文章發表於 : 02/03/2005 9:08 pm 
離線
留言五百如一日

註冊時間: 12/25/2001 1:01 am
文章: 610
comp.lang.c FAQ 有兩個相關問答:


How can I determine whether a machine's byte order is big-endian or little-endian?

How can I use a preprocessor #if expression to tell if a machine is big-endian or little-endian?

看看可否釋疑 8)


回頂端
 個人資料  
 
 文章主題 :
文章發表於 : 02/03/2005 10:42 pm 
離線
討論區管理員
頭像

註冊時間: 05/02/2001 1:01 am
文章: 1297
#include <netinet/in.h>
unsigned short int htons(unsigned short int data)

相關的還有 htonl()、ntohs() 跟 ntohl(),反正就是在做你想要做的處理之前,讓它統統先變成 big-endian 就對了。

_________________
[digdog dig];


最後由 digdog 於 02/04/2005 9:45 am 編輯,總共編輯了 1 次。

回頂端
 個人資料  
 
 文章主題 :
文章發表於 : 02/04/2005 8:23 am 
離線
討論區管理員
頭像

註冊時間: 05/18/2001 1:01 am
文章: 2475
來自: Forgotten Realm
測試 Big Endian 的方式倒是不難,在 Mac 上會有定義『_BIG_ENDIAN』,用一個 #ifdef 來判斷就好。
htons 之類的函式不能呼叫(因為目標平台上沒有這個函式庫),自己用 #define 定義了 Macro。
只是每個數字都要特別處裡,實在很討厭。雖說 Endian 是依據 CPU Register 的配置來決定,只是想看看有沒有任何方法讓 GCC 自動處理掉這個問題...
好像想得太美了。OTZ

_________________
ash nazg durbatuluk, ash nazg gimbatul,
ash nazg thrakatuluk agh burzum-ishi krimpatul.


回頂端
 個人資料  
 
 文章主題 :
文章發表於 : 02/04/2005 9:52 am 
離線
討論區管理員
頭像

註冊時間: 05/02/2001 1:01 am
文章: 1297
ulysses 寫:
htons 之類的函式不能呼叫(因為目標平台上沒有這個函式庫),自己用 #define 定義了 Macro。


好可憐喔.... 那自己寫一個如何?

代碼:
uint16_t htons(uint16_t host_int) {
      uint16_t big_endian_int;
      uint8_t *p = (uint8_t *)&big_endian_int;
      p[0] = (host_int & 0xff00) >> 8;
      p[1] = host_int & 0xff;
      return big_endian_int;
}

uint16_t ntohs(uint16_t big_endian_int) {
      uint8_t *p = (uint8_t *)&big_endian_int;
      return (p[0] << 8) + p[1];
}


ulysses 寫:
只是每個數字都要特別處裡,實在很討厭。雖說 Endian 是依據 CPU Register 的配置來決定,只是想看看有沒有任何方法讓 GCC 自動處理掉這個問題...
好像想得太美了。OTZ


你的 tool chain 是給那個平台用的?gcc 裡面有 -mwords-little-endian 這類的選項嗎?

_________________
[digdog dig];


回頂端
 個人資料  
 
 文章主題 :
文章發表於 : 02/04/2005 1:20 pm 
離線
討論區管理員
頭像

註冊時間: 05/18/2001 1:01 am
文章: 2475
來自: Forgotten Realm
digdog 寫:
ulysses 寫:
htons 之類的函式不能呼叫(因為目標平台上沒有這個函式庫),自己用 #define 定義了 Macro。

好可憐喔.... 那自己寫一個如何?


有啊,就這樣:

代碼:
typedef   unsigned char      byte_t;
typedef   unsigned short      word_t;
typedef   unsigned long      dword_t;
typedef   unsigned long long   qword_t;

#ifdef _BIG_ENDIAN
#define swapword(a)      ((word_t)(a)>>8)|((word_t)(a)<<8)
#define swapdword(a)   ((((dword_t)(a)&0xFF000000)>>24)|\
                   (((dword_t)(a)&0x00FF0000)>>8)|\
                   (((dword_t)(a)&0x0000FF00)<<8)|\
                   (((dword_t)(a)&0x000000FF)<<24))
#define swapqword(a)   ((((qword_t)(a)&0xFF00000000000000ll)>>56)|\
                   (((qword_t)(a)&0x00FF000000000000ll)>>40)|\
                   (((qword_t)(a)&0x0000FF0000000000ll)>>24)|\
                   (((qword_t)(a)&0x000000FF00000000ll)>>8)|\
                   (((qword_t)(a)&0x00000000FF000000ll)<<8)|\
                   (((qword_t)(a)&0x0000000000FF0000ll)<<24)|\
                   (((qword_t)(a)&0x000000000000FF00ll)<<40)|\
                   (((qword_t)(a)&0x00000000000000FFll)<<56))
#else
#define swapword(a)      ((word_t)(a))
#define swapdword(a)   ((dword_t)(a))
#define swapqword(a)   ((qword_t)(a))
#endif


不用說也知道,這個方式很蠢。

digdog 寫:
你的 tool chain 是給那個平台用的?gcc 裡面有 -mwords-little-endian 這類的選項嗎?


有三個平台,X86、AVR mega128 和 TI 460。都是 PDA 類型的裝置。Cross Compiler 用 GCC 就可以,但是 endian 的控制就不曉得應該在 GCC 下參數,還是用 binutil 來處理。

_________________
ash nazg durbatuluk, ash nazg gimbatul,
ash nazg thrakatuluk agh burzum-ishi krimpatul.


回頂端
 個人資料  
 
 文章主題 :
文章發表於 : 02/04/2005 4:48 pm 
離線
討論區管理員
頭像

註冊時間: 05/02/2001 1:01 am
文章: 1297
ulysses 寫:
有三個平台,X86、AVR mega128 和 TI 460。都是 PDA 類型的裝置。Cross Compiler 用 GCC 就可以,但是 endian 的控制就不曉得應該在 GCC 下參數,還是用 binutil 來處理。


gcc 的部分就加參數(像是 -mb / -mbig-endian / -mwords-big-endian )
如果有用到 library 那 ld script 要改,但是爛狗看不懂,所以也沒辦法告訴你要怎麼改

_________________
[digdog dig];


回頂端
 個人資料  
 
顯示文章 :  排序  
發表新文章 回覆主題  [ 7 篇文章 ] 

所有顯示的時間為 UTC + 8 小時


不能 在這個版面發表主題
不能 在這個版面回覆主題
不能 在這個版面編輯您的文章
不能 在這個版面刪除您的文章
不能 在這個版面上傳附加檔案

搜尋:
前往 :  
cron
POWERED_BY
正體中文語系由 竹貓星球 維護製作