I Compiled a small "Hello World" Program in GCC & it worked in Linux. Then i added .exe extension to the program, to see if it works with windows or not. But it did not work. Whats the reason for the program to not work in windows. Basically the Binary & assembly instructions are same in the Programs compiled under windows & linux (If OS specific library not used). The OS has to just load the Program in the RAM & processor will execute it. So, why does it not work.
-
2Please show us the code – Lithu T.V Nov 04 '13 at 11:07
-
3@LithuT.V a good joke! – vines Nov 04 '13 at 11:09
-
@LithuT.V No need for code. – m0skit0 Nov 04 '13 at 11:13
-
1I asked for the code jus to make sure how he did without os support capabilities. – Lithu T.V Nov 04 '13 at 11:15
-
3There is a whole spectrum of reasons why this won't work. (system arch, system libaries/headers, processor architecture linker itnerface implementation defined behavings and much more...) – dhein Nov 04 '13 at 11:15
-
@LithuT.V *Then i added .exe extension to the program*. That's all. – m0skit0 Nov 04 '13 at 11:21
-
hehe .. there i am dead!! – Lithu T.V Nov 04 '13 at 11:24
-
My friend have had similar problems years ago, she tried convert a JPG file to GIF, but she failed. She did it with F6, which not works. – ern0 Nov 04 '13 at 11:58
4 Answers
I'll break down your question into smaller subsets
I Compiled a small "Hello World" Program in GCC & it worked in Linux.
This is to be expected, as the usual GCC and binutils installed on the system are configured to compile for the same target and host as they're executed on. Or in layman terms, they will produce an executable suitable for the Linux kernel and the GNU C standard library (or a compatible libc) runtime.
There are also compilers that can build programs to run on a different kind of operating system and/or CPU architecture, than they themself are executed on. Those are so called cross-compilers and you're using them for example to build Smartphone Apps on your Desktop computer. When you create a native Android executable using the Windows Android NDK, you're actually cross-compiling for a Linux kernel and a different CPU (most likely ARM or MIPS).
Then i added .exe extension to the program, to see if it works with windows or not.
Here you fell for one misconception, I'll never understand why it came to be in the first place. That the file name suffix had to do anything with what it can do. Windows uses it to look up in the registry, what to do with it, but that's it. In Windows you can register any suffix you want to be recognized as being "executable". Linux (being a Unixoid) does something simpler, but IMHO more powerfull: Each file carries a set of flags, if it can be executed, and if so, who actually can do it.
But to be actually usefull for the system as a program that can be run, something different is required, and that all executables (for a given OS) share, regardless of their file name: A specific internal format. Windows uses the so called PE
format (PE stands for portable executable, which is a bit laughable, because the only OS supporting it is Windows). Linux and the *BSDs use ELF (Executable and Linkage Format) and MacOS X uses something called the Mach Binary Format with the transistion to Intel CPUs extended into the Mach Universal Binary format. Technically the Mach kernel (the foundation of MacOS X) could also understand the ELF format, but that's AFAIK not enabled in MacOS X.
While both file formats essentially do the same thing (describing how to load the file into memory, which libraries it depends on, that must be loaded, and where to load them, which point of the program to actually start) their structure is very different. Windows doesn't know how to load and execute ELFs and Linux doesn't know how to load and execute PEs.
And even if either had support for the other, the systems would still lack the libraries the program expects to load and run on. At least you need the (operating system) dependent runtime environment, which is responsible for such "mundane" things as retrieving the startup parameters from the OS, provide an interface to the OS specific memory management functions, etc., etc. Those also fundamentally differ between Linux and Windows.
Note that is perfectly possible to provide a compatibility wrapper, built on top of the OS specific stuff, that emulates the other OS to a program, and that also knows how to load, link and launch a foreign executable. The wrapper to load and execute Windows programs on Linux is called WINE, and there also exists the reverse thing called LINE, that runs Linux executables on Windows.
But it did not work. Whats the reason for the program to not work in windows.
Windows is different from Linux. It has a completely different system level API, it uses a different binary format and even such essential things like stdin/stdout (as defined by the C standard library) are implemented very differently. Heck, they even use different calling conventions
Linux uses the standard C calling convention (stdcall). Windows uses mostly the cdecl convention, which is kind of a hybrid of the pascal and the stdcall convention.
Basically the Binary & assembly instructions are same in the Programs compiled under windows & linux (If OS specific library not used).
Uh, no they're definitely not. The differences in the calling convention allone produce different assembly.
The OS has to just load the Program in the RAM & processor will execute it.
It's not that simple. The program also has to be "connected" to the operating system, to do anything useful. You want to see a string printed on the console? Then you must connect it to some operating system functions, that do that.
In Linux the console is already there, and there are the special files /dev/console
, /dev/stdin
, /dev/stdout
, /dev/stderr
, which are internally tied to the current pts
or tty
. Within the process those are always mapped to file descriptors 0, 1 and 2.
In Windows a program may, or may not have to open its own Console Window (if it's started from a CLI it will use that). So it must call AllocConsole
and if that failed as a fallback AttachConsole(parent_PID)
; then it can use GetStdHandle
to get stdin, stdout, stderr. The HANDLE
s this gets are arbitrary and need to be connected to the internal implementation of C stdio (printf, fwrite and so on) and C++ iostream.
Also the CPU won't "magically" execute a piece of binary, just because it ends up somewhere in the RAM. The operating system must create a new process, and to do that it must know at which places of the binary certain vital code rests (entry points). Those entry points are described (among other things) in a special place of the binary file format. And as I already explained, Windows understands only a very different executable binary format (PE) than Linux does. And once the binary has been loaded and linked, it must be actually started. The steps to start a binary are also different between Linux and Windows as outlined above.
Late EDIT, but it has to be written:
*Also it's very important to understand that the binary of an executable isn't loaded wholly into the RAM at all, when a program gets started. What happens is, that a so called "virtual memory mapping" is created. This means that a virtual address space is created by the operating system, and together with a few other data structures this is what's commonly called a process. The virtual address space in turn is backed by a set of so called "pages", which are chunks of address space which are mapped to actual memory or storage devices. In fact usually RAM is always used as a cache for disk operations. When the program binary is mapped the virtual memory pages will always point to the disk storage and the RAM acts merely as a cache for that. Dynamically allocated memory is taken from the disk cache that's caching the swap space on the storage device. If there's no swap device, then it's just taken from the general purpose disk cache.*
As you can see these are entirely different lists of tasks to perform. Add to that the differences in calling convention and binary format.
So, why does it not work.
Because there's more to an executable than just inert assembly instructions. A program needs to talk to the operating system to produce something meaningful. And Windows and Linux are very, very different.

- 159,371
- 13
- 185
- 298
-
Thank you datenwolf & everyone, Now I have some over view of how an executable is executed under the OS environment, but is there a Book/eBook which has all the information more elaborately & teaches what really happens to code when it is compiled. & Which has information deeply how does the executable & system calls/system interupts work. – Rahulsingh190 Nov 04 '13 at 15:58
-
Linux kernel is open source, you can check it directly or check one of the many books available about it. For ELF format, you can check the [specification](http://www.skyfree.org/linux/references/ELF_Format.pdf) directly. – m0skit0 Nov 04 '13 at 22:31
-
@user2952250: What m0skit0 said. When it comes to Windows, the definitive source is "Windows Internals" http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx – datenwolf Nov 04 '13 at 22:40
Modern OSs are not that easy. If you took the Linux executable, added the EXE extension, and ran it in Windows, it will not work. Modern OS have a lot of extra information in the executables besides the code and the data. Linux uses ELF executable format and Windows uses EXE format. This format includes relocation information, memory sizes, partitions and information sometimes relevant to only the OS that uses this executable format. So just changing the extension of the file will not work.
Also, OS system calls and how they're called differ. Linux uses software interrupts (INT 0x80 IIRC) for system calls while Windows uses another system. This means you have to recompile for each taget as not even system calls are done the same way and the C compiler needs to link against the right libc for that target.
-
Actually Linux doesn't use software interrupts anymore, if the hardware supports a fastpath syscall instruction. – datenwolf Nov 04 '13 at 11:39
-
@datenwolf I thought so, but back when I checked the source code (2.4) it did. Thanks for the clarification. – m0skit0 Nov 04 '13 at 11:40
-
2.4 is oooold. Yes, that kernel series relied on int 0x80. And version 2.6/3.x also has the code for this in it, to support x86 based architectures without a fastpath syscall capability. However on a sufficiently modern distribution and CPU the fastpath will be used. – datenwolf Nov 04 '13 at 12:09
The main difference between Linux's and Windows' executables is the format. Linux uses the ELF format, and Windows uses the PE one.
You have to compile your program on each platform. MinGW could be interesting for Windows.

- 4,363
- 19
- 31
Your assumption that the code should be the same is not exactly right. While it's true that math computations would work the same, it's wrong in that different operating systems provide the same interfaces to the program - they don't. See:

- 5,160
- 1
- 27
- 49