NASM x86,FIST 的意外结果

Posted

技术标签:

【中文标题】NASM x86,FIST 的意外结果【英文标题】:NASM x86, unexpected result of FIST 【发布时间】:2015-01-10 02:10:35 【问题描述】:

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

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

我唯一猜测的可能是在返回浮点数的情况下,它是从浮点数堆栈中取出的,因为我没有从那里弹出它,这就是答案。

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 converts ST0 to an integer and stores that in memory;"(src)。然后,您从内存中获取该值并返回它。它是一个整数。 好的,如果我错了,请纠正我。如果我尝试将整数作为浮点数返回,它应该类似于 x.00000 (我的意思是带点和零的整数)。但是,当我在函数声明中交换 float 和 int 时,我得到 11.58 而不是 12.000。 根据您使用的编译器,高级语言可能会在 FP 堆栈上预期浮点结果,这就是您离开它的地方(也是),因为您没有这样做FISTP (最后弹出)。 您知道整数和浮点值在内存中的存储方式完全不同,对吧? 好的。所以这就是我想知道的。谢谢你。 @JonathonReinhart - 好吧......我实际上已经忘记了这个:) 【参考方案1】:

FIST 不会将值从浮点堆栈中弹出——它会将其保留在那里。碰巧返回浮点值的普通 x86 调用约定使用浮点堆栈——返回浮点的函数仅返回堆栈上的单个值。

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

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

【讨论】:

以上是关于NASM x86,FIST 的意外结果的主要内容,如果未能解决你的问题,请参考以下文章

顶部带有 %include 的程序集 - 打印输出意外结果:只是一个“S”

是啥导致“ConvertResourcesCases”意外失败?

SignTool 错误:发生了意外的内部错误。错误 MSB3482

laravel 中查询的意外结果

为啥“+=”会给我在 SSE 内在的意外结果

NSDateComponents 返回意外结果