Executable files in Windows vs Linux

Dear experts

In the previous time,
I heard that executable files in Windows are able to run even in other machines (of course, OS version etc must be the same),
but those in Linux are not guarantee to run in other than its compiled machine.

Here, I wonder why Windows's executable make this transferability possible. CPU's instruction sets are determined in each CPU versions so that I think there must be some mechanism for translation of instructions (like virtual machine).

Though my question is misguided question, I hope you could teach me if you know the mechanism.

Kind regards
First of all, different operating systems use different file formats for their executable files. Windows uses the PE format (which comes as .exe files), while Linux uses the ELF format. That is the reason why Windows executable files cannot run on Linux and vice versa – except by an emulation layer like Wine – even when both file formats essentially contain compiled "x86" (or "x64") binary machine code.


Another important difference is the operating system's API. In Windows, applications use the Win32 API and/or COM interfaces to call services from the operating system, whereas Linux provides an API that is mostly POSIX compliant; even though Linux has many extensions that go beyond the POSIX standard.

😱 Neither has Windows a POSIX-compatible API, nor does Linux have a Win32 API. They're incompatible!


Windows executables certainly are not "automatically" guaranteed to run on every version of Windows that has ever existed! But it is relatively easy to make a Win32 executable that runs on all somewhat recent Windows versions, because there is only one "flavor" of Windows – the one that you can buy from Microsoft.

With Linux the situation is way more complicated/heterogeneous. That is because Linux is OpenSource, and because Linux is just a kernel. Linux is not a fully-fledged operating system by itself. Consequently, there are many different Linux distributions that create a "complete" operating system based on the Linux kernel – such as Debian/Ubuntu, RHEL/Fedora, Arch and many more – all of which are somewhat different !!!


Yet another thing to consider: On Windows, it is a common practice that executable files come "bundled" with all the required libraries (DLL files). Only some fundamental system libraries (kernel32.dll, etc. pp.) are provided by Windows itself. On Linux, however, it is common that all executables as well as all libraries are managed by the "centralized" package manager of the respective distribution. This can easily lead to library-incompatibilities, if you "transplant" a pre-compiled executable from one Linux distribution to another!

Anyhow, it is possible to create a Linux executable which runs on almost every Linux distribution that has a somewhat up-to-date Linux kernel. But, to make this possible, you need to link in all libraries statically. However, because glibc – the "default" C runtime library on most Linux distributions – is not well suited for static linking, you have to use an "alternative" C runtime library that supports static linking, e.g. musl.

https://musl.libc.org/


Finally, "container" technologies – like snap or flatpak – make it possible to package Linux executables in such a way that they can run on a wide range of different Linux distributions. But that's another topic.
Last edited on
Dear kigar64551

Thank you for your detailed reply.

I understand that some APIs in Win/Linux are fundamental to enable executable to run in other machines.

Here, I have an elementary question.
CPU has some specification for instruction sets (x86, x64 etc).
If these are the same, can executable run in different CPU machines for the same OS?
Or, do some instruction-set optimizations to fit a specific CPU disable the executables to run in others?


(Of course, I understand executable file format different in Win/Linux as PE/ELF, for which Win(or Linux) executables cannot run in another OS)
CPU has some specification for instruction sets (x86, x64 etc).
If these are the same, can executable run in different CPU machines for the same OS?
Or, do some instruction-set optimizations to fit a specific CPU disable the executables to run in others?

It depends ;-)

With "x86" we generally refer to the instruction set of the Intel "80386" (i386) processor and its descendants. Even modern "x86" (and "x64") processors are backward-compatible to the original i386 processor, but they also have many extensions that were added since then, such as MMX, SSE/2/3/4, AVX/2 and so on.

Not every CPU model supports every extension. An executable (or library) that is restricted to the "basic" i386 instruction set runs on any "x86" processor. However, if an executable (or library) contains machine code that uses a specific extension, then it will only be able to run on a CPU that supports, at least, that extension !!!

For example, if an executable (or library) contains machine code that uses AVX instructions, then that executable (or library) will only be able to run on CPUs that support, at least, AVX. It would simply crash, with "illegal instruction" exception, on CPU models that do not support the required AVX extension.

Be aware that extensions like SSE/2/3/4 and AVX/2 also require support from the operating system! That is because SSE introduced new "XMM" registers. And AVX introduced new "YMM" registers. The operating system (kernel) needs to be aware of those new registers, so that it can properly perform the context switch.

Finally, note that "x64" (64-Bit) processors are able to run old "x86" (32-Bit) code, but not the other way around! Also note that all "x64" (64-Bit) processors support at least the SSE and SSE2 extensions.

────────────────

As an aside: Some executables contains multiple "optimized" code paths for different instruction set extensions. For example, there could be one code path that uses only i386 instructions, one that is optimized with SSE2 instructions, and yet another code path that is optimized with AVX instructions. The executable could then decide, at runtime, which code path to run – depending on the respective CPU's actual capacities. This way you can get the "best" out of modern CPU models but still be able to run (though slower) on old CPUs.

On "x86" (and "x64") processors, the supported "capabilities" can be detected using the CPUID instruction:
https://en.wikipedia.org/wiki/CPUID

────────────────

All of the above was just a discussion about CPU instructions. But there are other reasons why an executable may not be able to run on a different (older) operating system version! For example, if an executable uses some Win32 API function that was introduced in Windows Vista, then that executable will not be able to run on Windows XP – simply because the required API function was not available yet in Windows XP :-(

Example:
https://i.imgur.com/87L0l3X.png
Last edited on
Topic archived. No new replies allowed.