我想以某种方式从FPU寄存器获取值并打印它。我有这个代码:
#include <stdio.h>
void change();
void single_precision();
int main()
{
float a = 3.14;
printf("%f", a);
}
gcc -S
生成此内容:
.file "zad4.c"
.section .rodata
.LC1:
.string "%f"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $20, %esp
flds .LC0
fstps -12(%ebp)
flds -12(%ebp)
subl $4, %esp
leal -8(%esp), %esp
fstpl (%esp)
pushl $.LC1
call printf
addl $16, %esp
movl $0, %eax
movl -4(%ebp), %ecx
leave
leal -4(%ecx), %esp
ret
.size main, .-main
.section .rodata
.align 4
.LC0:
.long 1078523331
.ident "GCC: (GNU) 6.3.1 20170306"
.section .note.GNU-stack,"",@progbits
除了main开头的一些混乱之外,它基本上加载了值(这个.long
,它可以硬编码为.float 3.14
,无论如何)到FPU寄存器。然后它将该值转换为-12(%ebp)
,再次加载它。但我不知道接下来会发生什么
为什么leal -8(%esp), %esp
?然后它再次将值从FPU寄存器弹出到(%esp)
,这样就是-8(%esp)
的地址。然后它打印。
现在,如果我希望看到这个数字的每一点,使用例如bt
指令,那么我应该在哪里存储它?我想我不能movl
它,因为它的80位长
Generated with `-O3`:
.file "XD.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC1:
.string "%f"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $8, %esp
pushl $1074339512
pushl $1610612736
pushl $.LC1
call printf
movl -4(%ebp), %ecx
addl $16, %esp
xorl %eax, %eax
leave
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 6.3.1 20170306"
.section .note.GNU-stack,"",@progbits
答案 0 :(得分:0)
以下示例使用st0
打印printf
中的值,我希望这是您所需要的:
.data
.fmtstr:
.string "%f\n"
.text
# print floating point value in st0
print_float:
sub $8,%esp # make space on the stack
fstp (%esp) # store the value we want to print
push $fmtstr # push formatting string
call printf
add $12,%esp # pop arguments back off
ret
请注意,我们需要使用fstp
,因为C调用约定要求函数调用时8087堆栈为空。
您还可以使用%Lf
格式说明符打印整个80位的浮点数:
.data
.fmtstr:
.string "%Lf\n"
.text
# print floating point value in st0
print_float:
sub $12,%esp # make space on the stack
fstpt (%esp) # store the value we want to print
push $fmtstr # push formatting string
call printf
add $16,%esp # pop arguments back off
ret
请注意,我们为12个字节而不是10个空间。这是因为需要2个字节的填充来将10个字节的参数与12个字节对齐。
如果你想看到浮点数的字节,你可以假装你推的10个字节实际上是两个整数和一个短的:
.data
.fmtstr:
.string "%02x%04x%04x\n"
.text
# print st0 in hex
print_float:
pushw $0 # pad with explicit zeros
sub $10,%esp # make space for the number
fstpt (%esp) # store the value we want to print
push $fmtstr # push formatting string
call printf
add $16,%esp # pop arguments back off
ret