我可以从我的EAX / RAX中获取一个int到FPU的寄存器,如st0吗?

时间:2018-05-08 19:26:40

标签: assembly x86 nasm fpu

我目前正在大学开展一个小型的Assembler项目。现在我的问题是,是否有可能得到一个乘法器(int)的skalar,这是由用户给出的,从我的EAX / RAX寄存器到我的FPU寄存器之一,如st0?我正在使用NASM语法。

谢谢

2 个答案:

答案 0 :(得分:5)

无法直接将整数寄存器的内容传送到x87浮点寄存器,您必须通过内存。典型代码如下所示:

PUSH RAX         ; push RAX on the stack
FILD QWORD [RSP] ; load eight byte integer onto FP stack
ADD RSP,8        ; release storage from stack

通常可以避免在函数开头的堆栈框架中为这种传输分配一些存储空间来摆弄堆栈指针。

答案 1 :(得分:2)

示例(适用于64b linux和NASM),根据fuz的回答进行计算:

; file: x87test.asm
section .data
    some_value  dq 1234.5678    ; double value

section .bss
    result      resq    1       ; reserve memory for result double
    result2     resq    1       ; reserve memory for second result (code variant 2)

section .text
    global _start
    _start:
        ; initializations of example
        finit                       ; initialize FPU
        ; store "factor" into the stack
        mov     rax,__float64__(51.6)
        push    rax
        ; "value" is already in memory at address `some_value`

        ; load the FPU-stack with factor and value
        fld     qword [some_value]  ; st0 = value
        fld     qword [rsp]         ; st0 = factor, st1 = value
        add     rsp, 8              ; release the CPU stack space occupied by factor (by "push rax")

        ; Do the calculation with st0 and st1
        fmulp   st1                 ; st0 = st0 * st1 with "pop" (the FP stack holds only "st0")
            ; "fmul" without "p" would keep the "st1" intact (value) and st0 = product
        fstp    qword [result]      ; "pop" st0 into memory at "result" address

        ;--------------------------------------------------------------------------------------------
        ; other variant, skipping the load of second value, as the FMUL can use memory argument too
        ; store "factor" into the stack
        mov     rax,__float64__(7.89)
        push    rax

        ; load the FPU-stack with value
        fld     qword [some_value]  ; st0 = value
        fmul    qword [rsp]         ; st0 = value * factor
        add     rsp, 8              ; release the CPU stack space occupied by factor (by "push rax")
        fstp    qword [result2]     ; "pop" st0 into memory at "result2" address

        ;--------------------------------------------------------------------------------------------
        ; exit back to linux
        mov     eax, 60
        xor     edi, edi
        syscall

使用以下内容构建并执行:

nasm -f elf64 x87test.asm -l x87test.lst -w+all
ld -b elf64-x86-64 -o x87test x87test.o
./x87test

不应该输入/输出,只需清除退出。检查调试器,单步执行每条指令,并观察堆栈(由rsp指向的)内存区域,以及x87 FPU" stack" (st0 .. st7值)和result地址的内存。

编辑:

  

我知道每个浮点操作都必须由FPU完成。

绝对不,如果你这么认为,你仍然缺少计算机的整个原理。计算机中的所有内容都编码为位序列(值0或1)。所以当你翻译成这个基本前提时你的陈述是"我在这里有一个位模式,其他位模式,一个定义明确的操作描述了某些操作应该产生的第三位模式,但是我不能这样做我没有FPU" - 这听起来合乎逻辑吗?

将两个IEEE-754"倍"相乘的大量工作(数十个x86指令)。手动值,你需要提取这些值的指数和尾数部分,分别乘以尾数和指数,然后归一化/钳制该值并组成一个有效的IEEE-754" double"将结果输回64位,但如果没有FPU,它绝对可行,这是x87的软件仿真在80486DX和奔腾CPU使硬件FPU通用之前所做的一切(80486SX和前辈80286和80386)它没有内置的x87,它作为单独的昂贵的协处理器芯片出售。在386时代,大多数人都使用x87的SW模拟器来运行需要FPU的专用软件。

问题是,如果您了解某些内容(输入信息)是如何以位编码的,以及您想要什么作为输出信息(以位编码),您可以描述某些位操作操作转换输入值的算法输入值,然后你可以通过任何符合图灵的CPU实现这样的算法(虽然有一些非常有限的系统,如8位CPU,它可能是主要的PITA创建IEEE-754双*双计算,因为它可能需要数百条指令,或者你甚至可能耗尽资源,如果内存太有限,无法同时保存这么多位。)

x87 FPU只是浮点运算的硬件加速解决方案,它不是唯一可行的计算方法。