Live data from Hacker News

X86 Register Encoding

eklitzke.org

41–50 of 54 posts

Re: X86 Register Encoding

#41
post #16
post #13

Earlier quoted context omitted.

> In fact, the average size of each instruction is almost exactly 4 bytes I was curious about this claim so I wrote a quick and dirty perl script to test it out: vmlinuz-linux = 2.71957329365681 bash = 3.95324321387071 firefox = 3.56640365053712 geany = 3.44776119402985 gzip = 4.17925462998247 perl = 4.10894941634241 python = 3.82481751824818 tar = 3.93348845041101 thunar = 3.82471016115786 radeon_drv.so = 4.02697782…

The kernel is compiled with -Os for code size last I checked (which was long ago) so that might explain the difference.

I wonder if that flag does anything at the instruction encoding level

Re: X86 Register Encoding

#42
post #36

Earlier quoted context omitted.

no, the compiler does this when generating code for functions and function calls crt0.o is the glue between how the kernel loads a program into memory and how main() expects things to work. it does basic setup tasks that can vary between platforms, but is generally things like collecting command line arguments and setting up the stack. it will also invoke exit() if main() returns, since that's how the kernel expects…

Thanks for the response. When you say "how the kernel loads a program into memory" I assume you are referring to ld-linux.so.2? Is that correct? I imagine then that ld-linux.so.2 calls __start in crt0.o and crt0.o jumps to main(). Is this correct?

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.g... load_elf_binary()

maps the executable to memory, and if an elf interpreter (/lib/ld-linux.so) is specified (which it normally is) also the elf interpreter.

It then jumps to the entry point of the raw binary or of the elf interpreter.

Re: X86 Register Encoding

#43
post #13
post #2

LLVM doesn't actually prefer the lower registers when doing register allocation. IIRC, sunfish told me that GCC doesn't either. It would be interesting to add features that try to minimize code size to the register allocator, but no compiler I know of actually does this. Partially as a consequence of this, the REX prefixes take up a lot of space in most x86-64 instruction streams. In fact, the average size of each in…

> In fact, the average size of each instruction is almost exactly 4 bytes I was curious about this claim so I wrote a quick and dirty perl script to test it out: vmlinuz-linux = 2.71957329365681 bash = 3.95324321387071 firefox = 3.56640365053712 geany = 3.44776119402985 gzip = 4.17925462998247 perl = 4.10894941634241 python = 3.82481751824818 tar = 3.93348845041101 thunar = 3.82471016115786 radeon_drv.so = 4.02697782…

Interesting, would you mind sharing the script or give a short overview how it works?

Re: X86 Register Encoding

#44

Earlier quoted context omitted.

And the market also chose ARM's AArch64 instruction set, despite the ARM installed base being wider than x86 and a backwards incompatible break from the past. The secret? Supporting both ISAs and switching instruction sets on exceptions. The lesson I take from history is that there is no need to maintain ISA compatibility as long as the old mode is accessible on a process level.

>The secret? Supporting both ISAs and switching instruction sets on exceptions. The secret is that Apple controls their hardware/appstore and android apps are ISA independent.

Whot?

Didn't the AMD64 architecture spank Itanium in the marketplace long before the iPhone became a big deal?

Re: X86 Register Encoding

#45
post #39
post #31

Earlier quoted context omitted.

Well, not lawyers directly. More through lack of cooperation (due to competitive mentality). http://www.agner.org/optimize/blog/read.php?i=25

I don't see how that matters in this case, AMD took the lead on AMD64 and Intel had to copy them afterward. They really could have done anything they wanted. As someone else here mentioned it was probably more to re-use the existing investment in x86 decoders.

Amd64 encoding, as is the case with most x86 encodings, is longer then it should be. Due to the two companies not communicating/cooperating.

That is the one advantage that i think ARM has over x86/amd64. That ARM encoding is much shorter.

Re: X86 Register Encoding

#46
post #24
post #6

Earlier quoted context omitted.

They probably wanted to re-use most of the x86-32 decoder that they had on the chip anyway. Kind of strange, nowadays, an embedded armv8 cpu will come with multiple decoders (ARM32, thumb2, AARCH64).

This. In today's world it is easy to support multiple instruction sets in the same silicon using the same registers and ALU. So why in the name of all that is holy does the x86 not have a nice clean 64-bit instruction set that you can swap in? It's all RISC under the hood anyway, why not give us access to it? The only explanation I can think of is that Intel wants to keep things complicated as a barrier to entry for…

> It's all RISC under the hood anyway, why not give us access to it? The only explanation I can think of is that Intel wants to keep things complicated as a barrier to entry for competition.

It wasn't Intel but AMD that came up with x86-64. Intel (and HP) indeed wanted to give you a clean 64-bit design - Itanium. And yes, it was meant as a barrier to entry among other things. But AMD won because Itanic didn't run existing x86 software and generally turned out to be slower than Intel hyped.

As for the internal RISC, you won't get it because it changes from generation to generation (also between vendors) and these changes are part of why x86 keeps getting faster. Furthermore, AFAIK these internal ops aren't as dense as x86 to make them simpler to decode and fetching them from memory would make bandwidth more of a bottleneck.

Re: X86 Register Encoding

#47
post #42

Earlier quoted context omitted.

Thanks for the response. When you say "how the kernel loads a program into memory" I assume you are referring to ld-linux.so.2? Is that correct? I imagine then that ld-linux.so.2 calls __start in crt0.o and crt0.o jumps to main(). Is this correct?

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.g... load_elf_binary() maps the executable to memory, and if an elf interpreter (/lib/ld-linux.so) is specified (which it normally is) also the elf interpreter. It then jumps to the entry point of the raw binary or of the elf interpreter.

> if an elf interpreter (/lib/ld-linux.so) is specified (which it normally is)

I think your "normally" means "in case of dynamically linked executables".

Re: X86 Register Encoding

#48
post #42

Earlier quoted context omitted.

Thanks for the response. When you say "how the kernel loads a program into memory" I assume you are referring to ld-linux.so.2? Is that correct? I imagine then that ld-linux.so.2 calls __start in crt0.o and crt0.o jumps to main(). Is this correct?

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.g... load_elf_binary() maps the executable to memory, and if an elf interpreter (/lib/ld-linux.so) is specified (which it normally is) also the elf interpreter. It then jumps to the entry point of the raw binary or of the elf interpreter.

Thanks, right, if there is a PT_INTERP header in the binary that specifies ELF then load_elf_binary() will be called.

Its easy to sometimes conceptually think or talk about "a loader" as if its some standalone entity. However this can be misleading(at least to me anyway.) Because in reality its linked into every dynamically-linked binary, along with crt0.o which as the other poster mentioned takes care of some ABI requirements and the setting up of the stack.

For anyone else who might be interested this also an illuminating source code file to read, libc-start. Which would be part of crt0.o

http://repo.or.cz/glibc.git/blob/HEAD:/csu/libc-start.c#l105

I don't have to think this low level on any kind of regular basis but its a great thought exercise to do so from time to time.

Re: X86 Register Encoding

#49
post #45
post #39

Earlier quoted context omitted.

I don't see how that matters in this case, AMD took the lead on AMD64 and Intel had to copy them afterward. They really could have done anything they wanted. As someone else here mentioned it was probably more to re-use the existing investment in x86 decoders.

Amd64 encoding, as is the case with most x86 encodings, is longer then it should be. Due to the two companies not communicating/cooperating. That is the one advantage that i think ARM has over x86/amd64. That ARM encoding is much shorter.

You just repeated your point without adding anything new, that doesn't help your argument.

Re: X86 Register Encoding

#50
post #43
post #13

Earlier quoted context omitted.

> In fact, the average size of each instruction is almost exactly 4 bytes I was curious about this claim so I wrote a quick and dirty perl script to test it out: vmlinuz-linux = 2.71957329365681 bash = 3.95324321387071 firefox = 3.56640365053712 geany = 3.44776119402985 gzip = 4.17925462998247 perl = 4.10894941634241 python = 3.82481751824818 tar = 3.93348845041101 thunar = 3.82471016115786 radeon_drv.so = 4.02697782…

Interesting, would you mind sharing the script or give a short overview how it works?

Here it is (warning: Perl): http://pastebin.com/MFmDzY0g

It calls "objdump -d" on the binary, which is binutil's disassembler.

objdump prints each instruction out in the following format:

     5dc:       67 80 7d 00 00          cmpb   $0x0,0x0(%ebp)
The first part is the instruction offset; the second is the bytes that comprise the instruction; the third part is the instruction in AT&T assembly syntax.

The script uses regexs to cut off the front and back, then counts the number of bytes (in hex format) in the second part.

Then it calculates the average for all instructions.

Post reply on HN