Assembly 用printf显示浮点

Assembly 用printf显示浮点,assembly,floating-point,shared-libraries,printf,Assembly,Floating Point,Shared Libraries,Printf,我在使用printf显示浮点值时遇到问题 我试图显示一些数学函数的结果,但我总是得到0.00 你能帮我说说我做错了什么吗 我的GNU代码: .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

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

我试图显示一些数学函数的结果,但我总是得到0.00

你能帮我说说我做错了什么吗

我的GNU代码:

.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

在GNU汇编程序中,
$
指定一个文本值(编码到指令中的值)。标签的值是其地址。因此,
$x
$format
$result
$text
是这些标签的地址;它们是包含要标记的值的地址
printf
不使用
%f
的地址。必须传递浮点数的值,而不是其地址。而且,正如Frank Kotler所指出的,您必须将其作为64位
双精度
传递,而不是32位
浮点

最简单的方法可能是在
FSTS result
指令之前插入
add$-8,%esp
(或
add%esp,$-8
,具体取决于汇编程序版本中的操作数顺序),并将
FSTS result
指令更改为
FST(%esp)
FSTL(%esp)
,取决于你的汇编程序。(也可以是
FSTP(%esp)
FSTPL(%esp)
从浮点堆栈中弹出值,而不是将其留在那里。)然后删除
push$result

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

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

补充 以下代码使用汇编程序的第二选择(gcc-4.7.2)在上运行:


在GNU汇编程序中,
$
指定一个文本值(编码到指令中的值)。标签的值是其地址。因此,
$x
$format
$result
$text
是这些标签的地址;它们是包含要标记的值的地址
printf
不使用
%f
的地址。必须传递浮点数的值,而不是其地址。而且,正如Frank Kotler所指出的,您必须将其作为64位
双精度
传递,而不是32位
浮点

最简单的方法可能是在
FSTS result
指令之前插入
add$-8,%esp
(或
add%esp,$-8
,具体取决于汇编程序版本中的操作数顺序),并将
FSTS result
指令更改为
FST(%esp)
FSTL(%esp)
,取决于你的汇编程序。(也可以是
FSTP(%esp)
FSTPL(%esp)
从浮点堆栈中弹出值,而不是将其留在那里。)然后删除
push$result

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

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

补充 以下代码使用汇编程序的第二选择(gcc-4.7.2)在上运行:


我不熟悉您使用的特定汇编程序版本的语法,但是
push$result
result
的地址放入堆栈中,传递给
printf
。根据ABI,您可能需要将
result
的值放入堆栈或浮点寄存器中进行传递。(在后一种情况下,只需删除
FSTS result
push$result
指令就足够了。)另外,您知道
.ascii
指令是否会在字符串末尾放置空字符?如果没有,您可能需要
.asciz
,或者需要以另一种方式向字符串中添加空字节。(32位)
printf
,尽管我们说
%f
,但总是希望堆栈上有一个双精度参数。@Eric Postdischil,我想我推送一个值是因为我使用了$symbol,没有这个,我就推送地址。我在字符串中添加了空字符并删除了这些指令,但这并没有帮助@Frank Kotler,我尝试将
result
的声明从float更改为double,然后将其放入堆栈中,但仍然不起作用。我不熟悉您正在使用的特定汇编程序版本的语法,但是
push$result
result
的地址放入堆栈中传递给
printf
。根据ABI,您可能需要将
result
的值放入堆栈或浮点寄存器中进行传递。(在后一种情况下,只需删除
FSTS result
push$result
指令就足够了。)另外,您知道
.ascii
指令是否会在字符串末尾放置空字符?如果没有,您可能需要
.asciz
或需要
.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