gpt4 book ai didi

c - 是否可以使用 Inline ASM 计算 __cdecl 中的函数(变量)参数?

转载 作者:太空宇宙 更新时间:2023-11-04 06:10:47 25 4
gpt4 key购买 nike

被调用者是否可以在不知道参数类型或数量的情况下,通过使用内联 ASM (x86) 偏移堆栈基指针 (rbp) 来迭代(和计数)函数调用参数?

void foo(char *arg, ...);

我使用的是 Intel 编译器,但其文档指出它支持 GCC 样式的内联汇编。因此,基于 GCC 的示例就足够了。

#include <stdio.h>
#include <inttypes.h>

int main(int argc, char **argv){

uint64_t n;

__asm__ __volatile__(
"movq %%rbp, %0\n\t"
: "=r"(n)
);

printf("rbp = 0x%" PRIx64 "\n", n);
return 0;
}

the code in this post

最佳答案

唯一可行的方法是使用标记最后一个参数的唯一标记值(例如 NULL 指针)。

这通常只适用于所有参数都是指针的情况,例如由 POSIX execl(3) functions 使用像

这样的签名
int execl(const char *pathname, const char *arg, ...
/* (char *) NULL */);

(那么你不需要内联汇编;你可以只使用 C VA_ARG 宏。)


此外,rbp 也没有用;您不知道该函数是否是在启用优化的情况下编译的,因此它可能根本不是帧指针。如果您想要 GNU C 中的帧地址,请使用 __builtin_frame_address(0)。 (查看编译器生成的 asm 以了解它的作用。IIRC,它为该函数强制 -fno-omit-frame-pointer 并只为您提供 rbp)

即使获得堆栈帧地址也无法帮助您获得寄存器参数(x86-64 System V 中的前 6 个整数/指针和前 8 个 FP 参数。或者 Windows x64 中的前 4 个总参数。)

将您的函数声明为可变参数并使用 VA_ARG 将所有可变参数读取为 uint64_t 这样您就可以检查它们是否为零,或者您选择的任何位模式哨兵。

显然这需要调用者的合作来传递哨兵。


顺便说一句,x86-64 不存在名为 __cdecl 的调用约定。微软称他们的 x64 __fastcall__vectorcall

关于c - 是否可以使用 Inline ASM 计算 __cdecl 中的函数(变量)参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57281945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com