【问题标题】:C float in NASM x86 assemblyNASM x86 程序集中的 C 浮点数
【发布时间】:2015-06-04 17:23:21
【问题描述】:

在我的大学项目中,我必须在 x86 汇编中使用浮点数的二进制表示来进行算术运算。禁止使用 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;
}

【问题讨论】:

  • 您使用的是哪个 C 编译器? .asm 扩展暗示了一些微软的变种,但我不能确定。这很重要,因为有多种调用约定;我不知道你的系统使用的是哪一个。
  • GCC on 64bit linux ubuntu
  • 约定将浮点参数和返回值放在 SSE 寄存器中。在您的情况下,这意味着 numxmm0 中,这也是它应该返回的地方。
  • ...但 .asm 代码显然是 32 位...
  • 我的错。我应该告诉你我的程序必须是 32 位的(我使用 64 位 linux,但在这里没关系)

标签: c assembly x86 nasm


【解决方案1】:

如果您将返回类型 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

构建并运行:

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

【讨论】:

    【解决方案2】:

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

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

    尝试将代码更改为:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-02
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多