4

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

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

4

1 回答 1

7

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

应使用序言%al来避免不必要地保存 XMM 寄存器。这对于仅整数程序以防止 XMM 单元的初始化尤其重要。

3.5.7 变量参数列表 - 寄存器保存区。System V 应用程序二进制接口版本 1.0

当你调用va_start它时,它会将寄存器中传递的所有参数保存到寄存器保存区

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

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

但是保存所有 8 个向量寄存器可能会很慢,因此编译器可能会选择使用传入的值对其进行优化al

...作为一种优化,在函数调用期间,%rax需要保存用于保存参数的 SSE 寄存器的数量,以允许可变参数调用者在没有浮点参数的情况下完全避免接触 FPU。

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

由于您希望至少保存使用的寄存器,因此该值可以大于实际使用的寄存器数。这就是为什么 ABI 中有这条线

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

你可以从ICC的prolog看到效果

    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: 

它本质上是一个达夫的设备。寄存器加载xmm保存指令后的r11地址,然后al*4从结果中减去(因为movaps XMMWORD PTR [rax-X], xmmX是4字节长)跳转到movaps我们应该运行的指令

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

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

这是与您的问题类似的问题。您可以在以下链接中找到更多信息

于 2018-07-24T05:46:58.323 回答