ABI (Application Binary Interface)

  • Binary-level software convention.

  • How compiled programs cooperate

  • Defines:

    • calling conventions

    • register usage

    • stack layout

    • object file format

    • syscall interface

  • ISA tells you what instructions exist.

  • ABI tells you how binaries interoperate.

  • Example ABIs on x86-64:

    • System V AMD64 ABI

    • Microsoft x64 ABI

  • It is the assumptions the compiler makes about how exactly the bit-for-bit representation and the usage of the computer’s actual hardware resources when it negotiate things that lie outside of a singular routine.

  • This includes things like:

    • the position, order, and layout of members in a struct/class;

    • the argument types and return type of single function (C++-only: and any relevant overloaded functions);

    • the “special members” on a given class (C++-only);

    • the hierarchy and ordering of virtual functions (C++-only);

    • and more.

C ABI

  • C is a protocol, not a programming language .

    • Interesting read, but also a bit of a sad one. It basically kinda implies, from my understanding, that C can't change things for the better due to incompatibilities that it would create.

  • The C integer hierarchy .

  • C also has much simpler ways of doing things, so it effectively boils down to two things that matter the most:

    • the position, order, and layout of members in a struct; and,

    • the argument types and return type of a function.

  • Because C++ consumes the entire C standard library into itself nearly wholesale with very little modifications, C’s ABI problems become C++’s ABI problems.

  • C’s ABI is “simple”, in that there is effectively a one-to-one correspondence between a function you write, and the symbol that gets vomited out into your binary. As an example, if I were to declare a function do_stuff, that took a long long parameter and returned a long long value to use, the code might look like this:

#include <limits.h>

extern long long do_stuff(long long value);

int main () {
    long long x = do_stuff(-LLONG_MAX);
    /* wow cool stuff with x ! */
    return 0;
}
  • and the resulting assembly for an x86_64 target would end up looking something like this:

main:
    movabs  rdi, -9223372036854775807
    sub     rsp, 8
    call    do_stuff
    xor     eax, eax
    add     rsp, 8
    ret
  • sub rsp, 8  "The ABI requires the stack to be 16-byte aligned at call sites.". Subtracting 8 fixes alignment.

  • xor reg, reg  is faster/smaller than mov reg, 0 .