C浮动在NASM x86组件中

时间:2015-06-04 17:23:22

标签: c assembly x86 nasm

在我的大学项目中,我必须在x86程序集中使用float number的二进制表示来进行算术运算。禁止使用FPU,因此我尝试读取浮点数并将其作为DWORD返回,但无论我尝试做什么,我都会得到" -nan"。有什么建议吗?

编辑: 我使用gcc和它的32位代码

C中的声明(我无法改变)

extern "C" float func(float num);

* .asm文件

section .text
global  func

func:
;prolog
    push    ebp
    mov ebp, esp

; zapamiętanie rejestrów zachowywanych
    push ebx
    push esi
    push edi

    mov eax, DWORD [ebp+8]
    ;mov eax, 0xffffffff i checked that but i still get the same result

; odtworzenie rejestrów, które były zapamiętane
    pop edi
    pop esi
    pop ebx

;epilog 
    pop ebp
    ret

示例结果(对于256)

01000011100000000000000000000000
11111111110000000000000000000000
num1: 256.000000
num2: -nan

编辑:

不检查位部分的C代码

#include <stdio.h>

extern "C" float func(float num);

int main()
{
    float num1;
    float num2;

    scanf("%f", &num1);
    num2=func(num1);

    printf("num1: %f\nnum2: %f\n", num1, num2);
    return 0;
}

2 个答案:

答案 0 :(得分:3)

如果将返回类型func声明为float,则结果将在FPU(ST0)中返回。要返回EAX中的值,必须将其声明为整数类型。对于printf,你必须伪造一个浮动。例如:

<强> caller.c:

#include <stdio.h>
#include <stdint.h>
extern float asmfunc1(float);
extern uint32_t asmfunc2(float);

int main (void)
{
    printf ("asmfunc1: %f\n", asmfunc1(456.78));

    uint32_t ifl = asmfunc2(123.45);
    float* pfl = (float*) &ifl;             // Faking a float
    printf ("asmfunc2: %f\n", *pfl);

    return 0;
}

<强> callee.asm:

section .text
global asmfunc1, asmfunc2

asmfunc1:
    fld dword [esp+4]
    ret

asmfunc2:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    leave
    ret

构建&amp;运行

nasm -felf callee.asm
gcc -m32 callee.o caller.c
./a.out

答案 1 :(得分:2)

在32位Linux ABI中,float值实际上返回到8087 FP堆栈顶部的long double。如果不使用FPU,则无法返回float

你可能被限制做的是加法,减法的FP操作......但你仍然需要将结果加载到FP堆栈中以返回它。在64位模式下,您会在float寄存器中将double值作为xmm0返回。

尝试将代码更改为:

    section .text
    global  func
func:
    push    ebp
    mov     ebp, esp
    flds    8(%ebp)
    pop     ebp
    ret