[REFERENCE] Little Endian vs Big Endian

Seeing as we are starting to attract quite the coding crowd and @FaunCB happens to be a very big risc and power pc architecture fan where I am a very heavy x86 enthusiast oh and ARM (which is risc) aight i guess to… RISC and CISC have their advantages and disadvantages and none is better then the other

Perhaps its time to provide a solid reference that people can link to when people find themselves asking what the heck is this endian stuff ? something outta minecraft XD?

Lets take a look at my notes shall we?

What are the two different theories, what do they set out to accomplish?

Little Endian and Big endian are two ways of storing multi-byte data-types ( int, float, etc) in computers. In a sense this is how the computer stores data in its processor registers, which can hold a variety of data types from instructions to storage addresses to stack pointers.

What’s the difference between the theories?

In Little Endian machines, last byte or least significant bit of binary representation of the multi-byte data-type is stored first while in Big Endian machines, first byte or most significant bit of binary representation of the multi-byte data-type is stored first.

For example:

Suppose an integer is stored as 4 bytes(32-bits), then a variable y with value 0xdeadbeef( Hexa-decimal representation) is stored as four bytes 0xDE, 0xAD, 0xBE, 0xEF, on Big-endian while on Little-Endian (Intel x86), it will be stored in reverse order as follows 0xEF 0xBE 0xAD 0xDE.

Example: How 0x1234567 is stored at memory location 0x100-ox103 on any standard machine at home?

Here is a piece of code from my ECE330 class that I wrote to do exactly that for a test given zero help to test endianness the third day of class. Execute it at home on a linux machine prefereably with all the build tools LOL… Or windows whichever you may prefer the operating system is completely irrelevant

#include <stdio.h>
/* function to show bytes in memory, from location start to start+n*/
void show_mem_rep(char *start, int n){
    int i;
    for (i = 0; i < n; i++)
    printf(" %.2x", start[i]);
    printf("\n");
}
/*Main function to call above function for 0xba5eba11*/
int main(){
    int i = 0xba5eba11;
    show_mem_rep((char *)&i, sizeof(i));
    return 0;
}

How to remember?

Well think about this. If you have two fishes. In big endian you have the whole fish but lets try to think about it as two halves of the fish in the correct order. representing each bit. Now in little endian you cut the fish in half and put the tail first then start counting. See the difference? Draw it for yourself all you gotta remember is that in Little Endian, things are stored in reverse order.

So you find yourself asking which is better?

Both have advantages and disadvantages:

In “Little Endian” form, assembly language instructions for picking up a 1, 2, 4, or longer byte number proceed in exactly the same way for all data storage formats. The process goes like this… first pick up the lowest order byte at offset 0. Also, because of the 1:1 relationship between address offset and byte number (offset 0 is byte 0), multiple precision math routines are correspondingly easier to write. Armed with that knowledge we can see why we write most mathematical routines in little endian.

In “Big Endian” form, by having the high-order byte come first, you can always test whether the number is positive or negative by looking at the byte at offset zero which is incredibly useful because you don’t have to know how long the number is, nor do you have to skip over any bytes to find the byte containing the sign information of the data or numerical instruction set. The numbers are also stored in the order in which they are printed out, so binary to decimal routines are particularly efficient and easier to read by humans

So what software has what kind of endianess?

Glad you asked…

Adobe Photoshop – Big Endian
BMP (Windows and OS/2 Bitmaps) – Little Endian
DXF (AutoCad) – Variable
GIF – Little Endian
IMG (GEM Raster) – Big Endian
JPEG – Big Endian
FLI (Autodesk Animator) – Little Endian
MacPaint – Big Endian
PCX (PC Paintbrush) – Little Endian
PostScript – Not Applicable (text!)
POV (Persistence of Vision ray-tracer) – Not Applicable (text!)
QTM (Quicktime Movies) – Little Endian (on a Mac!)
Microsoft RIFF (.WAV & .AVI) – Both
Microsoft RTF (Rich Text Format) – Little Endian
SGI (Silicon Graphics) – Big Endian
Sun Raster – Big Endian
TGA (Targa) – Little Endian
TIFF – Both, Endian identifier encoded into file
WPG (WordPerfect Graphics Metafile) – Big Endian (on a PC!)
XWD (X Window Dump) – Both, Endian identifier encoded into file

And so on

If you ever find yourself in need of reversing the order of a multibyte integer to suit your liking… there are many methods to doing so

It is pretty easy to reverse a multibyte integer if you find you need the other format. A single function can be used to switch from one to the other, in either direction. A simple and not very efficient version might look as follows:

    Function Reverse (N:LongInt) : LongInt ;
     Var B0, B1, B2, B3 : Byte ;
    Begin
        B0 := N Mod 256 ;
        N  := N Div 256 ;
        B1 := N Mod 256 ;
        N  := N Div 256 ;
        B2 := N Mod 256 ;
        N  := N Div 256 ;
        B3 := N Mod 256 ;
        Reverse := (((B0 * 256 + B1) * 256 + B2) * 256 + B3) ;
    End ;

A more efficient version that depends on the presence of hexadecimal numbers, bit masking operators AND, OR, and NOT, and shift operators SHL and SHR might look as follows:

    Function Reverse (N:LongInt) : LongInt ;
     Var B0, B1, B2, B3 : Byte ;
    Begin
        B0 := (N AND $000000FF) SHR  0 ;
        B1 := (N AND $0000FF00) SHR  8 ;
        B2 := (N AND $00FF0000) SHR 16 ;
        B3 := (N AND $FF000000) SHR 24 ;
        Reverse := (B0 SHL 24) OR (B1 SHL 16) OR (B2 SHL 8) OR (B3 SHL 0) ;
    End ;

There are certainly more efficient methods, some of which are quite machine and platform dependent as @FaunCB pointed out the Power Architecture has its own way of doing so that is optimized for its platform… Use what works best for your situation

@wendell feel free to chime in if I left some important bits out (no pun intended). Bound to have made some mistakes somewhere.

for those wishing to learn more:
https://betterexplained.com/articles/understanding-big-and-little-endian-byte-order/

You may link to this explanation anywhere you see fit on the forum and or post a link to it to explain the difference if you ever find yourself in the need of explaining it or talking about endianess in your post

3 Likes

All of the X’s and the D’s my friend.

I would be happy to see more RISC and POWER content on L1, even if it were just a short video talking about it. For me personally I like the number theory in it all and the idea that my shitty little ibook has a proc in it that is actually more capable than some of my core 2 duo systems is hilarious to me. Lunduke brought up a great point in an interview after he looked at Icaros Desktop (aros) in that we have such stupidly powerful processors today that still struggle to even run windows properly, let alone have a fast boot time on their own. I’ve always believed that little endian bit types were… Eh, slower. You can’t push as much shit down the pipeline and theres only scale in adding more processors. Mostly a waste of time.

Neat to see someone give a rats ass though.

Thats not really true. I mean it can be depending on how its written and implemented but thats not always the case each is better at different workloads but as for the amount of data processed say all worlds were equal… just switching the endianness and no other architectural differences then they both can have the same amount of data processed per clock cycle

Thanks for sharing this.

Also, what languge is this? I’m only familiar with NASM x86 assembly.

1 Like

Do you happen to have quantitative evidence to this effect?

Its x86 look at the register logic shift functions I am using… Its really easy to denote an assembly language by its functions SHL and SHR are unique calls to IA-32 // x86

Mostly basing that off of the design of the chips themselves. As OP said they move the same data mathematically.

At the time that the iBook and Powerbooks were out, outside of commercial use you could get a workstation grade laptop for 800 bucks from apple. All intel had at the time was the Pentium M (which was a pentium 3) and amd wasn’t big into laptops quite yet, on top of OEM’s getting paid by intel to not take AMD. When IBM got to stop working thebconsumer market they came out with a new series of POWER and CELL/XELL which ripped intel to shreds, and has ever since pretty much, minus 2010 and a bit of 2015.

So, thats what I mean.

Mmmmm only when coded for properly. You see you optimized code on either can run significantly faster. Each architecture is optimized for a different set of workloads. It really all depends on the application. Where cell maybe faster intel can be slower or amd… and vice versa… in fact IBM is rather interested in amd’s infinity fabric lol

1 Like

Trust me I know all about that. Its the reason IBM dragged power out of the consumer market to begin with.

Yeah, but its not NASM. :stuck_out_tongue:

1 Like

That is true but once you have learned one assembly language you start to see the basic similarities everywhere. AVR is something I have yet to get into. Perhaps Ill get the direct access kit to my arduino to mess around a bit

Storing multi-byte data in reverse order doesn’t make sense to me. Do you specify a memory offset at the end of the data set and its read in reverse towards 0x00. Otherwise you would be wasting operations formatting your data for displaying and so on.

Reversing the byte itself does make sense.

This is what I meant sort of but think about where the stack pointer starts in little endian… vs big endian… which is easier to overflow?

sorry to ask, but endianess isn’t that just how the bytes are read. e.g. 10000000 would be read as either 10000000 or 00000001. e.g. when you recieve data from a different endian system the hex values doesn’t magically switch as well.
an integer is a set of 4 bytes, and the max value of these 4 bytes would be 2^32, which is enterprited as an int, and not 4 bytes.

e.g. 0xDE, 0xAD, 0xBE, 0xEF != 0xEF 0xBE 0xAD 0xDE on the two different systems.
rather it woud be 0xDE, 0xAD, 0xBE, 0xEF == 0x7B, 0xB5, 0x7D, 0xF7, since it is not the integer read backwards/forwards, but the bytes it consists of.

Endianess is the order the bytes are stored in. Note that bit order inside the bytes is not affected, just the order of the bytes themselves.