Why are executables in machine code operating system dependent?
In windows, when I compile a simple 'C' program, I get the final executable machine code .exe
.
The same thing using gcc in unix yields a .out
machine code file.
What's the difference between these?
My basic question is, .exe
and .out
being machine codes, why are they operating system dependent?
As in, in Unix I c开发者_开发百科annot execute .exe
directly and in Windows, I can't execute .out
of Unix. Why is this so?
It all has to do with how the program is loaded.
Windows and Linux have different formats for how they want a program to define itself.
In Linux, the ELF format is normally used. For Windows it is PE.
These formats define different data about the program that is needed to execute the machine instructions.
Also, the operating system interfaces are different, so different libraries need to be used and different system calls need to be made.
For a simple program, you can usually just recompile on the other operating system to have it work on both, but you will not be able to use a single file on both.
The operating system abstracts access to the underlying hardware, and makes it available to programmers via system calls. In Windows, these are done through the Windows API (which is usually further abstracted by libraries that make programming easier, like MFC, etc). In UNIX, this is often done through interrupts, which the system's C library makes a bit easier by following the POSIX api (often with a few system-dependent additions).
For example, on Linux, system calls are made through int 0x80
, with several registers being loaded with the arguments to the function, and the C library makes this easier by allowing you to call, e.g. read
, with the expected arguments ( int fd, void *buf, size_t count )
. This gets translated into an interrupt call, which the kernel responds to.
These two manners of making requests against the operating system are incompatible, and thus you (generally) can't run a Windows executable on UNIX systems, and vice versa, without using some additional system that acts as a translation layer, like WINE, VMWare, etc. (though the way those two work is very different).
(Incidentally, a.out
says nothing about the contents of the executable; it's the traditional filename given to executables compiled on UNIX systems, and is short for "assembler output". GCC allows cross-compiling, so you can even compile Win32-compatible .EXE files with it. You can use the -o
flag to gcc to specify the output filename, which shows you that it has no bearing on the actual format of the outputted file.)
In unix environment any file that has +x bit set is considered executable. Remember even non-binary files can be executable (shell scripts, batch files, etc...). Windows relies on the concept of a file extension, on Unix we just set chmod +x filename
.
You can always use -o file
flag to force gcc producing whatever filename you like.
精彩评论