Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 为什么eax包含向量参数的数量?_Assembly_X86 64_Calling Convention_Abi_Sysv - Fatal编程技术网

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

Assembly 为什么eax包含向量参数的数量?,assembly,x86-64,calling-convention,abi,sysv,Assembly,X86 64,Calling Convention,Abi,Sysv,为什么al在汇编中包含向量参数的数量 为什么向量参数与被调用方的正常参数不同?该值用于优化,如中所述 序言应使用%al避免不必要地保存XMM寄存器。这对于防止XMM单元初始化的纯整数程序尤为重要 3.5.7变量参数列表-寄存器保存区域 当您调用va_start时,它会将在寄存器中传递的所有参数保存到寄存器保存区域 要启动,任何已知使用va_start的函数都需要在函数启动时将所有可能用于将参数传递到堆栈上的寄存器保存到“寄存器保存区域”,以便va_start和va_arg将来访问。这是一个明显的

为什么al在汇编中包含向量参数的数量


为什么向量参数与被调用方的正常参数不同?

该值用于优化,如中所述

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

3.5.7变量参数列表-寄存器保存区域

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

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

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

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

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

%al
的内容不需要精确匹配寄存器的数量,但必须是所用向量寄存器数量的上限,并且在0到8(包括0到8)的范围内

您可以从中看到效果

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

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

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

这是一本书。您可以在以下链接中找到更多信息


注意,这仅适用于varargs函数,而不是
eax
只是
al
。我想这是为了让通用Thunk处理适当数量的向量寄存器,例如节省空间。该规范说,它“不需要精确匹配寄存器的数量,但必须是所用向量寄存器数量的上限”。请注意,这不是向量参数的数量,而是在XMM/YMM/ZMM regs中传递的数量。您可以有无限数量的
\uuu m128
参数,但在前8个参数之外,它们将在堆栈上传递。我认为应该在堆栈上传递FP args并设置
al=0
,但我还没有测试。gcc的可变函数代码生成器只检查
al=0
并将所有xmm0..7存储到堆栈上的一个数组中,它可以对该数组进行索引,因此前8个FP/vector参数可能确实需要放入vector regs中。如果我没有记错,参数只是在寄存器中传递,在堆栈上传递额外的参数。如果是这种情况,为什么我需要传递FP/vector参数的数量?被调用方是否应该能够访问它知道需要访问的内容,或者这对可变参数更重要?有时,这些信息在其他情况下是不可用的,例如在通用thunk或hook中。编译器正在加载寄存器(在调用方中),所以它当然知道。它遵循ABI中的规则。还有一件事:我们为什么不保存整数寄存器?是不是因为调用方负责保存,而浮点寄存器的保存成本非常高?@Riolku整数寄存器被保存,你可以在序言中看到这一点。正如我在最后一段中所说的,保存它们的6
mov
指令的成本可能比计算要保存哪个寄存器的成本要小,所以请将它们全部保存。回答得很好,这很有道理,谢谢!你引用的是ABI的旧版本,它错误地说RAX需要计数。它实际上只是AL,您不能假设它是零扩展到RAX的(尽管许多编译器使用xor zero RAX或使用
mov eax,4
或其他任何东西,当优化大小时,它们可能会使用2字节
mov AL,4
来存储非零数字。)有趣的事实:旧的GCC使用AL来保存正确数量的XMM regs,用计算出的跳跃IIRC,就像你为ICC展示的那样。当前的GCC只是测试al,al/
jz
以跳过8x
movaps
指令。
    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: