作者:潇洒嘉新 | 来源:互联网 | 2022-12-09 18:43
为什么al包含汇编中的矢量参数数量?
为什么向量参数与被调用者的正常参数有任何不同?
1> phuclv..:
该值用于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:
它本质上是Duff的设备.该r11
寄存器装有XMM保存指令后的地址,然后al*4
从结果中减去(因为movaps XMMWORD PTR [rax-X], xmmX
是4个字节长),跳转到movaps
,我们应该运行指令
正如我所看到的,其他编译器总是保存所有向量寄存器,或者根本不保存它们,所以它们不关心al
它的值,只检查它是否为零
通用寄存器总是被保存,可能是因为将6个寄存器移动到存储器而不是花时间进行条件检查,地址计算和跳转会更便宜.因此,您不需要在寄存器中传递了多少个整数的参数
以下是与您类似的问题.您可以在以下链接中找到更多信息
vararg函数如何找出机器码中的参数数量?
为什么在调用printf之前%eax归零?
识别变量args函数