【问题标题】:Why am I getting a float, not a double, from scanf? [closed]为什么我从 scanf 得到一个浮点数而不是双精度数? [关闭]
【发布时间】:2016-09-05 05:52:09
【问题描述】:

最近在写fp数的小程序。 首先,我将双 fp 读入对齐的位置(对于 SSE 指令)

    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让scanf读取。

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,我使用过)

这是怎么回事?

【问题讨论】:

  • 你需要展示你的完整程序,你是如何构建它的,你是如何运行它的,以及你在运行它时输入了什么。您还需要说出您希望在调试器中显示的内容。
  • mov rax, 1 是一个错误。您在整数寄存器中传递一个指向双精度的指针,在 xmm regs 中传递零 FP args。
  • @RossRidge Build: yasm -f elf64 -g dwarf2 main.asm; gcc -o main main.o Run: ./main Typed: 1.6 期望类似{v4_float = {smth, 0, 0, 0}, v2_double = {1.6, 0}, ...
  • 您不应该期望 v4_float 的第二个元素为零,除非双精度数的尾数的低 32 位全为零。 (这只有在它完全可表示的情况下才有可能,例如 0.5 或整数之类的)
  • 更重要的是,你用的是什么格式的字符串?

标签: assembly x86-64 sse


【解决方案1】:

来自scanf(3)

%f 匹配可选带符号的浮点数; next 指针必须是指向float 的指针。

所以 scanf 将 32 位单精度 float 存储到 [x] 中,就像你告诉它的那样。接下来的 32 位保持为零。

你看到的其他一切都是明显的结果。


double 的转换说明符是 %lf,您可以通过在手册页中搜索“double”快速找到。

【讨论】:

  • 如何准确读取scanf双浮点数?这样 scanf 将根据 IEEE 754 在内存位置放置 8 字节双精度,而不仅仅是 4 字节单精度浮点数。它们的格式相似,但仅在 float 的前面填充 4 个零字节是不可能的。
  • 像普通人一样在手册页中搜索double。就像在 C 中执行此操作一样。
  • 啊,很明显,需要阅读 mans(“lf” 用于阅读双精度)。现在 gdb 中的 xmm0 按预期打印。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多