Skip to content

Comment on On Endianness (2021)

Comments

OK, temporarily-victorious little-endians: Explain how you find it perfectly natural that the bits in a byte are big-endian?

[Various replies (and votes) indicate I had better edit to clarify:] How come the single byte value written as 0x12 means "eighteen" and not "thirty-three"? Shouldn't the two four-bit nibbles also be considered as little-endian? Or it could even mean "seventy-two", if the bits are little-endian as a whole?

As a thought experiment, how do you know that bits within a byte are ordered big endian? does it have to do with the result of casting a unsigned char[4] to an unsigned int or something? I forget.

Because if it's just that the name "left shift" corresponds to an operation that multiplies by two and vice-versa, you could probably just swap the names "left/right shift" and be none the wiser.

Edit: the point I'm making is that you need to use either a left/right shift to extract individual bits from a byte B, or calculate some AND(B, L) where L is some literal like 0x4 (in which case it depends on how you write the literal's bit order).

When you write "0x12" you're confusing the "visible representation" with the hardware representation. The whole endianness discussion is around how the hardware counts them. I believe that with the exception of some IBM hardware, bit n has always had weight 2^n, which is basically the little-endian convention.

Clarifying my point further: Let's say I'm looking at a hex dump of memory contents (as you still can do in gdb and lldb with "p/x"). The debugger shows me four consecutive bytes as: 0x89ABCDEF. If I'm on a big-endian IBM 360, I can say to myself "to figure out what integer that is, I'll compute 8<<28 + 9<<24 + A<<20 + B<<16 + C<<12 + D<<8 + E<<4 + F<<0". Nice sequence of shift amounts, decreasing by four for each single-hex-digit in order. If I'm on a little-endian 8008, I have to compute "F<<24 + E<<28 + D<<16 + C<<20 + B<<8 + A<<12 + 9<<0 + 8<<4". Not such a nice sequence of shift amounts. So, my question is, why don't true little-endians say it should be F<<28 + E<<24 + D<<20 + C<<16 + B<<12 + A<<8 + 9<<4 + 8<<0?

Succinctly, why is the big-endian number 0x01234567 not known as 0x76543210 to little-endians? Why are they OK in calling it 0x67452301? That sure looks like a mix of big-endian nibbles in the little-endian bytes.

The debugger shows me four consecutive bytes as: 0x89ABCDEF

That means it has already interpreted it as one quantity, so at that point endianness is completely irrelevant.

Succinctly, why is the big-endian number 0x01234567 not known as 0x76543210 to little-endians?

Once again you are mixing up the visual representation with the in-memory. There is no such thing as "the big-endian number" or "the little-endian number". You have already written an indivisible number, and interpreted it according to the human convention.

Ok, sorry I said "0x89ABCDEF" rather than "0x89 0xAB 0xCD OxEF" to make it clear that it is not "already one quantity", but an ordered sequence of four bytes (though it is how p/x displays it).

How about this way: The decimal number 19088743 is stored in a 32-bit memory word on a big-endian machine. When asked what the four consecutive bytes are, from low address to high, the debugger displays "0x01, 0x23, 0x45, 0x67".

Now, let's put that same decimal number into a 32-bit memory word on a little-endian machine. When asked what the four consecutive bytes are, why does the debugger not display "0x76, 0x54, 0x32, 0x10"? That's what would happen on a truly little-endian hardware system, as used by little-endian human thinkers, expecting a little-endian human display convention. Instead, it displays the weird hybrid "0x67, 0x45, 0x23, 0x01" version. Why aren't the humans who like little-endian not bothered by the fact that the human convention is not completely little-endian, and shows the two hex digits within each byte with a big-endian human display convention?

Or, how about this: We all agree that decimal numbers as currently written by humans follow big-endian conventions. Certainly someone could come along and claim that they preferred little-endian representation for decimal numbers, so that one thousand two hundred thirty four should be shown as 4321 rather than 1234. Great; good luck to them. But if they said that they're actually going to write it as 3412, I hope we'd agree that they weren't really following little-endian conventions for displaying values for human consumption.

So, yeah, I'm complaining that the current widely accepted human convention for little-endian display is not self-consistent and not fully little-endian. And, you're right, it has nothing to do with the actual hardware, which doesn't care how we display stuff.

Now, let's put that same decimal number into a 32-bit memory word on a little-endian machine. When asked what the four consecutive bytes are, why does the debugger not display "0x76, 0x54, 0x32, 0x10"? That's what would happen on a truly little-endian hardware system, as used by little-endian human thinkers, expecting a little-endian human display convention. Instead, it displays the weird hybrid "0x67, 0x45, 0x23, 0x01" version. Why aren't the humans who like little-endian not bothered by the fact that the human convention is not completely little-endian, and shows the two hex digits within each byte with a big-endian human display convention?

Because from a hardware architecture perspective, a single byte is a single digit. The order of the bits within that digit has no bearing upon the programmer. A debugger just converts the bits to a human readable format, be it decimal, hexadecimal or whatever. If you ask GDB nicely, it can print them out as decimal for you, through the "x/4db" command. You can also get it to show you the entire thing in big endian hex through "x/1xw". You're essentially complaining about the single-digit view using multiple digits for human readability.

Exactly. It has nothing to do with hardware. I am complaining about the inconsistency in the single hex digit, two ascii character, view.

Why don't people who claim to prefer little-endianness actually follow through and display these two ascii characters in a little-endian order? Why do people who like little-endian not prefer the human readable hexadecimal display of eighteen to be 0x21 rather than 0x12? If these humans really prefer little-endian human readable hexadecimal display of multi-byte values, then why don't they also prefer little-endian human readable hexadecimal display of the two four-bit nibbles in single-byte values?

How is it consistent that little endian people say "0x0A0B" means "eleven times two to the eighth power, plus ten"; but they don't say that "0xAB" means "eleven times two to the fourth power, plus ten"?

In what world does it make sense that the ordering of the ascii characters that represent each 4-bit nibble of a multi-byte value hops back and forth between being less significant and more significant as you read them left to right?

Good point. Do any popular hex editors have options to display hex values with the most-significant digit on the right? Or, alternately, to display memory right-to-left so that the lowest memory addresses are on the right side and the highest on the left?

The bits in a byte do not have a defined endianness!

Most CPUs have assembly instructions called something like "shift left/right" or "rotate left/right". That implies an endianness, and it is (to my knowledge) always the endianness of normal written numbers - most significant is "left". That is, big endian.

Bit-endianness is only relevant for serial transmission. You only have to worry about it in circumstances where you have hardware that assumes a different bit order than what you're communicating with. Otherwise, the internal layout of words is abstracted and you can ignore it.

It's relevant when dealing with the control registers of peripherals, even if that's over a parallel bus. It's at least important that you have the same bit order as the peripheral.

I seem to recall discussion of this in the RFC. They do ultimately have an order if transmitted over a network!

But most of us are used to getting them a byte at a time through the memory interface so we are ignorant of this.

They do ultimately have an order if transmitted over a network!

They do if transmitted over a serial port. But today's networks encode whole bytes or more into the symbols actually sent over the wire/air, so there's not really any way to point out on an oscilloscope trace where particular bits out of a byte are sent in a specific order.

Wow! I didn’t know that

Bit 0 is the LSB. The bits in a byte are little endian.

not on all machines (cough IBM cough ...)

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.