Short answer is: by historical reasons.
Naturally, if the systems have different CPU, in traditional paradigm the executable code is composed of machine-code instruction, but even with identical CPU's the executables are usually incompatible. Different classes of OS use very different approaches, different file formats.
Programming platforms based on intermediate byte code are different. For example, I run my .NET programs (if they are written using some standard sub-set of API (in practice, well beyond)) on Windows and Linux. Executable files are built into intermediate code (CIL) and compiled in machine code on every target machine during execution using mechanism called Just-In-Time compilation (JIT). See
http://en.wikipedia.org/wiki/.NET_Framework[
^],
http://en.wikipedia.org/wiki/Just-in-time_compilation[
^].
Java machine also makes compiled Java code platform-independent:
http://en.wikipedia.org/wiki/Just-in-time_compilation[
^].
There are other platforms based on similar approaches, mostly historical. It's hard to say if platform-independent technologies are taking over or not, but they certainly grow quite aggressively.
By the way, you should not assume you don't use API. Eventually you do. How do you do input/output? Even with file system of console, this is done through OS API. Theoretically speaking, a DLL (or Shared Library) could present purely data and calculations, without any API calls, but in real life this is unlikely. Even in this case, DLL's executable files are incompatible.