系统V AMD64 ABI浮点varargs命令

时间:2018-10-23 15:46:14

标签: c linux assembly calling-convention abi

我用不同类型的args编译了对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"-> rsi
133.7-> xmm0
420-> rdx
69-> xmm1
2-> rax(表示有2个浮点参数)

现在我不明白的是printf(或任何其他varargs函数)如何确定这些浮点参数在其他参数中的位置。

由于它是动态链接的,因此也不能成为编译器魔术。
因此,我唯一想到的可能只是va_arg内部,以及如何在提供类型时(如果它是浮点)必须从xmms(或堆栈)获取而不是其他。

对吗?如果没有,另一方如何知道从哪里得到他们?预先感谢。

1 个答案:

答案 0 :(得分:3)

对于printf,格式字符串指示剩余参数的类型。

va_arg的实现知道类型,因为它是va_arg的参数,并且可以从类型中推导出正确的寄存器。