• Uncategorized

About assembly : Printing-floats-with-printf-in-x86-nasm-32-bit

Question Detail

I’m trying to print out some 32-bit floats using NASM flavored x86 assembly. This is a minimum working example of what I’m trying to do:

global main
extern printf, scanf

section .data
    scan_format: db "%f",0
    print_format: db "%f",0xA,0

section .bss
    result_num: resb 4

section .text
main:
    push result_num
    push scan_format
    call scanf
    add esp, 8

    push dword [result_num]
    push print_format
    call printf
    add esp, 8
    ret

When I run this, I get some strange output:

$ nasm -felf32 -g printf_test.asm
$ gcc printf_test.o -o printf_test.out
$ ./printf_test.out <<< 1234
-0.000000

If I try to examine the value while the program is running, it seems to be correct:

$ gdb ./printf_test.out
(gdb) disassemble *main
Dump of assembler code for function main:
   0x08048420 <+0>:     push   0x804a028
   0x08048425 <+5>:     push   0x804a018
   0x0804842a <+10>:    call   0x8048330 <[email protected]>
   0x0804842f <+15>:    add    esp,0x8
   0x08048432 <+18>:    push   DWORD PTR ds:0x804a028
   0x08048438 <+24>:    push   0x804a01b
   0x0804843d <+29>:    call   0x8048320 <[email protected]>
   0x08048442 <+34>:    add    esp,0x8
   0x08048445 <+37>:    ret
   0x08048446 <+38>:    nop
   0x08048447 <+39>:    nop
   0x08048448 <+40>:    nop
   0x08048449 <+41>:    nop
   0x0804844a <+42>:    nop
   0x0804844b <+43>:    nop
   0x0804844c <+44>:    nop
   0x0804844d <+45>:    nop
   0x0804844e <+46>:    nop
   0x0804844f <+47>:    nop
End of assembler dump.
(gdb) break *main+34
Breakpoint 1 at 0x8048442
(gdb) r
Starting program: /vagrant/project_03/printf_test.out
1234
-0.000000

Breakpoint 1, 0x08048442 in main ()
(gdb) p /f result_num
$1 = 1234

What am I doing wrong here?

EDIT

If I try to use doubles, it won’t even assemble, this program:

global main
extern printf, scanf

section .data
    scan_format: db "%f",0
    print_format: db "%f",0xA,0

section .bss
    result_num: resb 4
    result_num_dub: resb 8

section .text
main:
    push result_num
    push scan_format
    call scanf
    add esp, 8

    fld dword [result_num]
    fstp qword [result_num_dub]

    push qword [result_num_dub] ;ASSEMBLER ERROR HERE
    push print_format
    call printf
    add esp, 8
    ret

Generates this output:

$ nasm -felf32 -g printf_test.asm
printf_test.asm:22: error: instruction not supported in 32-bit mode

And if I try to go directly from the float stack to the memory stack, I get a segfault, even though the right thing appears to be stored in memory.

fld dword [result_num]
fstp qword [esp]
push format

call printf

It looks right in gdb:

(gdb) p  *((double*)($esp))
$9 = 2.5

But it generates a segfault in the middle of the printf call.

I have to be missing something.

Question Answer

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.