There are lots of different compilers for the same os too -- its called competition.
JBennet pretty much summed it up. The final result of a computer program is a binary list of bits read by the OS and processed by the CPU and associated devices. Operating Systems define specific ways in which that data should be read.
I think an easy to grasp example is how an OS stores Data. This would be the FileSystem. Each OS writes files with a header containing meta-data called an i-node. Files written in a different OS would have different I-nodes and therefore, impossible to read properly. A compiler is a set of files and a program is a set of files. For a compiler to correcly associate the data correctly, those files should be written in - for the propper OS.
Most OS code is written in C since it is less painful to write then assembly but low-level enough that you can do specific kernel-level operations.
Another interesting thing to note is that, compilers
don't necessarily have to be tied to a specific OS The Church-Turing thesis states that any computable function (i.e. a program) can be computed by a turing machine (a theoretical computer). This means that any software, theoretically, can run on any machine. This is how emulators work. If you've played MAME games or perhaps downloaded an amiga chipset emulator. This is also why OpenGL runs system independantly. It's not that compilers
have to run on a specific OS, it just means that no one has bothered to implement the overhead to ensure that they can.
Another good example would be PERL. When I write a windows PERL program in active perl, the statemnt system("pause") does just that. When I run the same program on my Solaris SPARC workstation, it has no idea what the pause command does