代码之家  ›  专栏  ›  技术社区  ›  Riolku

为什么eax包含向量参数的数目?

  •  2
  • Riolku  · 技术社区  · 8 年前

    为什么al包含汇编中的向量参数个数?

    为什么向量参数与被调用者的正常参数有任何不同?

    1 回复  |  直到 8 年前
        1
  •  6
  •   phuclv    8 年前

    该值用于ABI文档中所述的优化

    开场白应该用 %rax 以避免不必要地保存XMM寄存器这对于防止XMM单元初始化的纯整数程序尤其重要。

    https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf

    当你打电话 va_start 它将把寄存器中传递的所有参数保存到 注册保存区域

    首先,任何已知要使用的函数 虚拟开始 在函数开始时,需要将可能用于将参数传递到堆栈的所有寄存器保存到寄存器保存区域中,以便将来通过 虚拟开始 va_arg . 这是一个明显的步骤,我相信在任何平台上都是非常标准的,有一个寄存器调用约定寄存器保存为整数寄存器,后跟浮点寄存器。。。

    但是保存所有8个向量寄存器可能会很慢,所以编译器可以选择使用传入的值来优化它 al

    ... 作为优化,在函数调用期间, %拉克斯 需要保留用于保存参数的SSE寄存器的数量,以允许varargs调用方在没有浮点参数的情况下完全避免接触FPU。

    https://blog.nelhage.com/2010/10/amd64-and-va_arg/

    既然你想拯救 至少 使用的寄存器,该值可以大于实际使用的寄存器数所以ABI里有这条线

    的内容 %al 不需要精确匹配寄存器的数量,但必须是所用向量寄存器数量的上限,并且在0–8范围内。

    你可以从 prolog of ICC

        sub       rsp, 216                                      #5.1
        mov       QWORD PTR [8+rsp], rsi                        #5.1
        mov       QWORD PTR [16+rsp], rdx                       #5.1
        mov       QWORD PTR [24+rsp], rcx                       #5.1
        mov       QWORD PTR [32+rsp], r8                        #5.1
        mov       QWORD PTR [40+rsp], r9                        #5.1
        movzx     r11d, al                                      #5.1
        lea       rax, QWORD PTR [r11*4]                        #5.1
        lea       r11, QWORD PTR ..___tag_value_varstrings(int, ...).6[rip] #5.1
        sub       r11, rax                                      #5.1
        lea       rax, QWORD PTR [175+rsp]                      #5.1
        jmp       r11                                           #5.1
        movaps    XMMWORD PTR [-15+rax], xmm7                   #5.1
        movaps    XMMWORD PTR [-31+rax], xmm6                   #5.1
        movaps    XMMWORD PTR [-47+rax], xmm5                   #5.1
        movaps    XMMWORD PTR [-63+rax], xmm4                   #5.1
        movaps    XMMWORD PTR [-79+rax], xmm3                   #5.1
        movaps    XMMWORD PTR [-95+rax], xmm2                   #5.1
        movaps    XMMWORD PTR [-111+rax], xmm1                  #5.1
        movaps    XMMWORD PTR [-127+rax], xmm0                  #5.1
    ..___tag_value_varstrings(int, ...).6: 
    

    本质上是 Duff's device . 这个 r11 寄存器在xmm保存指令之后加载地址,然后 al*4 从结果中减去 movaps XMMWORD PTR [rax-X], xmmX 是4字节长)以跳到 movaps 我们应该运行的指令

    如我所见,其他编译器总是保存所有的向量寄存器,或者根本不保存它们,所以它们不关心 艾尔 的值,然后检查它是否为零

    通用寄存器总是被保存,可能是因为将6个寄存器移到内存中而不是花时间进行条件检查、地址计算和跳转比较便宜因此,您不需要一个参数来确定在寄存器中传递了多少个整数

    这是一个 similar question to yours . 您可以在下面的链接中找到更多信息

    推荐文章