Вопрос сборки Intel x86 сопроцессора - PullRequest
1 голос
/ 20 января 2010

У меня возникли некоторые проблемы с пониманием того, как получить результат вычисления, выполненного с использованием сопроцессора Intel x86.

Пожалуйста, рассмотрите следующий сегмент данных.

.data

res real4 ?
x real4 5.0
k real4 3.4

и следующий кодсегменты, версия 1 :

.code

main:

fld x      ; 5.0
fadd k1    ; 5.0 + 3.4
fistp res  ; store as integer (it will round, in this case down)

mov eax, res ; eax = 00000008

end main

и версия 2 :

.code

main:

fld x     ; 5.0
fadd k    ; 5.0 + 3.4
fstp res  ; store as real

mov eax, res ; eax = 41066666

end main

Я понимаю версия 1 ,без проблем.

Это версия 2 Я не понимаю.Я вижу в отладчике, что он выполняет точные вычисления, как в версии 1, но когда приходит время для сохранения, он делает это как «41066666» !?

В чем причина этого?
Какое "кодирование" использовалось для преобразования 8.4 в "41066666"?
Есть ли способ преобразовать его обратно в 8.4, чтобы я мог его распечататьв консоли (например, с помощью функции библиотеки StdOut masm32)?

Спасибо.

Ответы [ 3 ]

4 голосов
/ 20 января 2010

Калькулятор с плавающей точкой и конвертер

Введите 8.4, и вы увидите, что шестнадцатеричная версия числа представлена ​​в виде: 41066666

3 голосов
/ 20 января 2010

0x41066666 - это 8,4 (точнее, 8,3999996185302734375), закодированный в формате IEEE-754 с одинарной точностью.Вы можете легко отобразить его значение в виде шестнадцатеричного числа, извлекая поля компонента из кодировки, что даст вам 0x8.66666, но преобразовать его в десятичное довольно сложно сделать правильно.Если вы хотите получить десятичный вывод, проще всего связать библиотеку C в вашей системе и использовать функцию printf.

В качестве альтернативы, как предложено wallyk , взять источникдля одной из процедур преобразования с открытым исходным кодом (или написать свою собственную реализацию, хотя это удивительно сложная задача, чтобы преуспеть).Вероятно, лучшие легкодоступные источники находятся в файле gdtoa.tgz на Netlib .Сложность этой реализации должна дать вам некоторое представление о проблемах, которые могут возникнуть, и может привести к тому, что вы вернетесь к использованию библиотеки =)

3 голосов
/ 20 января 2010

Кодировка - IEEE-754 формат с плавающей запятой. Похоже, вы используете 32-разрядные числа с плавающей запятой, также известные как одинарная точность. Этот формат содержит знаковый бит, восьмибитную экспоненту, которая смещена на 127 (может быть, 128 - я не помню, от руки) и 24 бита мантиссы, где хранится 23, а недостающий бит является наиболее значимым и обычно имеет значение один, за исключением ненормальных значений. Существует несколько паттернов с особым значением: ноль, NaN , бесконечность и денормали.

Помимо внешнего инструмента, предложенного CookieOfFortune, вы можете написать преобразование с плавающей запятой в ASCII, выполняя различные арифметические операции для определения значения. Есть много алгоритмов, которые компромисс скорость для пространства. См. Любой источник библиотеки времени выполнения для ftoa или преобразований% f или% g для printf().

...