Могу ли я получить int из моего EAX / RAX в регистр FPU вроде st0? - PullRequest
0 голосов
/ 08 мая 2018

В настоящее время я работаю над небольшим проектом ассемблера в университете. Теперь мой вопрос: возможно ли получить скаляр для умножения (int), которое дает пользователь, из моего регистра EAX / RAX в один из моих регистров FPU, например st0? Я использую синтаксис NASM.

Спасибо

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Пример (для 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 - это просто аппаратно-ускоренное решение для операций с плавающей запятой, это не единственный возможный способ вычисления чего-либо.

0 голосов
/ 08 мая 2018

Невозможно напрямую передать содержимое целочисленного регистра в регистр с плавающей запятой 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

Обычно вы можете избежать необходимости возиться с указателем стека, выделяя некоторую память для такого рода передачи в вашем кадре стека в начале вашей функции.

...