我在使用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
1条答案
按热度按时间vmjh9lq91#
在GNU汇编程序中,
$
指定一个文字值(编码到指令中的值)。标签的值就是它的地址。所以$x
、$format
、$result
和$text
是这些标签的地址;它们是你所标注的值所在的地址。printf
不使用%f
的地址。必须传递浮点数的值,而不是其地址。而且,正如Frank Kotler所指出的,必须将其作为64位double
传递,而不是32位float
,因为对于可变参数函数,C规则隐式地将FP参数提升为double
,就像窄整数类型提升为int
一样。最简单的方法可能是在
FSTS result
指令之前插入add $-8, %esp
,并将FSTS result
指令更改为FSTL (%esp)
,以将64位double
存储到堆栈中。(或者FSTPL (%esp)
从浮点堆栈中弹出值,而不是将其留在那里。)然后删除push $result
。这些更改将在堆栈上分配8个字节(在
add
指令中),并将浮点结果存储到这8个字节中。另外,我希望你的代码负责清理传递给调用例程的参数:在调用
scanf
弹出两个参数后,它应该向堆栈指针添加8,在调用printf
弹出新的8字节参数和格式字符串的4字节地址后,它应该添加12。您的程序可以在没有这些更改的情况下工作,因为您通过调用exit
终止了程序。但是,如果不清理堆栈,则无法从具有ret
指令的例程返回。补充
下面的代码在ideone.com上工作,使用Assembler的第二个选择(gcc-4.7.2):