我想用printf
打印浮点值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吗?我做错了什么?
答案 0 :(得分:6)
我怀疑问题与您的代码设置rax
到0
有关,而它必须是1
,因为您传递了一个浮点参数(请参阅here细节)。基本上rax
应该包含xmmN
寄存器中传递的变量参数的数量。
编辑:
printf
中的崩溃似乎是由堆栈miaslignment引起的,因为程序在movaps
指令崩溃(期望内存操作数在16字节边界上对齐):
=> 0x7ffff7a65f84 <__printf+36>: movaps %xmm0,0x50(%rsp)
0x7ffff7a65f89 <__printf+41>: movaps %xmm1,0x60(%rsp)
0x7ffff7a65f8e <__printf+46>: movaps %xmm2,0x70(%rsp)
0x7ffff7a65f93 <__printf+51>: movaps %xmm3,0x80(%rsp)
0x7ffff7a65f9b <__printf+59>: movaps %xmm4,0x90(%rsp)
0x7ffff7a65fa3 <__printf+67>: movaps %xmm5,0xa0(%rsp)
0x7ffff7a65fab <__printf+75>: movaps %xmm6,0xb0(%rsp)
0x7ffff7a65fb3 <__printf+83>: movaps %xmm7,0xc0(%rsp)
当输入main
时,堆栈不是16字节对齐的,但是如果你修复了这个,那么程序运行正常。以下是我的测试程序(注意开头的sub rsp, 8
):
global main
extern printf
section .data
string db `%f\n`, 0
rs dq 1.6
section .text
main:
sub rsp, 8
movq xmm0, qword [rs]
mov rdi, string
mov rax, 1
call printf
add rsp, 8
mov eax, 0x60
xor edi, edi
syscall
答案 1 :(得分:1)
我做错了什么?
首先:确保使用正确的调用约定(堆栈,寄存器,从左到右,从右到左等)。如果你的程序确实打印了一个浮点数,虽然它不是你需要的那个,那么至少格式字符串正在正确传递(或者你运气很好,printf
找到格式的地址即使你没有把地址放在那里,也要把它放在正确的地方。
第二次:您要打印的数字......是浮动还是双倍? rs
被定义为保持四字值(64位),但浮点数为32位。因此,如果已经检查了第一个点并且没有问题,我建议您使用"%lf"
作为格式,而不是"%f"
。
RAX = 0
?对printf
的调用意味着什么?
更新:这可能会对您有所帮助。一个愚蠢的程序的反汇编(f.c
):
#include <stdio.h>
main()
{
float x;
x = 1.6;
printf ("%f\n", x);
}
$ gcc -c -S f.c
$ less f.s
.file "f.c"
.section .rodata
.LC1:
.string "%f\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0x3fcccccd, %eax
movl %eax, -4(%rbp)
movss -4(%rbp), %xmm0
cvtps2pd %xmm0, %xmm0
movl $.LC1, %eax
movq %rax, %rdi
movl $1, %eax
call printf
leave