You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

206 lines
7.3 KiB

Big and Little Endian Byte Orderings
Big and Little Endian Byte Orderings
The MIPS processor and compilers support both the Big Endian and Little
Endian byte-ordering conventions. The names Big Endian and Little
Endian are used because of the apt analogy to the bloody feud in the
classic children's book Gulliver's Travels (quod vide). The feud was
between the two mythical islands, Lilliput and Blefescu, over the
correct end (big or little) at which to crack an egg.
In our case, the
issue has to do with the "end" (most significant or least significant)
of a multiple-byte data type.
With Big Endian ordering, the address of a multiple-byte data type is
of its most significant byte (its "big end"), whereas with Little
Endian ordering, the address is of its least significant byte (its
"little end"). This is shown in Figure A.14. For structures declared
in a high-level language, the order of bytes in memory will differ
depending on the byte ordering and the particular data type, as shown
for a C structure in Figure A.15.
��������������������������������������������������������������������������������
Code Big Endian Little Endian
Memory Contents Memory Contents
��������������������������������������������������������������������������������
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 */
};
��������������������������������������������������������������������������������
Figure A.15 Big and Little Endian Byte-Ordering Example
Note that Endianness only affects the operation of the load and store
instructions, which means when data is moved between memory or
peripheral devices and registers.
Except in cases where the host and target have the same byte-ordering
convention, you must explicitly define the required Endianness of the target
code using the appropriate command-line option (EB or EL). This will
override the host's default byte ordering. For example,
pmcc -EB -o prog prog.c
pmcc -EL -o prog prog.c
To write code that can be compiled/assembled to execute correctly in
either a Big or a Little Endian target environment, the user must
follow one basic rule: either eliminate Endian-specific code or enclose
it with #ifdef/else statements, using the appropriate preprocessor
flag (MIPSEB or MIPSEL). Endian-specific code is produced whenever the
data type implicit in the instruction (e.g., "byte" in load byte)
differs from the data type of the accessed data, such as using four
load-byte instructions to read a single word or using a store-word
instruction to store 4 bytes. I/O addresses are also Endian-specific,
because a peripheral device is hardwired to a specific part of the data
bus (typically D0-D7).
The example programs main.c and asm.s print Endian-sensitive values
returned from the functions end1 and end2 and the contents of two
Endian-sensitive I/O locations, SIOCNTL and SIODATA. For purposes of
illustration, the functions return correct results when passed the
value 0 and incorrect results when passed the value 1. The programs are
shown in their entirety in the final section of this appendix and are
discussed below.
The C program defines two base addresses for the peripheral device
(SIOBASE) and uses the preprocessor variable MIPSEB (Big Endian) to select
between the two byte-ordering conventions.
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)
The function main prints the results of the functions end1 and end2.
Incorrect results are produced by end1 because when the function is
passed a 1, it reads the word as a series of 4 bytes, rather than as a
single word. Starting at the word address, each byte is read into the
variable v, such that the lowest addressed byte ends up in the most
significant byte of the variable. This is the correct byte ordering for
Big Endian but incorrect for Little Endian:
19 for (i=0;i
Incorrect results are produced by end2 because the lwl and lwr instruc-
tions are used to access unaligned data; the non-Endian-sensitive solution
uses the ulw instruction:
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
For Big Endian the program prints:
12345678 12345678
12345678 12345678
00 3b
and for Little Endian it prints:
12345678 78563412
12345678 78345612
00 3b
Keep in mind that a program's binary cannot be converted from one
byte-ordering convention to another by simply swapping all the bytes. This
would produce correct results only if all of the program's data were of the
same type (size) and the same size as the instructions. To change the byte
ordering, programs must be recompiled using the appropriate compiler
option.
A.7 PROGRAM LISTINGS
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 *)
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
[EGG] Danny Cohen, "On Holy Wars and a Plea for Peace," IEEE
Computer, Oct. 1981, pp. 48-54.
��������������������������������������������������������������������������������
This explanation was extracted from Appendix A of
The MIPS Programmer's Handbook, by Erin Farquhar and Philip Bunce.
��������������������������������������������������������������������������������
Navigation:
Document Home |
Document Contents |
Document Index