将x86-64上的long double传递给可变参数函数

时间:2018-07-24 08:43:12

标签: x86-64 variadic-functions calling-convention x87

在x86-64上使用gcc进行编译,我有一个带有签名的函数

void * g(void* p, unsigned char a, unsigned char b, ...)

和函数调用

long double zero = 0;
g(NULL, 0, 0, zero);

但是,当g()通过zero读取va_arg(...,long double)参数并将其与== 0进行比较时,结果为FALSE !!!

我正在尝试汇编输出(我不太了解x86-64的调用约定),但是函数调用的输出是

fldz
fstpt   -16(%rbp)
pushq   -8(%rbp)
pushq   -16(%rbp)
movl    $0, %edx
movl    $0, %esi
movl    $0, %edi
movl    $0, %eax
call    g

,这和我上面写的一样不起作用。但是当我添加这样的指令

...    
fstpt   -16(%rbp)
movw    $0, -6(%rbp) #added instruction
pushq   -8(%rbp)
...

它开始做正确的事。但是,如果long double类型和FPU处理的内容只有10个字节,这怎么会产生影响。据我了解,long double参数是通过[RBP-16],...,[RBP-7]传递的,但是在有效版本和无效版本之间的更改仅是[RBP-6]和[RBP- 5]。

也许有人有想法?谢谢!

编辑:这是g的C代码:

void * g(void* p, unsigned char a, unsigned char b, ...) {
    va_list list;
    long double x;
    va_start(list, b);
    x = va_arg(list, long double);
    if (x == 0)
        h(q,r);
...

以及相应的汇编代码:

g:
pushq   %rbp
movq    %rsp, %rbp
subq    $240, %rsp
movq    %rdi, -232(%rbp)
movq    %rcx, -152(%rbp)
movq    %r8, -144(%rbp)
movq    %r9, -136(%rbp)
testb   %al, %al
je      .L1635
movaps  %xmm0, -128(%rbp)
movaps  %xmm1, -112(%rbp)
movaps  %xmm2, -96(%rbp)
movaps  %xmm3, -80(%rbp)
movaps  %xmm4, -64(%rbp)
movaps  %xmm5, -48(%rbp)
movaps  %xmm6, -32(%rbp)
movaps  %xmm7, -16(%rbp)
.L1635:
movl    %esi, %eax
movb    %al, -236(%rbp)
movl    %edx, %eax
movb    %al, -240(%rbp)
movq    %fs:40, %rax
movq    %rax, -184(%rbp)
xorl    %eax, %eax
movl    $24, -208(%rbp)
movl    $48, -204(%rbp)
leaq    16(%rbp), %rax
movq    %rax, -200(%rbp)
leaq    -176(%rbp), %rax
movq    %rax, -192(%rbp)
movq    -200(%rbp), %rax
addq    $15, %rax
andq    $-16, %rax
leaq    16(%rax), %rdx
movq    %rdx, -200(%rbp)
fldt    (%rax)
fstpt   -224(%rbp)
fldt    -224(%rbp)
fldz
fucomip %st(1), %st
fstp    %st(0)
jp      .L1636
fldt    -224(%rbp)
fldz
fucomip %st(1), %st
fstp    %st(0)
jne     .L1636
leaq    .LC22(%rip), %rsi
leaq    .LC23(%rip), %rdi
call    h
.L1636:
...

0 个答案:

没有答案