为什么 al 包含汇编中矢量参数的数量?
为什么向量参数与被调用者的正常参数有任何不同?
该值用于优化,如ABI 文档中所述
应使用序言
%al
来避免不必要地保存 XMM 寄存器。这对于仅整数程序以防止 XMM 单元的初始化尤其重要。3.5.7 变量参数列表 - 寄存器保存区。System V 应用程序二进制接口版本 1.0
当你调用va_start
它时,它会将寄存器中传递的所有参数保存到寄存器保存区
首先,任何已知使用的函数
va_start
都需要在函数开始时,将所有可能用于将参数传递到堆栈中的寄存器保存到“寄存器保存区”中,以供将来va_start
访问va_arg
。这是一个明显的步骤,我相信在任何具有寄存器调用约定的平台上都是相当标准的。寄存器保存为整数寄存器,后跟浮点寄存器......
但是保存所有 8 个向量寄存器可能会很慢,因此编译器可能会选择使用传入的值对其进行优化al
...作为一种优化,在函数调用期间,
%rax
需要保存用于保存参数的 SSE 寄存器的数量,以允许可变参数调用者在没有浮点参数的情况下完全避免接触 FPU。
由于您希望至少保存使用的寄存器,因此该值可以大于实际使用的寄存器数。这就是为什么 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 个寄存器移动到内存而不是花时间进行条件检查、地址计算和跳转更便宜。因此,您不需要参数来指示在寄存器中传递了多少整数
这是与您的问题类似的问题。您可以在以下链接中找到更多信息