1. 程式人生 > >ARM Endian(位元組序)初探

ARM Endian(位元組序)初探

Endian這個詞在有道詞典中這樣描述:名詞,位元組儲存次序,元組排列順序,位元組序

這個單詞的出處是諷刺小說《格利佛遊記》,百度百科上的描述是:

在小人國裡的小人因為非常小(身高6英寸)所以總是碰到一些意想不到的問題。有一次因為對水煮蛋該從大的一端(Big-End)剝開還是小的一端(Little-End)剝開的爭論而引發了一場戰爭,並形成了兩支截然對立的隊伍:支援從大的一端剝開的人Swift就稱作Big-Endians,而支援從小的一端剝開的人就稱作Little-Endians......(字尾ian表明的就是支援某種觀點的人)。

1980年,Danny Cohen在其著名的論文"On Holy Wars and a Plea for Peace"中為了平息一場關於在訊息中

位元組該以什麼樣的順序進行傳送的爭論而引用了該詞。該文中,Cohen非常形象貼切地把支援從一個訊息序列的最高位開始傳送的那夥人叫做Big-Endians,支援從最低位開始傳送的相對應地叫做Little-Endians。此後Endian這個詞便隨著這篇論文而被廣為採用。

上面是資訊傳輸的順序,而本文想要說的是位元組在記憶體中的儲存順序。

如果高位值存放在記憶體中低位地址就是Big-Endian,如果低位值存放在記憶體中的低位地址就是Little-Endian。

比如:

0x11223344在大端機上是11223344,在小端機上是44332211

通常來說,x86 cpu是Little-Endian。而一般ARM CPU也是Little-Endian。

但是當前常見的開發板使用的處理器比如S3C2410A、S3C2440等都是大小端支援的,可以通過軟體選擇。

那麼如何用程式看當前裝置是什麼位元組序呢?

很多人的做法是使用一個指標:

int x = 1;  
if(*(char *)&x == 1)  
    printf("little-endian\n");  
else  printf("big-endian\n");
或者結構體:
  union w
 {
  int a;  //4 bytes
  char b; //1 byte
 } c;
  c.a=1;
  if (c.b==1)
  printf("It is Little_endian!\n");
  else
  printf("It is Big_endian!\n");

那麼如何在Android中測試呢?下面寫了一個Android NDK Demo。

Endian.java

package com.linc.lib;

public class Endian {
	static {
		System.loadLibrary("Endian");
	}
	
	public static native String getEndian();
}
Endian.c
#include "com_linc_lib_Endian.h"

JNIEXPORT jstring JNICALL Java_com_linc_lib_Endian_getEndian(JNIEnv *env, jclass obj)
{
	jclass class = (*env)->FindClass(env, "java/lang/String");
	jstring endian;
	
	union w
	 {
		  int a;  //4 bytes
      	  char b; //1 byte
	 } c;
	  c.a=1;
	  if (c.b==1)
	  endian=(*env)->NewStringUTF(env,"It is Little_endian!\n");
	  else
	  endian=(*env)->NewStringUTF(env,"It is Big_endian!\n");


	  int x = 1;
	  if(*(char *)&x == 1)
		  endian=(*env)->NewStringUTF(env,"It is Little_endian!\n");
	  else
		  endian=(*env)->NewStringUTF(env,"It is Big_endian!\n");

	return endian;
}