Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
664 views
in Technique[技术] by (71.8m points)

printf - How to print floating point numbers from assembly?

I'm trying to print a floating point number by calling printf but it seems to always just print the pi value (3.1415) although the result, which is supposed to be the area of a circle, is supposed to be moved to the pi variable after being calculated.

.section .data
    value:
        .quad 0
    result:
            .asciz "The result is %lf 
"
    pi:
        .double 3.14159

.section .bss
.section .text
.globl _start
.type area, @function
area:

    nop
    imulq %rbx, %rbx
    movq %rbx, value
    fildq value
    fmul pi                           # multiply r^2 by pi
    fst  pi                           # Store result to pi
    movupd pi, %xmm0                  # move result to xmm0
    nop
    ret

_start:

    nop
    movq $2, %rbx
    call area                 # calculate for radius 2
    leaq result, %rdi         
    movq $1, %rax             # specify only one float value
    call printf                 
    movq $0, %rdi             # Exit
    call exit                     
    nop

I always get 3.1415 back. I dont know why as it's supposed to be overwritten by the fst instruction.

question from:https://stackoverflow.com/questions/65940008/how-to-print-floating-point-numbers-from-assembly

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to add a size suffix to your floating point operations if they happen to use memory operands. Otherwise, the GNU assembler will implicitly use single precision which is not what you want. To fix your code, change

fmul pi                           # multiply r^2 by pi
fst  pi                           # Store result to pi

to

fmull pi                           # multiply r^2 by pi
fstl  pi                           # Store result to pi

Some other remarks about your code:

  • use rip-relative addressing modes instead of absolute addressing modes if possible. Specifically, this means to replace foo with foo(%rip) in your memory operands, including for lea result(%rip), %rdi

  • make sure to leave a clean x87 stack at the end of your functions or other code may spuriously cause it to overflow. For example, use fstpl pi(%rip) to store the result and pop it off the stack.

  • use movsd, not movupd to load one double into an SSE register, not a pair.

  • consider using SSE instead of x87 if possible for all the math. It's the standard way to do scalar FP math in x86-64, that's why XMM registers are part of the calling convention. (Unless you need 80-bit extended precision, but you have a pi constant in memory that's far less accurate than x87 fldpi.)

       ...
       cvtsi2sd   %rbx, %xmm0
       mulsd      pi(%rip), %xmm0
       ret
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...