在 fuz 答案下的 cmets 中计算的示例(适用于 64b linux 和 NASM):
; 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“堆栈”(st0 .. st7 值)和result 地址处的内存。
编辑:
我的理解是每个浮点运算都必须由 FPU 完成。
绝对不,如果你这么认为,你仍然缺少计算机的整个原理。计算机中的所有内容都被编码为位序列(值 0 或 1)。所以你的陈述当翻译成这个基本前提时是“我这里有一个位模式,那里有另一个位模式,一个定义明确的操作,描述了某个操作应该产生哪个第三位模式,但如果我没有,我就做不到FPU”——这听起来合乎逻辑吗?
手动将两个 IEEE-754 “双精度”值相乘需要大量工作(数十条 x86 指令),您需要提取这些值的指数和尾数部分,分别将尾数和指数相乘,然后归一化/钳位值并将有效的 IEEE-754 "double" 类型结果组合回 64 位,但在没有 FPU 的情况下绝对可行,这就是 x87 的软件仿真在 80486DX 和 Pentium CPU 使硬件 FPU 通用(80486SX 和前辈)之前一直所做的80286 和 80386 没有内置 x87,它作为单独的昂贵协处理器芯片出售)。在 386 时代,大多数人确实使用 x87 的 SW 仿真器来运行需要 FPU 的专用软件。
问题是,如果您了解某事物(输入信息)如何以位编码,以及您想要什么作为输出信息(以位编码),您就可以描述一些位操作运算的算法来转换输入值转换为输出值,然后您可以通过任何符合图灵的 CPU 实现这种算法(尽管对于一些非常有限的系统,如 8 位 CPU,创建 IEEE-754 双 * 双计算可能是主要的 PITA,因为它可能需要数百条指令,或者如果内存太有限而无法同时容纳这么多位,您甚至可能会耗尽资源)。
x87 FPU 只是浮点运算的硬件加速解决方案,并不是唯一可能的计算方式。