5

32-bit application executables contain machine code for a 32-bit CPU, but the assembly and internal architecture (number of registers, register width, calling convention) of 32-bit and 64-bit Intel CPU's differ, so how can a 32-bit exe run on a 64-bit machine?

Wikipedia's x86-64 article says:

x86-64 is fully backwards compatible with 16-bit and 32-bit x86 code. Because the full x86 16-bit and 32-bit instruction sets remain implemented in hardware without any intervening emulation, existing x86 executables run with no compatibility or performance penalties, whereas existing applications that are recoded to take advantage of new features of the processor design may achieve performance improvements.

I don't understand what they mean by saying remain implemented in hardware without any intervening emulation. What does it mean?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
lychee
  • 1,771
  • 3
  • 21
  • 31
  • 2
    The 64-bit processor can run in 32-bit mode. – Raymond Chen Feb 03 '15 at 19:32
  • @RaymondChen can you elaborate? – lychee Feb 03 '15 at 19:33
  • 8
    This isn't really a programming question. It's a CPU design question. The point is that the 64-bit processor understands both instruction sets and can execute them both. It's like somebody who can speak both French and English. – Raymond Chen Feb 03 '15 at 19:39
  • 2
    It says the 32-bit processor instruction set is supported by the 64-bit processor, therefore these instructions don't require any form of emulation. – jweyrich Feb 03 '15 at 19:39
  • 4
    GDT and LDT entries have a bit that can be set to make it execute code as 64bit when CS refers that entry. If it is not set, code will be executed as 32bit. This means that far jumps/calls/returns can change between the two sub-modes of IA-32e mode. – harold Feb 03 '15 at 19:50
  • http://en.wikipedia.org/wiki/WoW64 – ASA Feb 04 '15 at 11:16

3 Answers3

9

The short answer is that the x86 family of processors were all designed to be backward compatible. The logic circuits that perform arithmetic and read/write operations in new CPUs are still capable of carrying out instructions designed for older CPUs while also carrying out newer instructions like 64-bit add and subtract.


If you want more history...

The x86 instruction set dates back to the mid-1970s, beginning with Intel's first 16-bit processor, the 8086. The general-purpose 16-bit (2-byte) registers on this CPU were called AX, BX, CX, and DX. The 8086 also allowed access to the high and low bytes of each register. For example, you could access the lower 8 bits of AX using the name AL, or the higher 8 bits using AH.

When Intel started developing new processors with new features, they wanted them to be backward compatible with the 8086 and any processors that came afterward. Next in line came the 80186, the 80286, and the 80386--the last of which was their first 32-bit processor.

Of course, all the registers on the 80386 had to be 32-bit, but it also had to be backward compatible with older x86 processors. So rather than replace the registers, Intel merely extended the existing ones to EAX, EBX, ECX, ...etc. (E meaning "extended"). The AX register is merely the lower 16 bits of theEAXregister, and is still accessible.

The same logic was followed with Intel's first 64-bit processor; the 32-bit EAX was extended to the 64-bit RAX and so on. The current x86-64 assembly language can still perform arithmetic operations on 32-bit registers using instructions like addl, subl, andl, orl, ... etc, with the l standing for "long", which is 4 bytes/32 bits. 64-bit arthimetic is done with addq, subq, andq, orq, ...etc, with q standing for "quadword", which is 8 bytes/64 bits.

EDIT: This pdf looks like it gives a good introduction to the differences between 32-bit and 64-bit x86 architectures.

eigenchris
  • 5,791
  • 2
  • 21
  • 30
  • 1
    +1 for the history, but how about calling convention? x86 heavily used stack to pass arguments, while on x64 Much of the program state is held in registers rather than on the stack. Integer and pointer procedure arguments (up to 6) are passed via registers. Some procedures do not need to access the stack at all. – lychee Feb 03 '15 at 20:15
  • 4
    @simple16 The x86-64 architecture does have 8 new registers, and from a little bit of reading I see that these are commonly used for storing function arguments. I don't see this as being a problem, though, as any program compiled for a 32-bit architecture can just use the stack for its function calls while 64-bit programs can use the new method. Also it's really the compiler for a language that chooses how to use the stack/registers for its calling convention. There isn't one single correct way to do things. – eigenchris Feb 03 '15 at 21:41
  • 5
    The 64-bit extension was developed by AMD, actually. Still, the point about backwards compatibility holds. – W.B. Feb 03 '15 at 22:11
  • @W.B. Very true! :) Intel originally tried to make a 64-bit instruction set that was not backward compatible with the x86 instruction set, which didn't turn out to be a very popular decision, so AMD developed x86-64 (now called AMD64) to try and take advantage of a market that wanted it. – eigenchris Feb 03 '15 at 22:17
4

Instead of just extending 32-bit Protected mode, long mode is a separate mode that 64-bit kernels switch to during bootup. When in long mode, the CPU decodes machine-code read from memory as x86-64 instructions.

There's a Compatibility Mode that lets a 64-bit kernel run 32-bit user-space processes. This is what "no emulation" means. The CPU hardware directly reads and decodes x86-32 machine code in compat mode the same way it would if the machine had never switched to 64-bit mode at all during bootup. (i.e. what the 64-bit manuals call legacy mode).

When an interrupt or system call happens in a user-space process running in compat mode, the CPU switches to long mode while jumping to the kernel's interrupt or system-call entry point. This is the key to the "no emulation" claim: there's hardware support for having 32-bit processes efficiently interact with a 64-bit kernel using the same mechanisms as on a purely 32-bit system.

Wikipedia has a table of modes the CPU can be in.

Default installs of most versions of most major x86-64 OSes come with support for running 32-bit x86 binaries (libraries, and a kernel that supports the 32-bit system call interfaces). There's basically no extra overhead even on system calls. In Windows, this is called WoW64 (Windows on Windows64).


Note that x86-64 machine code could have been designed to be totally different from 16/32-bit machine code. The main reason they're extremely similar is so the CPU can share most of the instruction-decoding hardware between modes.

(When they designed it, AMD wasn't even sure that Intel would ever adopt AMD64, and they didn't want to risk being stuck using a lot of transistors for AMD64 instruction-decode hardware in future CPUs if it didn't catch on. I suspect this is why they were so conservative about not cleaning up as much x86 legacy baggage as they could have. e.g. dropping more less-used one-byte instructions to free up space for shorter encodings for more-useful instructions, and future extensions.)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
-1

One difference between 32-bit and 64-bit programs are the new instructions for moving or calculating with 64 bits. Those new instructions uses opcodes or arguments that weren't used in 32-bit programs. The older instructions are implemented with the same opcode they were implemented in older CPUs, so there isn't conflict*.

The other difference is the new 64-bit addressing mode. While loading an executable in memory, the OS sets the addressing mode to 32-bit or 64-bit. Everytime Windows switches between two processes (which happens many times in a second), Windows changes the addressing mode for the usermode applications. Windows itself uses the kernelmode addressing mode.

*EDIT: There are some conflicts due to changed or removed opcodes.

Van Uitkon
  • 356
  • 1
  • 6
  • 2
    There are many conflicts actually. For example the 1-byte encoding of `inc` and `dec` (REX prefixes in 64bit mode), instructions that were removed entirely sometimes with new instructions taking their opcode (`arpl = movsxd`), instructions that are 64bit by default (`push`, `pop`, `call`, `ret`), and the encoding of an `[dword]` operand without using a SIB byte – harold Feb 04 '15 at 09:09
  • Instead of further extending the same mode, "long mode" is a separate mode that the CPU switches to for running 64-bit code. There's a compat mode that lets a 64-bit kernel run 32-bit user-space processes, with the CPU switching modes on interrupts and system calls. So the two instruction sets don't have to be binary-compatible. The main reason they're extremely similar is so the CPU can share most of the instruction-decoding hardware between modes. It's not just a different default address-size. – Peter Cordes Sep 18 '16 at 21:44