简体   繁体   中英

C float in NASM x86 assembly

In my university project i have to use binary representation of float number in x86 assembly for arithmetic operations. Using FPU is forbidden so i try to read float number and return it as DWORD but whatever i try to do i get "-nan". Any advices?

Edit: I use gcc and it's 32 bit code

Declaration in C (i can't change that)

extern "C" float func(float num);

*.asm file

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

Example result (for 256)

01000011100000000000000000000000
11111111110000000000000000000000
num1: 256.000000
num2: -nan

Edit:

C code without checking bits part

#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;
}

If you declare the return type func as float the result will be returned in the FPU (ST0). For returning a value in EAX you have to declare it as an integer type. For printf you have to fake a float. Example:

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

Build & run:

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

In the 32 bit Linux ABI, float values are actually returned as long double at the top of the 8087 FP stack. You cannot return a float without using the FPU.

What you are probably restricted from doing is FP operations for addition, subtraction... But you still need to load the result in the FP stack to return it. In 64 bits mode, you would return float values as double in the xmm0 register.

Try changing the code to this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM