2013-12-15 51 views
1

我想打印的浮点值与printf的printf的浮在NASM组件64位

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 

但程序打印

[[email protected] folder]$ ./programname 
0.000000 

谁可以让程序打印1.6?我究竟做错了什么?

+0

我真的不知道该调用约定的细节,但我没有料想到会需要的东西推到堆栈中。 –

回答

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 
+0

rax实际上al应该保存所使用的xmm寄存器的数量,我将它更改为1,但现在程序在printf中发生seg故障而崩溃。 printf的浮动参数存储在xmm寄存器(amd64汇编器)中,字符串地址存储在rdi中。 – user2798943

+0

您是否尝试将字符串格式更改为'%lf'? –

+0

是的,但它仍然崩溃 – user2798943

3

我怀疑问题有一些与你的代码设置rax0做的,而必须是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 
+0

我已经更改了代码,但现在它在printf中发生seg故障。 – user2798943

+0

@ user2798943:看到我编辑的答案 – szx

+0

它的工作原理,谢谢 – user2798943