【发布时间】:2021-01-03 19:48:53
【问题描述】:
我正在编写一段代码来获取函数的参数,而不使用stdarg。
参数将始终是整数。
平台是 Linux x86_64。
因此调用约定应该是:寄存器%rdi、%rsi、%rdx、%rcx、%r8 和%r8 和%r9 中的前6 个参数,然后是堆栈中的以下参数。考虑到这一点,我最终得到了以下代码,它使用内联汇编来获取前 6 个参数,然后使用指向堆栈的指针来解析剩余的参数。
#define CFI_DEF_CFA_OFFSET 16ull
void get_args (int arg1, ...)
{
register int rdi __asm__ ("rdi"); // 1st arg
register int rsi __asm__ ("rsi");
register int rdx __asm__ ("rdx");
register int rcx __asm__ ("rcx");
register int r8 __asm__ ("r8" );
register int r9 __asm__ ("r9" ); // 6th arg
printf("%d %d %d %d %d %d\n", rdi, rsi, rdx, rcx, r8, r9);
uint64_t frame_pointer = (uint64_t)__builtin_frame_address(0) + CFI_DEF_CFA_OFFSET;
printf("%d\n", *((int*)frame_pointer)); // 1st stack argument
frame_pointer += 8ull; // going to the next
printf("%d\n", *((int*)frame_pointer)); // and so on ...
}
int main (void)
{
get_args(666, 42, 64, 555, 1111, 8888, 7777, 4444);
}
这适用于 GCC,但内联汇编部分不适用于 Clang(它可以编译,但值似乎是随机垃圾)。 由于我对汇编的了解有限,并且可能对 cmet 在类似问题上的误解,我不明白是否可以用 Clang 以类似的方式读取这些特定的寄存器,如果可以,用什么语法。
感谢您的帮助!
【问题讨论】:
标签: c arguments clang x86-64 inline-assembly