NASM x64:浮点部分错误地打印为 0.000000

问题描述 投票:0回答:1

我是汇编新手,我尝试在 Windows (x64) 上使用 NASM 编写汇编程序来提取和打印浮点数的小数部分。但是,我的程序打印

Floating Point Part: 0.000000
而不是预期的
Floating Point Part: 0.500000

这是我当前的代码:

section .data
    fmt db "Floating Point Part: %f", 10, 0
    float_value dq 10.5
    result dq 0.0

section .text
global main
extern printf

main:
    ; Function prologue
    push rbp
    mov rbp, rsp
    sub rsp, 32              ; Allocate shadow space

    ; Load floating-point value into the FPU
    fld qword [rel float_value]

    ; Call floatVal function
    call floatVal

    ; Store result from the FPU to memory
    fstp qword [rel result]

    ; Print the result using printf
    lea rcx, [rel fmt]       ; First argument: format string
    lea rdx, [rel result]    ; Second argument: address of result
    movsd xmm0, qword [rdx]  ; Move the double to xmm0 for printf
    call printf

    ; Function epilogue
    add rsp, 32              ; Deallocate shadow space
    mov eax, 0
    pop rbp
    ret

floatVal:
    ; Function prologue
    push rbp
    mov rbp, rsp
    sub rsp, 32              ; Allocate shadow space

    ; Get the integer part
    fld st0                  ; Copy the value to the top of the stack
    frndint                  ; Round to integer
    fsub                     ; Subtract integer part from original value (st0 - st1)

    ; Function epilogue
    add rsp, 32              ; Deallocate shadow space
    pop rbp
    ret

编译与执行步骤:

nasm -f win64 flo.asm -o flo.o
gcc -m64 -o flo flo.o -lkernel32 -lmsvcrt
.\flo.exe

预期输出:

Floating Point Part: 0.500000

实际产量:

Floating Point Part: 0.000000

环境:

  • Windows 10 x64
  • NASM
  • Mingw-w64

我尝试过的:

  • 确保正确处理浮点运算。
  • 检查堆栈是否正确对齐并分配影子空间。
  • 尝试直接打印整个浮点值以隔离问题。
  • 使用 RIP 相对寻址来确保正确的地址处理。

浮点运算看似执行了,但结果不是我所期望的。看起来结果可能被覆盖或未正确传递给 printf。

我到底需要知道什么

  • 为什么程序打印 0.000000 而不是预期的小数部分?
  • 浮点处理或函数调用约定是否有错误?
  • 如何正确打印浮点数的小数部分?

我对低级编程非常陌生,任何帮助或建议将不胜感激。

PS: 我发现之前在 StackOverflow 中发布的相同问题,并尝试更新引用它们的代码。他们不为我工作,我对重新发布表示歉意

assembly floating-point 64-bit nasm mingw-w64
1个回答
0
投票

根据调用约定,第二个参数进入

xmm1
而不是
xmm0
。此外,它应该复制到
rdx
“第二个参数:结果的地址” 没有任何意义,因为
printf
不需要双精度值的地址。你应该这样做:

lea rcx, [rel fmt]       ; First argument: format string
movsd xmm1, [rel result] ; Move the double to xmm1 for printf
movq rdx, xmm1           ; duplicate second argument as per convention
call printf

此外,在 64 位模式下,您通常应该完全避免使用 x87 FPU。叶子函数不需要分配影子空间。

© www.soinside.com 2019 - 2024. All rights reserved.