调用双方共享的规则
调用者和被调用者必须对参数位置与结果位置取得一致。代码还需要知道哪些寄存器可以被调用破坏,哪些必须由被调用者恢复,避免返回后继续使用已被覆盖的数据。
这些规则独立于函数在源代码中做什么。即使两个函数具有看似相同的声明,如果对二进制传递方式理解不同,连接成功也不保证调用正确。
不同平台采用不同安排
Arm 的 AArch64 过程调用标准以通用寄存器组传递常见参数,并区分可供临时使用的寄存器与需要保留的寄存器。浮点、向量和复合类型还有对应规则。
Microsoft x64 默认约定为前四个参数位置使用规定的整数或浮点寄存器,并要求调用方预留相应栈空间。后续参数使用栈;不能把这组规则当作所有64位机器的统一标准。
同一平台还可能因函数形式出现细分规则。Microsoft x64约定要求调用者为四个寄存器参数预留影子空间,即使实际参数较少;对于可变参数或无原型函数,前四个参数位置中的浮点值还须复制到对应通用寄存器。因此,只照固定签名的浮点调用例子生成代码,再把它用于所有可变参数调用,仍可能破坏二进制约定。
参数传递离不开数据布局
复合值怎样对齐、字段占多少空间,也影响它是直接分散传递,还是通过指针交给被调用者。Microsoft 的 x64 软件约定因此同时说明标量大小、结构布局和对齐规则。
调用约定还应与系统调用接口区分:进入内核可能使用另一组规定。编写跨语言接口或手写汇编时,必须核对目标平台、函数种类和数据表示,而不能只匹配函数名。