在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:
...