📄 endian.htm
字号:
<title>Big and Little Endian Byte Orderings </title> <h1 align=center>Big and Little Endian Byte Orderings </h1><!--INDEX "Gulliver's Travels" MIPSEB "MIPS Programmer's Handbook" --><!--INDEX "Big endian" "Little endian" "Byte ordering" --><!--INDEX "Philip Bunce" "Erin Farquhar" -->The MIPS processor and compilers support both the Big Endian and LittleEndian byte-ordering conventions. The names Big Endian and LittleEndian are used because of the apt analogy to the bloody feud in theclassic children's book Gulliver's Travels (quod vide). The feud wasbetween the two mythical islands, Lilliput and Blefescu, over thecorrect end (big or little) at which to crack an <a href="#Q1">egg</a>. In our case, theissue has to do with the "end" (most significant or least significant)of a multiple-byte data type. <p>With Big Endian ordering, the address of a multiple-byte data type isof its most significant byte (its "big end"), whereas with LittleEndian ordering, the address is of its least significant byte (its"little end"). This is shown in Figure A.14. For structures declaredin a high-level language, the order of bytes in memory will differdepending on the byte ordering and the particular data type, as shownfor a C structure in Figure A.15. <p><pre><hr><!------------------------------------------------------------------> Code Big Endian Little Endian Memory Contents Memory Contents<hr><!------------------------------------------------------------------>struct { long a; short b[2]; char c[4]; } S1 = { /* Big Endian Little Endian */ 0x12345678, /* 12 34 56 78 78 56 34 12 */ 0x1234,0x5678, /* 12 34 56 78 34 12 78 56 */ "ABC" /* 41 42 43 00 41 42 43 00 */ };<hr><!------------------------------------------------------------------></pre> <b>Figure A.15</b> Big and Little Endian Byte-Ordering Example <p>Note that Endianness only affects the operation of the load and storeinstructions, which means when data is moved between memory or peripheral devices and registers. <p>Except in cases where the host and target have the same byte-orderingconvention, you must explicitly define the required Endianness of the targetcode using the appropriate command-line option (EB or EL). This will override the host's default byte ordering. For example,<p> <pre> pmcc -EB -o prog prog.c pmcc -EL -o prog prog.c </pre> <p>To write code that can be compiled/assembled to execute correctly ineither a Big or a Little Endian target environment, the user mustfollow one basic rule: either eliminate Endian-specific code or encloseit with #ifdef/else statements, using the appropriate preprocessorflag (MIPSEB or MIPSEL). Endian-specific code is produced whenever thedata type implicit in the instruction (e.g., "byte" in load byte)differs from the data type of the accessed data, such as using fourload-byte instructions to read a single word or using a store-wordinstruction to store 4 bytes. I/O addresses are also Endian-specific,because a peripheral device is hardwired to a specific part of the databus (typically D0-D7). <p>The example programs main.c and asm.s print Endian-sensitive valuesreturned from the functions end1 and end2 and the contents of twoEndian-sensitive I/O locations, SIOCNTL and SIODATA. For purposes ofillustration, the functions return correct results when passed thevalue 0 and incorrect results when passed the value 1. The programs areshown in their entirety in the final section of this appendix and arediscussed below. <p>The C program defines two base addresses for the peripheral device(SIOBASE) and uses the preprocessor variable MIPSEB (Big Endian) to selectbetween the two byte-ordering conventions.<p><pre> 1 #ifdef MIPSEB 2 #define SIOBASE 0xbe000003 /* Big Endian base address */ 3 #else 4 #define SIOBASE 0xbe000000 /* Little Endian base address */ 5 #endif 6 #define SIOCNTL *((volatile unsigned char *)SIOBASE+4) 7 #define SIODATA *((volatile unsigned char *)SIOBASE+12)</pre><p>The function main prints the results of the functions end1 and end2.Incorrect results are produced by end1 because when the function ispassed a 1, it reads the word as a series of 4 bytes, rather than as asingle word. Starting at the word address, each byte is read into thevariable v, such that the lowest addressed byte ends up in the mostsignificant byte of the variable. This is the correct byte ordering forBig Endian but incorrect for Little Endian:<p><pre> 19 for (i=0;i<4;i++) { 20 v <<= 8; 21 v |= p[i]; 22 } 23 }</pre><p>Incorrect results are produced by end2 because the lwl and lwr instruc-tions are used to access unaligned data; the non-Endian-sensitive solutionuses the ulw instruction:<p><pre> 8 end2: la t0,dat2 9 beq a0,zero,1f 10 nop 11 lwl v0,0(t0) 12 lwr v0,3(t0) 13 b 2f 14 nop 15 1: ulw v0,(t0) 16 2: jr ra</pre> <p> For Big Endian the program prints:<p><pre> 12345678 12345678 12345678 12345678 00 3b</pre><p> and for Little Endian it prints:<p><pre> 12345678 78563412 12345678 78345612 00 3b</pre> <p>Keep in mind that a program's binary cannot be converted from onebyte-ordering convention to another by simply swapping all the bytes. Thiswould produce correct results only if all of the program's data were of thesame type (size) and the same size as the instructions. To change the byteordering, programs must be recompiled using the appropriate compileroption.<p><b>A.7 PROGRAM LISTINGS</b><p><pre>main.c: 1 #ifdef MIPSEB 2 #define SIOBASE 0xbe000003 /* Big Endian base address */ 3 #else 4 #define SIOBASE 0xbe000000 /* Little Endian base address */ 5 #endif 6 #define SIOCNTL *((volatile unsigned char *)SIOBASE+4) 7 #define SIODATA *((volatile unsigned char *)SIOBASE+12) 8 int dat1 = 0x12345678; 9 end1(n) 10 int n; 11 { 12 int i,v; 13 unsigned char *p; 14 /* set up a pointer into the data */ 15 p = (unsigned char *)&dat1; 16 if (n==0) v = dat1; 17 else { 18 v = 0; 19 for (i=0;i<4;i++) { 20 v <<= 8; 21 v |= p[i]; 22 } 23 } 24 return(v); 25 } 26 main() 27 { 28 printf("%08x %08x\n"); 29 printf("%08x %08x\n"); 30 printf("%02x %02x\n"); 31 }asm.s: 1 #include "mips.h" 2 .data 3 dat2: .word 0x12345678 4 .text 5 .globl end2 6 .ent end2 7 .set noreorder 8 end2: la t0,dat2 9 beq a0,zero,1f 10 nop 11 lwl v0,0(t0) 12 lwr v0,3(t0) 13 b 2f 14 nop 15 1: ulw v0,(t0) 16 2: jr ra 17 nop 18 .end end2</pre><a name="Q1"><!--INDEX "Danny Cohen" -->[EGG] Danny Cohen</a>, "On Holy Wars and a Plea for Peace," IEEE Computer, Oct. 1981, pp. 48-54.<p><hr>This explanation was extracted from Appendix A of <a href="http://www.carmel.com/mipsbook.html">The MIPS Programmer's Handbook</a>, by Erin Farquhar and Philip Bunce.</dl><p><hr><b>Navigation:</b> <a href="index.htm">Document Home</a> | <a href="doctoc.htm">Document Contents</a> | <a href="docindex.htm">Document Index</a> <p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -