Intel processors (and maybe some others) use the little endian format for storage.
I always wonder why someone would want to store the bytes in reverse order. Does this format have any advantages over the big endian format?
|
Intel processors (and maybe some others) use the little endian format for storage. I always wonder why someone would want to store the bytes in reverse order. Does this format have any advantages over the big endian format? |
|||||||||||||||
|
|
There are arguments either way, but one point is that in a little-endian system, the address of a given value in memory, taken as a 32, 16, or 8 bit width, is the same. In other words, if you have in memory a two byte value:
taking that '16' as a 16-bit value (c 'short' on most 32-bit systems) or as an 8-bit value (generally c 'char') changes only the fetch instruction you use — not the address you fetch from. On a big-endian system, with the above layed out as:
you would need to increment the pointer and then perform the narrower fetch operation on the new value. So, in short, ‘on little endian systems, casts are a no-op.’ |
|||||||||||||||||
|
Big-endian and little-endian are only "normal order" and "reverse order" from a human perspective, and then only if all of these are true...
Those are all human conventions that don't matter at all to a CPU. If you were to retain #1 and #2, and flip #3, little-endian would seem "perfectly natural" to people who read Arabic or Hebrew, which are written right-to-left. And there are other human conventions that make big-endian that seem unnatural, like...
Back when I was mostly programming 68K and PowerPC, I considered big-endian to be "right" and little-endian to be "wrong". But since I've been doing more ARM and Intel work, I've gotten used to little-endian. It really doesn't matter. |
|||||||||||||||||
|
|
With 8 bit processors it was certainly more efficienct, you could perform an 8 or 16bit operation without needing different code and without needing to buffer extra values. It's still better for some addition operations if you are dealing a byte at a time. But there is no reason that big-endian is more natural - in English you use thirteen (little endian) and twenty three (big endian) |
|||||||||||
|
|
When creating a processor you have to pick an order of bytes. There is no advantage of one order above the other. The only exception would be when all bytes in the rest of the world would use the order and you would end up swapping constantly. |
|||||||||
|
|
The Japanese date convention is "big endian" - yyyy/mm/dd. This is handy for sorting algorithms, which can use a simple string-compare with the usual first-character-is-most-significant rule. Something similar applies for big-endian numbers stored in a most-significant-field-first record. The significance order of the bytes within the fields matches the significance of the fields within the record, so you can use a Flip the order of significance of the fields and you get the same advantage, but for little-endian numbers rather than big-endian. This has very little practical significance, of course. Whether your platform is big-endian or little-endian, you can order a records fields to exploit this trick if you really need to. It's just a pain if you need to write portable code. I may as well include a link to the classic appeal... http://tools.ietf.org/rfcmarkup?url=ftp://ftp.rfc-editor.org/in-notes/ien/ien137.txt EDIT An extra thought. I once wrote a big integer library (to see if I could), and for that, the 32-bit-wide chunks are stored in little-endian order, irrespective of how the platform orders the bits in those chunks. The reasons were...
This has no obvious relevance to processors, of course - until CPUs are made with hardware big-integer support, it's purely a library thing. |
||||
|
|
|
OK, here's the reason as I've had it explained to me: Addition and subtraction When you add or subtract multi-byte numbers, you have to start with the least significant byte. If you're adding two 16-bit numbers for example, there may be a carry from the least significant byte to the most significant byte, so you have to start with the least significant byte to see if there is a carry. This is the same reason that you start with the rightmost digit when doing longhand addition. You can't start from the left. Consider an 8-bit system that fetches bytes sequentially from memory. If it fetches the least significant byte first, it can start doing the addition while the most significant byte is being fetched from memory. This parallelism is why performance is better in little endian on such as system. If it had to wait until both bytes were fetched from memory, or fetch them in the reverse order, it would take longer. This is on old 8-bit systems. On a modern CPU I doubt the byte order makes any difference and we use little endian only for historical reasons. |
|||||
|
|
jimwise made a good point. There is another issue, in little endian you can do the following:
More straight forward for programmers which are not affected by the obvious disadvantage of swapped locations in the memory. I personally find big endian to be inverse of what is natural :). 12 should be stored and written as 21 :) |
|||||||||||||
|
|
Nobody else has answered WHY this might be done, lots of stuff about consequences. Consider an 8 bit processor which can load a single byte from memory in a given clock cycle. Now, if you want to load a 16 bit value, into (say) the one and only 16 bit register you have - ie the program counter, then a simple way to do it is:
the outcome: you only ever increment the fetch location, you only ever load into the low order part of you wider register, and you only need to be able to shift left. (Of course, shifting right is helpful for other operations so this one is a bit of a side show.) A consequence of this is that the 16 bit (double byte) stuff is stored in order Most..Least. Ie the smaller address has the most significant byte - so big endian. If you instead tried to load using little endian, you would need to load a byte into the lower part of your wide register, then load the next byte into a staging area, shift it, and then pop it into the top of your wider register. Or use a more complex arrangement of gating to be able to selectively load into the top or bottom byte. The result of trying to go little endian is you either need more silicon (switches and gates), or more operations. In other words, in terms of getting bang for buck back in the old days, you got more bang for most performance and smallest silicon area. These days, these considerations and pretty much irrelevant, but things like pipeline fill may still be a bit of a big deal. When it comes to writing s/w, life is frequently easier when using little ending addressing. (And the big endian processors tend to be big endian in terms of byte ordering and little endian in terms of bits-in-bytes. But some processors are strange and will use big endian bit ordering as well as byte ordering. This makes life very intersing for the h/w designer adding memory-mapped peripherals but is of not other consequence to the programmer.) |
|||
|
|
|
Big-endian is useful for some operations (comparisons of "bignums" of equal octet-length springs to mind). Little-endian for others (adding two "bignums", possibly). In the end, it depends on what the CPU hardware has been set up for, it's usually one or the other (some MIPS chips were, IIRC, switchable on boot to be LE or BE). |
|||
|
|
Decimal number are written big endian. It also how you write it in English You start with the most significant digit and the next most significant to the least most significant. e.g.
is one thousand, two hundred and thirty four. This is way big endian is sometimes called the natural order. In little endian, this number would be one, twenty, three hundred and four thousand. However, when you perform arithmetic like addition or subtraction, you start with the end.
You start with 4 and 7, write the lowest digit and remember the carry. Then you add 3 and 6 etc. For add, subtract or comparison, it is simpler to implement, if you already have logic to read the memory in order, if the numbers are reversed. To support big endian this way, you need logic to read memory in reverse, or you have RISC process which only operates on registers. ;) A lot of the Intel x86/Amd x64 design is historical. |
|||
|
|
|
When only storage and transfer with variable lengths are involved, but no arithmetics with multiple values, then LE is usually easier to write, while BE is easier to read. Let's take an int-to-string conversion (and back) as a specific example.
When the int is converted to the string, then the least significant digit is easier to extract than the most significant digit. It can all be done in a simple loop with a simple end condition.
Now try the same in BE order. Usually you need another divisor that holds the largest power of 10 for the specific number (here 100). You first need to find this, of course. Much more stuff to do. The string to int conversion is easier to do in BE, when it is done as the reverse write operation. Write stores the most significant digit last, so it should be read first.
Now do the same in LE order. Again, you'd need an additional factor starting with 1 and being multiplied by 10 for each digit. Thus I usually prefer to use BE for storage, because a value is written exactly once, but read at least once and maybe many times. For its simpler structure, I usually also go the route to convert to LE and then reverse the result, even if it writes the value a second time. Another example for BE storage would be UTF-8 encoding, and many more. |
|||
|
|
|
http://icu-project.org/docs/papers/forms_of_unicode/
|
|||||||||||
|