NASM x86,FIST 的意外结果

NASM x86, unexpected result of FIST

我无法理解拳头操作的结果。在我的代码中,我试图从用户那里获取 1 个整数,然后将其传递给程序集,乘以 const 和 return 作为近似整数。

问题是我读到 FIST 指令将浮点数转换为整数并将其保存在内存中。当我 return 我的结果并且有 int 作为一种结果时,我得到了我想要的。但是,如果我将其更改为 float,我将获得没有近似值的结果。 所以对于 3 和 const = 3.86 我希望从拳头得到 12。我将 eax 中的结果与 12 进行了比较,似乎确实有 12。但是,如果我将函数结果类型更改为浮点数,我会得到 11.58 的答案。

我唯一猜测的可能是在 returning 浮动的情况下,它是从浮动堆栈中取出的,因为我不从那里弹出它,这就是答案。

extern "C" int fun (int a);

extern "C" float fun (int a);

这是我的代码:

大会

section .data
    bmp dd 3.86
    res dd 0

section .text
    global fun

fun:
;---------- intro ---------- 
    push ebp        
    mov ebp,esp     

;-------- procedura -------- 
    fld dword [bmp]     
    fimul dword [ebp+8]
    fist dword [res]
    xor eax, eax
    mov eax, [res]

;---------- outro ---------- 

    mov esp, ebp            
    pop ebp                 
    ret                     

C++

#include <iostream>
#include <cstring>
using namespace std;
extern "C" float fun (int a);

int main()
{
    int a;
    cin >> a;
    cout << fun(a) <<endl;
    return 0;
}

FIST 不会从浮点堆栈中弹出值——它会将它留在那里。碰巧 returning 浮点值的正常 x86 调用约定使用浮点堆栈——一个函数 returning float returns 在堆栈上只有一个值.

因此,当您将声明的 return 值更改为 float 时,C 代码从堆栈中获取该值并且似乎工作正常。这实际上比将其声明为 int 时效果更好,因为在 int 情况下,C 编译器假设 fp 堆栈为空。因为它不是,如果你重复调用你的函数,你最终会得到一个 fp 堆栈溢出(它可能会被忽略,因为这是默认行为,但仍然)。

对于一个严格正确的程序,你应该使用FISTP转换和弹出。