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

Rio*_*lku 3 assembly x86-64 abi calling-convention sysv

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

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

phu*_*clv 6

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

序言应该%rax用来避免不必要地保存XMM寄存器.这对于仅限整数的程序来说尤其重要,可以防止XMM单元的初始化.

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

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

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

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

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

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

由于您希望至少保存所使用的寄存器,因此该值可能大于实际使用的寄存器数.这就是ABI中这条线的原因

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

您可以从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: 
Run Code Online (Sandbox Code Playgroud)

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

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

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

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