打印FPU寄存器值

时间:2017-05-21 02:45:00

标签: assembly floating-point fpu

我想以某种方式从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

1 个答案:

答案 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
相关问题