Let’s first talk about APIs and ABIs. In programming, many people talk about application programming interfaces (APIs). APIs define how a program can call into another piece of functionality. In C, APIs are often contained in header files and these are documented in manual pages. For example, here are some API declarations in C:
extern int fstat(int struct stat *);
extern void *(size_t);
extern int fputc(int, FILE *);
The API names a function and describes the types of the parameters and the return value of the function. These declarations (and dependent headers) are all that one needs to write a C program. While the API is enough to write a program, when the compiler and link-editor get to work and you actually run your program, you need to rely on something else entirely: the ABI.
The application binary interface (ABI) describes a lot of aspects of the program that are required to have it run. For example, when you call into libc, where are the arguments found? Are they found on the stack? Are they found in registers? The ABI also describes certain things like how many bytes comprise an
int and how should one lay out a structure.
Now, a large amount of the ABI is standardized in different documents for a given platform. For example, many Unix-based systems follow the System V ABI. This ABI defined many aspects of systems such as ELF (executable and linkable format) and dynamic linking.
movq %rsp, (%rdi)
movq (%rsi), %rsp
Function schedule() will finally call arch_switch_to here for x86 platform, which use the pointer of previous & next thread_obj->host_sp as the input parameters (rdi & rsi).