2015-03-07 5 views
-1

Я пытаюсь использовать функцию printTime(), написанную на C, чтобы проверить время работы моего 32 бит Программа NASM.Функция printf C не работает должным образом в сборке NASM

void printTime(float time){ 
    printf("The cpu time is %e \n" , time); 
} 

Вот часть кода NASM:

push edi   <---------------- Here edi holds int 6580001 
call printTime 
pop edi 

Вот сборка код, генерируемый GCC, и я использую GDB, чтобы отслеживать каждый шаг:

push ebp 
mov esp, ebp 
sub 0x8, esp 
flds 0x8(esp)  <------- x/d ($esp+0x8) gives me 6580001, the correct number 
sub 0x4,esp 
lea -0x8(esp),esp 
fstpl (esp) 
push 0x80486f6 
call 0x8048370 <[email protected]> <--- it prints 9.220545e-39 here, which is wrong 
add 0x10, esp 
leave 
ret 

Может кто-нибудь пожалуйста скажите, почему функция printf печатает что-то неправильно вместо 6.58001e + 5? я ценю это.

+2

Ну, вы передаете int и printTime ожидает поплавок. Они имеют разные двоичные представления. См. Здесь http://www.h-schmidt.net/FloatConverter/IEEE754.html и введите 0x646721 (ваш номер в шестнадцатеричном формате) в качестве «шестнадцатеричного представления» – Roddy

+0

@ Roddy Очень благодарю вас. –

ответ

1

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

Битовая диаграмма, образованная целым числом 6580001 (0x00646701), показана на приведенной ниже аналитической диаграмме. Число с плавающей запятой состоит из знака, предвзятого экспонента и дробной части.

seee eeee efff ffff ffff ffff ffff ffff 
0000-0000 0110-0100 0110-0111 0000-0001 

Прежде всего, давайте рассмотрим знак. Будучи 0, это означает, что число положительное. Это был легкий бит :-)

Биты экспоненты равны нулю, и в кодировке IEEE754 вы обычно вычитаете смещение 127 и поднимите два на эту мощность, чтобы получить множитель.

Однако, все ноль-экспоненты обрабатываются специально (это денормализованные числа). Во-первых, нормальная практика добавления одного из бит бит (см. Ниже) не выполняется. Во-вторых, коэффициент умножается на 2-126, а не 2-127.

Это делает множитель 1.1754943508222875079687365372222 x 10-38.

Для дробных битов, то, как правило, добавьте их место значений (уменьшая обратные два), но, так как это denormalised, вы пропустите добавив один:

110-0100 0110-0111 0000-0001 
|| | || |||   | 
|| | || |||   +- 1/8M = 0.00000011920928955078125 
|| | || ||| (64K-4M) 
|| | || ||+----------- 1/32K = 0.000030517578125 
|| | || |+------------ 1/16K = 0.00006103515625 
|| | || +------------- 1/8K = 0.0001220703125 
|| | ||  (2K,4K) 
|| | |+----------------- 1/1K = 0.0009765625 
|| | +------------------ 1/512 = 0.001953125 
|| |    (64-256) 
|| +----------------------- 1/32 = 0.03125 
||     (8,16) 
|+--------------------------- 1/4 = 0.25 
+---------------------------- 1/2 = 0.5 
             0.78439342975616455078125 

Чтобы получить фактическое номер , вы берете продукт этого результата и множитель, рассчитанный ранее, чтобы получить 9.2205004550049022573489420224302 x 10-39, что является результатом, который вы видите.

Смежные вопросы