该值用于优化,如ABI document中所述
序言应使用%al 以避免不必要地保存XMM 寄存器。这对于仅整数程序以防止 XMM 单元的初始化尤其重要。
3.5.7 变量参数列表 - 寄存器保存区。 System V Application Binary Interface version 1.0
当你调用va_start时,它会将所有传入寄存器的参数保存到寄存器保存区
首先,任何已知使用va_start的函数都需要在函数开始时将所有可能用于将参数传递到堆栈上的寄存器保存到“寄存器保存区”中,供va_start 和va_arg 将来访问。这是一个明显的步骤,我相信在任何具有寄存器调用约定的平台上都是相当标准的。寄存器保存为整数寄存器,后跟浮点寄存器...
https://blog.nelhage.com/2010/10/amd64-and-va_arg/
但保存所有 8 个向量寄存器可能会很慢,因此编译器可能会选择使用 al 中传递的值对其进行优化
... 作为优化,在函数调用期间,%rax 需要保存用于保存参数的 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指令
正如我所见,其他编译器总是保存所有向量寄存器,或者根本不保存它们,所以他们不关心 al 的值,只检查它是否为零
通用寄存器总是被保存,可能是因为将 6 个寄存器移动到内存而不是花时间进行条件检查、地址计算和跳转更便宜。因此,您不需要参数来指示在寄存器中传递了多少整数
这是similar question to yours。您可以在以下链接中找到更多信息