cgm*_*gmb 6 assembly printf x86-64
我正在尝试在x86_64程序集中打印浮点数,但它只是将值打印为零.
关于这个问题已经存在一些问题.通过确保设置在%al中使用的向量寄存器的数量,似乎可以解决一个问题.另一个表明你需要一个16字节的堆栈对齐.但是,我正在做这两件事而仍然没有得到正确的输出.
这是我的计划:
# prints a floating point value
.section .rodata
.fmt: .string "num: %f\n"
.num: .float 123.4
.section .text
.global main
.type main, @function
main:
subq $8, %rsp # 16-byte alignment
# print my number
movss .num, %xmm0 # load float value
movq $.fmt, %rdi # load format string
movb $1, %al # use 1 vector register
call printf
# exit
addq $8, %rsp # undo alignment
movq $0, %rax # return 0
ret
Run Code Online (Sandbox Code Playgroud)
Pet*_*des 10
printf(3)的%f格式说明想要一个double.没有办法让printf接受afloat,onlydouble或long double.
C的默认参数提升指定对可变参数函数的调用,如foo(char *fmt, ...)提升float到double,并执行通常的窄整数类型的整数提升,以int用于跟踪...与原型部分匹配的args .(这同样适用于没有原型的调用函数的所有args.) N1570 6.5.2.2函数调用,第6和7小节.
因此,C不允许调用者传递float给printf,因此它没有转换,并且%f意味着double.(%lf也适用于double,假设实现忽略它的非整数/ wchar_t转换. 接受%lf了double在C99/C11和C++ 11个需要printf实现,所以你可以放心地使用相同的%lf格式字符串用double的printf和scanf).
请注意,这scanf是不同的,因为float *并且double *不受这些促销的影响.
CVTSS2SD .num, %xmm0.如果你看一下编译器输出,你会看到gcc做你所做的一切,并且pxor首先使用-zero寄存器来打破对旧值的错误依赖%xmm0.(cvtss2sd糟糕的设计使目标的高64位保持不变.)gcc在谨慎方面犯了错误,并且在许多情况下插入xor-zeroing指令以打破错误依赖.
你可能得到0因为xmm0的高位恰好为零.当printf将xmm0的低64位视为double(x86上的IEEE binary64)时,它会123.4f在尾数的低32位中找到位模式,其余为零.这代表一个非常小的(非正规)数字,所以它与零一起出现%f.
您可以尝试使用等效的float(例如,在http://www.h-schmidt.net/FloatConverter/IEEE754.html上),在低半部分设置一些位以查看您得到的内容.
如果使用%g(科学记数法)或%a(double位模式的十六进制表示),则会显示非零位.(除非你在MXCSR中启用了Denormals Are Zero模式.)
| 归档时间: |
|
| 查看次数: |
2978 次 |
| 最近记录: |