don't click here

Big Endian or Little Endian?

Discussion in 'Engineering & Reverse Engineering' started by LOst, Sep 25, 2005.

Big Endian or Little Endian?

  1. Big Endian CPU

    0 vote(s)
    0.0%
  2. Little Endian CPU

    0 vote(s)
    0.0%
Thread Status:
Not open for further replies.
  1. LOst

    LOst

    Tech Member
    4,891
    6
    18
    Read what they all mean here:

    Everyone that has used a hexeditor knows what this is. Let me refresh your memory:

    Big Endian is what the Genesis CPU (Motorola 68000) uses. When you see a hex WORD value $112 in a hexeditor, you will see it as 01 12. When you see a hex LONG WORD value $1126C in a hexeditor, you will see it as 01 12 6C.
    Big Endian is easy to read in a hexeditor, as it shows up exactly as the original value. However there is a big side effect to Big Endian programming wise. It has to do with offsets. You all know that you can access Sonic's X coordinate at RAM offset $FFD008. No you didn't? Anyway, this value is a 1.15.16 fixed point, but at some pont this value can be read as 1.15 fixed point, or just the left over fractal value 16, simply a LONG WORD value. However to get the fractal WORD value from Sonic's X coordinate, you can't access it from Sonic X coordinate offset $FFD008, so you need to add 2 to it like this: $FFD00A. But this is no longer Sonic's X coordinate, it is the screen space Y coordinate for objects in screen space. So we have a position conflict. Big Endian may be good while reading one value with the same size. You can always load the value as a LONG WORD and use AND to make it into a WORD, but you will waste a whole register and you will also waste ROM space and CPU cycles.

    Little Endian is what your computer uses. When you see a hex WORD value $112 in a hexeditor, you will see it as 12 01. When you see a hex LONG WORD value $1126C in a hexeditor, you will see it as 6C 12 01. The values are byte swapped.
    This makes Little Endian really hard to work with in hexeditors because you have to guess the WORD size, and then search the value byte swapped. I do this a lot when I hack Windows programs, or Playstation arcade hardware games, or GBA games. They all use Little Endian because it is better for the programmer.
    Now you can use the same offset no matter what WORD size you are reading, or writing (Well an exception will occur if you write a size that you are not allowed to write, or read for that matter depending on the current CPU settings). Remember that the bytes are swapped, so that if you read a BYTE from the value 1126C, you will get 6C. If you read a WORD from the value 1126C, you will get 126C, because they come in that order. You can get those values from the same offset. You just specify the size and get that value. Remember that a LONG WORD value of $16 will show up as 16 00 00 00 in a hexeditor, and when you read the value from your program, you can specify the size to be a BYTE, WORD, or LONG WORD, use that same offset, and you will always get $16!

    Yes, byte swapped is always stored byte swapped. As soon as you have got it into a CPU register, you will read it like if it was Big Endian, even though it is byte swapped. This is actually just an effect by the CPU debugger, or your program, to show the value like Big Endian even if the real value is always byte swapped.

    EDIT: Typos and Typos
     
  2. LOst

    LOst

    Tech Member
    4,891
    6
    18
    I choosed Little Endian. I have even seen a Genesis Sonic game that worked with Little Endian, and that was an experience.
     
  3. Tweaker

    Tweaker

    Misfit
    12,389
    1
    0
    I pick little endian. It may be harder to read, but I've coped with that and would rather pick efficiency over simplicity.
     
  4. Heran Bago

    Heran Bago

    Ah! It's Puyo battle then. Tech Member
    I've never understood why little endian could be easier on hardware than big endian. Why is it easier for a programmer to have to swap bytes?

    I chose big because it's just more sensible to me. Plus, if you want to swap bytes, it takes a fraction of a second of thought. Those fractions add up!
     
  5. Mask of Destiny

    Mask of Destiny

    Tech Member
    87
    0
    6
    I believe little endian is a relic from 8-bit CPU design. Most CPUs of that era were pretty much completely 8-bit internally, but they often supported a limited number of 16-bit operations. Generally speaking, when you do an operation that's bigger than your ALU can handle, you do the least significant byte first (since you need to know whether there's a bit that get's carried into the next most significant byte). Since you're doing the LSB first, it's easier to have the LSB first in memory.

    Of course, once you get into 32-bit CPUs (like the 68000) this is no longer an issue because the ALU can do a whole 32-bits at the same time (and 64-bit math isn't common enough to make it worthwhile to bend over backwards for it). If it hadn't been for the popularity of the IBM PC (and Intel's subsequent decision to keep pushing x86 forward) little endian would be long dead by now. The only reason you see it popping up in ARM based PDAs is that it's inefficient to work on a little-endian file on a big endian machine and PDAs have to increasingly deal with files created on PCs.

    @LOst
    In your example of a fixed point number, it's just as conceivable that I would need to access just the integral part of the number in which case you'd have the same problem on little endian. It's a wash either way and since most computers have fast FPUs these days, it's rare to use fixed point at all.

    Personally I think little endian should have died a long time ago. Of course, I also think that the 68K should have taken over the computer world instead of x86, but alas...
     
  6. Sonic 65

    Sonic 65

    Tech Member
    I choose Little Endian. After all, if you want to hack any game in hex, you have to learn to deal with it. =P

    And it's also efficient.
     
  7. Aurochs

    Aurochs

    Единый, могучий Советский Союз! Tech Member
    2,343
    0
    0
    Whatever catches my fancy
    What? Why the hell would the program use the lower word of some variable as a completely different variable? That makes absolutely no sense. Furthermore, X coordinates are represented as words, IIRC. There should be no reason to store Sonic's X position in a longword.

    And how is little endian representation more efficient, exactly? I don't see any efficiency gains that can't be had through good programming practice on a big endian machine.
     
  8. Ultima

    Ultima

    Games Publisher Tech Member
    2,398
    1
    18
    London, England
    Publishing mobile games!
    If you're storing a huge array of general purpose variables (16 word values per object on screen, say, and up to 128 objects on screen), then you wanna save as much space as possible (when dealing with limited RAM - like on consoles). So, you could split one word up and use it as two byte values - but since it's an array (to make it easier to program I guess - using a struct would mean you're limited to those types for every object, with this you can do it on a per obejct basis if and when you need it) you have to do it manually with >> and &. I think that's what LOst was talking about.
     
  9. Kles

    Kles

    Member
    This is why I'll never be a good hacker. I have no clue what you're talking about - all I know is big endian is in "simple" order and little endian is flipped weirdly (34128756 for the win...) so I chose big endian.
     
  10. Quickman

    Quickman

    be attitude for gains Tech Member
    5,596
    18
    18
    :x
    omg porjcet
    I choose big-endian - the performance hit on older processors is worth the ease-of-reading for the layman in my opinion.
     
  11. drx

    drx

    mfw Researcher
    2,248
    325
    63
    :rolleyes:
    YES! 68k all the way. x86 sucks ass ;)

    And yeah, big endian. I'm the genesis hacker :P
     
  12. LOst

    LOst

    Tech Member
    4,891
    6
    18
    It is very common in C/C++ to do a type cast like this:
    Code (Text):
    1. unsigned char byte = (unsigned char) word;
    Little Endian disassembly of the code above (Made in M68k assembler even if that is not possible):
    Code (Text):
    1. movea.l byte,a0
    2. movea.l word,a1
    3. move.b (a1),(a0)
    or having byte value in D0 and word value in D1:
    Code (Text):
    1. move.b d1,d0

    Big Endian disassembly of the code above:
    Code (Text):
    1. movea.l byte,a0
    2. movea.l word,a1
    3. move.b 1(a1),(a0)
    or having byte value in D0 and word value in D1:
    Code (Text):
    1. move.w d1,d0
    2. lsr.w #8,d0
    This will work so much faster, and better with Little Endian since the CPU doesn't have to shift the word before moving it into the byte.
     
  13. Ultima

    Ultima

    Games Publisher Tech Member
    2,398
    1
    18
    London, England
    Publishing mobile games!
    Well, it's actually a difference of a few cycles, but in a few cases that could make a big difference. And there is also the fact that if you use Little Endian everyone, those few cycles will start adding up =P
     
  14. Mask of Destiny

    Mask of Destiny

    Tech Member
    87
    0
    6
    This is incorrect. move.b d1,d0 already moves the least significant byte. The code you have would put the most significant byte into d0 which is not the equivalent of the C code you have there.

    Little endian versus big endian only effects how data is stored in memory, not how it's stored in a register.

    In good C programming practice, most variables are local variables and are therefore referenced via a displacement of the stack register (a7) so the point is moot. Both the source operand and destination operand would have a displacement value in both bit and little endian processors.

    Even if they were both global variables there are very few situations in which the compiler would generate code like that. It's also possible that on later members of the 68K family there is no penalty for the Address register Indirect with Displacement mode. On the 68000, that mode requires an extra read from memory (since the data bus is only 16-bit) and on the 68000 that means an extra 4-cycles. Later members of the 68K family had a 32-bit data bus, so this is less likely to be a problem.

    It should also be noted that although casts are relatively common, they tend not to occur in loops which is where you tend to care about just a few cycles here and there.
     
  15. Tweaker

    Tweaker

    Misfit
    12,389
    1
    0
    Yeah, as far as I knew, Little Endian processors read the data/pointers backwards, then byteswapped during the processing cycles. I'm not exactly sure of the specifics, though.
     
  16. Hivebrain

    Hivebrain

    Administrator
    3,010
    99
    28
    53.4N, 1.5W
    Github
    I don't think you can do LSRs with more than #7.
     
  17. Quickman

    Quickman

    be attitude for gains Tech Member
    5,596
    18
    18
    :x
    omg porjcet
    With a word value wouldn't the limit be 15?
     
  18. Mask of Destiny

    Mask of Destiny

    Tech Member
    87
    0
    6
    The limit is 8. It's encoded as a three bit value, but since a rotate or shift of 0 is useless, one is added to the value so you get a range of 1-8. To get larger rotation values requires that you use a data register for the shift operand.

    @Quick Man
    In this case, the .w refers only to the value being shifted (d0), not to the operand for the number of bits to shift. In an effort to stuff the instruction into a single word, you only get 3 bits when you're using an immediate value for the shift count.
     
Thread Status:
Not open for further replies.