0

我在使用 printf 显示浮点值时遇到问题。

我正在尝试显示一些数学函数的结果,但我总是得到 0.00。

你能帮我告诉我做错了什么吗?

我的 GNU AS 代码:

.text
text: .ascii  "Function result: %4.2f \n"
.data
x: .float 2.0
one: .float 1.0
result: .float 0.0


format: .ascii "%f"


.global main

main:
push $x
push $format
call scanf


FINIT

FLDS x  

FMULS x     #x*x

FADDS one   

FSQRT       

FSUB one        

FSTS result

xor %eax, %eax


push $result
push $text

call printf


pushl $0
call exit
4

1 回答 1

3

在 GNU 汇编器中,$指定一个文字值(编码到指令中的值)。标签的值是它的地址。所以$x, $format, $result, 和$text是这些标签的地址;它们是您拥有要标记的值的地址。printf不使用地址%f。您必须传递浮点数的值,而不是其地址。而且,正如 Frank Kotler 所指出的,您必须将其作为 64-bit 传递double,而不是 32-bit传递float

执行此操作的最简单方法可能是在指令之前插入add $-8, %esp(或add %esp, $-8,取决于汇编器版本中操作数的顺序)并将FSTS result指令更改FSTS resultFST (%esp)or FSTL (%esp),具体取决于您的汇编器。(此外,这些可能是FSTP (%esp)FSTPL (%esp)从浮点堆栈中弹出值,而不是将其保留在那里。)然后删除push $result.

这些更改将在堆栈上分配八个字节(在add指令中)并将浮点结果存储到这八个字节中。

另外,我希望您的代码负责清理传递给被调用例程的参数:它应该在调用scanf弹出两个参数后向堆栈指针添加 8,它应该在调用后添加 12printf以弹出新的八字节参数和格式字符串的四字节地址。您的程序可以在没有这些更改的情况下运行,因为您通过调用exit. ret但是,如果不清理堆栈,就不可能从带有指令的例程返回。

补充

以下代码适用于ideone.com,使用 Assembler (gcc-4.7.2) 的第二选择:

.text
text: .asciz  "Function result: %4.2f \n"
.data
x: .float 2.0
one: .float 1.0
result: .float 0.0


format: .asciz "%f"


.global main

main:
push $x
push $format
call scanf
add $8, %esp

FINIT

FLDS x  

FMULS x     #x*x

FADDS one   

FSQRT       

FSUB one        
add $-8, %esp
FSTPL (%esp)

xor %eax, %eax


push $text

call printf
add $12, %esp


pushl $0
call exit
于 2013-05-19T10:37:39.823 回答