NAN在与使用x87浮点的程序集混合的C代码中意外出现

NAN在与使用x87浮点的程序集混合的C代码中意外出现,c,function,x86,sse,clock,C,Function,X86,Sse,Clock,我的C代码如下。它调用一个汇编函数 clock_t t = clock(); asmfunction(input); t = clock() - t; printf("%.5f\n", ((float)t)/CLOCKS_PER_SEC); 我将汇编x86-32+SSE用于asmfunction 我不明白为什么第二个clock()调用返回nan 我的汇编代码是一个使过程调用的循环。我注意到,如果它迭代超过六次,则第二次调用clock函数返回NaN。否则它工作正常 这是我的汇编代码的核心: do

我的C代码如下。它调用一个汇编函数

clock_t t = clock();
asmfunction(input);
t = clock() - t;
printf("%.5f\n", ((float)t)/CLOCKS_PER_SEC);
我将汇编x86-32+SSE用于
asmfunction

我不明白为什么第二个
clock()
调用返回nan

我的汇编代码是一个使过程调用的循环。我注意到,如果它迭代超过六次,则第二次调用clock函数返回NaN。否则它工作正常

这是我的汇编代码的核心:

do_while:
    push dword [eax+n]
    push eax
    push ecx
    push dword [eax+p]
    call function1
    add esp,16

    push dword [eax+n]
    push eax
    push ecx
    call function2
    add esp,12      

    fst qword[res]

    push dword [eax+n]
    push eax
    push ecx
    call function3  ;function3 returns a double precision floating 
                    ;point value
    add esp,12 
    movsd xmm1,[res] ;xmm1=res

    comisd xmm1,[eax+ex] ; eax+ex is a quadword
    ja do_while
为什么
时钟调用的结果是NaN?

x87 FPU(浮点单元)堆栈只有八个元素。如果例程没有弹出它所推送的所有元素,堆栈将随着例程的重复使用而迅速溢出。一旦堆栈溢出,浮点操作将产生NAN(英特尔文档中的“浮点不定值”)


问题中汇编代码中的
fst
指令存储一个值,而不会弹出堆栈。假设先前的函数之一(
function1
function2
)将浮点值推送到堆栈上以将其返回给调用者,调用者应将其从堆栈中弹出,在存储时,可以使用
fstp
指令而不是
fst

来执行此操作。您没有提供足够的信息<代码>时钟可以是整数或浮点类型。如果是前者,则整数值在浮点中与
nan
相对应是完全合理的。如果您是说
printf
打印
nan
,那么您不能断定问题是对
time()
的第二次调用。程序集可能正在堆栈上咀嚼
t
。您必须找到您认为代码所做的与它实际所做的不同之处。标准调试技术:调试器;打印值,二进制搜索剪切代码部分。另一种选择是根据网站指南提取MCVE。为什么使用
fst
而不是
fstp
?是
asm_函数
还是它调用的函数溢出了处理器中的八项浮点堆栈?它们是否在
asm\u函数返回后将元素留在堆栈上?如果你用bollyx表示浮点堆栈,那就可以解释NaNs了。
printf(“%lld%e\n”,(long-long)t,(double)t)请将此输出报告在
printf(%.5f\n“…
No,@Gene之前,标准规定
clock\u t
为实数类型,而非整数类型()。此外,有效整数值对应于FP NaN是不合理的,除非具有相同的位模式。但是,即使发生了这种位模式匹配,它也与OP的代码无关。更具体地说,i386 System V调用约定要求x87堆栈在函数调用/返回时为空,或者,如果返回类型为FP,则返回时x87堆栈为空,但
st(0)
中的返回值除外。因此,是的,C编译器希望
asmfunction
将x87堆栈保留为空,但几乎肯定不是这样(但是我们看不到
function3
的代码,所以它可能包括
finit
或其他什么,它所说的返回的
double
xmm0
中?非常缺少一个,但这个答案肯定是最有可能的。