Compiling with gcc on x86-64, I have a function with the signature
void * g(void* p, unsigned char a, unsigned char b, ...)
and a function call
long double zero = 0;
g(NULL, 0, 0, zero);
But when g()
reads the zero
argument via va_arg(...,long double)
and compares it == 0
, the result is FALSE
!!!
I was experimenting with the assembly output (I don't know the x86-64 calling conventions well), but the output of the function call is
fldz
fstpt -16(%rbp)
pushq -8(%rbp)
pushq -16(%rbp)
movl $0, %edx
movl $0, %esi
movl $0, %edi
movl $0, %eax
call g
and this does not work as I have written above. But when I add an instruction like this
...
fstpt -16(%rbp)
movw $0, -6(%rbp) #added instruction
pushq -8(%rbp)
...
it starts to do the right thing. But how can this even have an influence if the long double
type and what is handled by the FPU, has only 10 bytes. As I understand, the long double argument is passed via [RBP-16],...,[RBP-7], but what is changed among the working and the not working versions is only [RBP-6] and [RBP-5].
Maybe anyone has some ideas? Thank you!
EDIT: This is the C code of g:
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);
...
and the respective assembler code:
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:
...