2016-09-05 15 views
1

Недавно писал небольшие программы с номерами fp. Сначала я прочитал двойной FP в выровненных местоположениях (для SSE инструкции)Почему я получаю плавающий, а не двойной, от scanf?

segment .data 
scanf_fmt: 
     db "%f%ld", 0 

    segment .bss 
    align 16, db 0 
x  resq 1  ; for double fp 
number resq 1  ; for integer 
    align 16, db 0 
res resq 1  ; for double fp 

lea rdi, [fmt] 
lea rsi, [x] 
lea rdx, [number] 
xor eax, eax ; number of fp values(edited from mov rax, 1 ,still looks the same) 
call scanf 

Затем я перехожу дважды:

movsd xmm0, [x] 

Тогда я начал отладки: я напечатал в 1.6 для зсапЕ читать ,

100 movsd xmm0, [x] 
(gdb) p/f x 
$1 = 1.60000002 
(gdb) n 
(gdb) p $xmm0 
$2 = {v4_float = {1.600000002, 0, 0, 0}, v2_double = {5.2..., 0}, ... 

значение с плавающей точкой на этикетке x переехал, но, как поплавок (movss) не как двойной (movsd, который я использовал)

Что здесь происходит?

+2

Вам нужно показать свою полную программу, как вы ее создали, как вы ее запускали и что вы набрали, когда вы ее запускали. Вам также нужно сказать, что вы ожидали отобразить в отладчике. –

+0

'mov rax, 1' является ошибкой. Вы передаете указатель в двойник в целочисленном регистре, а нулевые аргументы FP - в xmm regs. –

+0

@RossRidge Build: 'yasm -f elf64 -g dwarf2 main.asm; gcc -o main main.o' Run: './main' Набираемый текст:' 1.6' Ожидайте что-то вроде '{v4_float = {smth, 0, 0, 0}, v2_double = {1.6, 0}, .. . –

ответ

3

От scanf(3):

%f Соответствует необязательно число с плавающей точкой; следующий указатель должен быть указателем на float.

Так зсапЕ хранится 32-разрядный с одинарной точностью float в [x], как вы сказали ей. Следующие 32 бита остаются равными нулю.

Все, что вы видели, является очевидным следствием этого.


Конверсия спецификатор для double является %lf, как вы можете быстро найти путем поиска «двойной» на странице человека.

+0

Как читать с точным номером с плавающей запятой scanf точно? Так что scanf поместит 8 байтов в ячейку памяти в соответствии с IEEE 754, а не только по 4 байта с плавающей запятой. Их форматы схожи, но, тем не менее, невозможно сделать двойной выход из float только с заполнением 4 нулевых байта в передней части float. –

+2

поиск 'double' на странице man, как обычный человек. Это так же, как если бы вы делали это в C. –

+0

А, очевидно, нужно читать mans («lf» для чтения double). Теперь xmm0 в gdb напечатано, как ожидалось. –