我用不同的参数编译了对printf的调用。
下面是代码+生成的asm:

int main(int argc, char const *argv[]){
    //   0: 55                      push   rbp
    //   1: 48 89 e5                mov    rbp,rsp
    //   4: 48 83 ec 20             sub    rsp,0x20
    //   8: 89 7d fc                mov    DWORD PTR [rbp-0x4],edi
    //   b: 48 89 75 f0             mov    QWORD PTR [rbp-0x10],rsi
    printf("%s %f %d %f\n", "aye u gonna get some", 133.7f, 420, 69.f);
    //   f: f2 0f 10 05 00 00 00 00 movsd  xmm0,QWORD PTR [rip+0x0]        # 17 <main+0x17> 13: R_X86_64_PC32   .rodata+0x2c    69
    //  17: 48 8b 05 00 00 00 00    mov    rax,QWORD PTR [rip+0x0]        # 1e <main+0x1e>  1a: R_X86_64_PC32   .rodata+0x34    133.7
    //  1e: 66 0f 28 c8             movapd xmm1,xmm0
    //  22: ba a4 01 00 00          mov    edx,0x1a4 (420)
    //  27: 48 89 45 e8             mov    QWORD PTR [rbp-0x18],rax
    //  2b: f2 0f 10 45 e8          movsd  xmm0,QWORD PTR [rbp-0x18]
    //  30: 48 8d 35 00 00 00 00    lea    rsi,[rip+0x0]        # 37 <main+0x37>    33: R_X86_64_PC32   .rodata-0x4  "aye u wanna get some"
    //  37: 48 8d 3d 00 00 00 00    lea    rdi,[rip+0x0]        # 3e <main+0x3e>    3a: R_X86_64_PC32   .rodata+0x18 "%s %f %d %f\n"
    //  3e: b8 02 00 00 00          mov    eax,0x2
    //  43: e8 00 00 00 00          call   48 <main+0x48>   44: R_X86_64_PLT32  printf-0x4
    return 0;
    //  48: b8 00 00 00 00          mov    eax,0x0
    //  4d: c9                      leave
    //  4e: c3                      ret
}

这里的大多数东西对我来说都有意义。
事实上这里的一切对我来说都有一定的意义。
"%s %f %d %f\n"->RDI
"aye u gonna get some"->相对强弱指数
133.7->xmm0
RDX公司
420>>xmm1
69->rax(表示有两个浮点参数)
现在我不明白printf(或任何其他varargs函数)是如何计算出这些浮点参数在其他变量中的位置的。
它也不可能是编译器魔术,因为它是动态链接的。
所以我唯一能想到的是,它可能只是va_arg的内部结构,以及当您提供一个类型时,如果它是浮点类型,那么它必须从xmms(或堆栈)获取,而不是从其他类型获取。
是这样吗?如果没有,对方怎么知道从哪里弄来的?提前谢谢。

最佳答案

对于printf,格式字符串指示其余参数的类型。
va_arg的实现知道类型,因为它是va_arg的一个参数,并且可以从类型中推断出正确的寄存器。

关于c - 系统V AMD64 ABI浮点varargs命令,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52953079/

10-16 20:30