Пример (для 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 (значения st0 .. st7
) и памяти по адресу result
.
редактирование:
Я понимаю, что каждая операция с плавающей запятой должна выполняться FPU.
Абсолютно нет, если вы так думаете, вам все еще не хватает всего принципа компьютеров. Все в компьютере кодируется как последовательность битов (значение 0 или 1). Итак, ваше утверждение в переводе на эту базовую предпосылку звучит так: «У меня здесь есть один битовый шаблон, другой битовый шаблон, четко определенная операция, описывающая, какой третий битовый шаблон должна генерировать какая-то операция, но я не могу сделать это, если у меня нет ФПУ "- это звучит логично для вас?
Это большая работа (десятки инструкций x86) для умножения двух двойных значений IEEE-754 вручную, вам нужно извлечь части экспоненты и мантиссы этих значений, умножить мантиссу и экспоненты отдельно, а затем нормализовать / зажать оцените и скомпилируйте действительный результат двойного типа IEEE-754 обратно в 64 бита, но это определенно выполнимо без FPU, это то, что программная эмуляция x87 делала все время, пока 80486DX и процессоры Pentium не сделали аппаратный FPU общим (80486SX и предшественники 80286 и 80386 не имели встроенного x87, он продавался как отдельный дорогой сопроцессорный чип). Во времена 386 большинство людей использовали SW-эмуляторы x87 для запуска специализированного программного обеспечения, которое требовало FPU.
Дело в том, что если вы понимаете, как что-то (входная информация) кодируется в битах, и что вы хотите получить в качестве выходной информации (кодируется в битах), и вы можете описать некоторый алгоритм операций с битами, преобразующий входное значение в выходное значение, то вы можете реализовать такой алгоритм с помощью любого Turing-совместимого ЦП (хотя в некоторых очень ограниченных системах, таких как 8-битные ЦП, PITA может быть основной для создания двойного * двойного вычисления IEEE-754, так как для этого потребуется, вероятно, сотни инструкций или вы можете даже исчерпать ресурсы, если память слишком ограничена для одновременного хранения большого количества битов).
x87 FPU - это просто аппаратно-ускоренное решение для операций с плавающей запятой, это не единственный возможный способ вычисления чего-либо.