system
Given the following post, respond as if you're commenting on Reddit:
human
How do I know my code runs on different machines?

Let's say I write a program in C. That programm compiles to assembly code and that code gets assembled to machine code. Given the plethora of different processors out there, how can I distribute my binaries and know they run on different machines? When you download a program on the internet, you often see a Windows, MacOS, and Linux version, but why would there be different versions depending on the operating system and not on the machine? My thought process is: If my binary runs on machine A, it will probably not run on machine B, because machine B has a different instruction set. I'm not that deep into assembly programming, so I'm just guessing here, but I'd assume there are so many different instruction sets for different machines, that you could't distribute binaries for all machines. I'm also guessing that when I use a compiler, let's say gcc, that it knows different architectures and can given certain arguments compile for different machines. When I distribute non-open-source software I would of course only distribute the binaries and not the C code. But then I wouldn't be able to compile on my target system. So how would this work? Does it have something to do with the OS? Does the OS change instructions to match the system's architecture?
gpt
It's not just the instruction set alone. For example, every operating system provides different system call interfaces. They differ in the kind of services provided by the system calls (like reading/writing files). And the convention how a system call in the operating system is invoked from the assembly differs as well.

That's one of the reasons that you need to compile separately for each ISA/OS combination whenever a program runs on the CPU's instruction set directly. (ISA = instruction set architecture)

If you want to compile only once and have it run on all platforms, you need something like Java that compiles to CPU independent bytecode. But then, you need a virtual machine to run those Java programs. And that virtual machine again is compiled separately for each ISA/OS combination.

For C, you need to compile your code with a compiler that's configured to produce code for your target ISA/OS combination. If you install a gcc on your development system, it's typically set up to produce code for your development system's ISA/OS combination. If you are developing on an x86 Windows but want to create your binaries for a Linux running on an ARM CPU, you need to install a cross-compiler that targets Linux for ARM.

You still need to be careful about writing your code in a portable manner, like using libraries that are available across your target systems. And your C code itself must be portable. For example, your code should not have any silent assumptions about the target architecture, like the size of a pointer.

Hope that helps.