an ABI (at a glance)
/ ay-bee-eye /
If an API is the agreement at the level of source code (what to call), an ABI is the agreement at the level of the compiled bytes (how the machine code actually fits together). ABI stands for application binary interface. Two pieces of already-compiled code - your program and a library, say - have to agree on a host of low-level mechanics to call each other correctly, and the ABI is exactly that set of binary-level conventions.
What does the ABI pin down? Things like how arguments are passed to a function (which CPU registers or stack slots), where a return value goes, how the stack is arranged during a call, how big each data type is and how its bytes are laid out and aligned in memory, and how names are encoded so the linker can match them. None of this appears in your source code; the compiler picks it according to the platform's ABI. Both sides of a call must use the same ABI, or the bytes will be misinterpreted - one side puts an argument in a register the other side never reads.
Why it matters: the ABI is why you can link against a pre-compiled library you did not build yourself, and why an updated shared library can keep working with old programs as long as its ABI did not change. It is also why a compiled executable is tied to a platform: it bakes in that platform's ABI. The key contrast: an API is checked when you compile (source-level, broken at build time if you misuse it), while an ABI matters after you compile, when separately built binaries must mesh - an ABI mismatch produces crashes and corruption, not tidy compiler errors.
On 64-bit Linux the System V ABI says the first integer argument to a function goes in register rdi and the return value comes back in rax. Your compiler emits code following that rule, and so does the library you link - so a call just works, even though neither side saw the other's source.
The ABI fixes the invisible binary rules - which register holds an argument, etc.
Do not confuse ABI with API. API breakage shows up as a compile error; ABI breakage shows up at run time as crashes or garbage, because the source still compiled but the compiled pieces no longer agree on the binary layout. Same library, recompiled with a different ABI, may not link or run with old binaries.