从汇编调用 C 函数——切换调用约定

标签 c assembly linux-kernel nasm

我有一个适用于 Linux x64 的汇编应用程序,我通过寄存器将参数传递给函数,因此我使用了某种特定的调用约定,在本例中为 fastcall。现在我想从程序集应用程序调用一个 C 函数,比如说,它需要 10 个参数。我是否必须为此切换到 cdecl 并通过堆栈传递参数,而不管我的应用程序中其他任何地方我通过寄存器传递它们的事实?是否允许在一个应用程序中混合调用约定?

最佳答案

我假设 fastcall 是指 SysV ABI 使用的 amd64 调用约定(即 Linux 使用的),其中前几个参数在 rdi 中传递, rsirdx.

ABI 稍微复杂一些,下面是一个简化。您可能想阅读 the specification了解详情。

一般来说,前几个(最左边的)整数或指针参数被放入寄存器rdirsirdxrcxr8r9。浮点参数在 xmm0 中传递给 xmm7。如果寄存器空间用完,则附加参数从右到左通过堆栈传递。例如,调用一个有 10 个整数参数的函数:

foo(a, b, c, d, e, f, g, h, i, k);

你需要这样的代码:

mov $a,%edi
mov $b,%esi
mov $c,%edx
mov $d,%ecx
mov $e,%r8d
mov $f,%r9d
push $k
push $i
push $h
push $g
call foo
add $32,%rsp

对于您的具体示例,getnameinfo:

int getnameinfo(
    const struct sockaddr *sa,
    socklen_t salen,
    char *host,
    size_t hostlen,
    char *serv,
    size_t servlen,
    int flags);

您将在 rdi 中传递 sa,在 rsi 中传递 salenhostrdxhoSTLenrcxservr8servlen r9flags 在堆栈上。

关于从汇编调用 C 函数——切换调用约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41738307/

相关文章:

c - 使用链表在 C 中表示和排序多项式

assembly - 启动 x86 机器上的默认寄存器和段值

linux-kernel - 常量类似 "VM_RESERVED"和 3.9.6 中的 nopage 方法

c - 访问特定 UID 的 user_struct

c - 为什么c中的时间函数返回毫秒而不是秒?

c - 在头文件中声明枚举,在源文件中不可见?

c - 内核环境: RSDP points to invalid RSDT

assembly - TASM 中的 "Near jump or call to different CS"错误

c - GCC typeof 扩展和 typeof 结果的数学运算

c - C获取用户的特定输入