assembly 用printf显示浮点数

xwmevbvl  于 2023-05-23  发布在  其他
关注(0)|答案(1)|浏览(137)

我在使用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
vmjh9lq9

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):

.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

相关问题