我想用printf打印一个float值
global main
extern printf
section .data
string: db `%f\n`, 0
section .bss
rs: resq 1
[...]
movq xmm0, [rs]
mov rdi, string
mov rax, 0
call printf
rs包含浮点值1.6
(gdb) x/fg &rs
0x600ad8 <rs>: 1.6000000000000001
但程序会打印
[username@localhost folder]$ ./programname
0.000000
谁能让程序打印1.6?我做错了什么?
3条答案
按热度按时间vmpqdwk31#
第一个问题是您的代码将
AL
(通过RAX
)设置为0
,而它必须是1
,因为您传递了一个浮点参数(有关详细信息,请参阅here)。基本上,AL
应该包含xmmN
寄存器中传递的变量参数的数量。如果不进行其他更改,修复该问题将导致
printf
,caused by stack misalignment内部的segfault。程序在movaps
指令处崩溃(该指令期望内存操作数在16字节边界上对齐):当输入
main
(或任何其他函数)时,堆栈对齐RSP%16 == 8,但在call
之前需要RSP%16 == 0。如果你解决了这个问题,程序工作正常。下面是我的测试程序(注意开始的sub rsp, 8
):可能的陷阱和相关的Q& A:
printf
与原始_exit()
系统调用混合。call printf
的PLT存根,例如在PIE可执行文件中。gwbalxhn2#
我做错了什么
第一个:请确保您使用正确的呼叫约定(堆栈、寄存器、从左到右、从右到左等).如果你的程序确实打印了一个浮点数,虽然它不是你所要求的那个然后至少格式字符串被正确地传递(或者你运气很好,
printf
在正确的位置找到了格式字符串的地址,即使你没有把它的地址放在那里)。第二个:你要打印的数字...是float还是double?
rs
定义的是一个四字值(64位),但float是32位。所以,如果第一个点已经检查过了,没有问题,我建议你使用"%lf"
作为格式,而不是"%f"
。顺便问一句:你为什么把
RAX = 0
?这是什么意思,关于调用printf
?更新:这可能对你有帮助。一个愚蠢的程序(
f.c
)的反汇编:$ gcc -c -S f.c
$ less f.s
gt0wga4j3#