更改FPU舍入模式

时间:2014-04-30 15:23:38

标签: linux assembly x86 att fpu

我想知道,我应该使用什么值来改变FPU舍入模式。

.data
nearest:
    ??
down:
    ??
up:
    ??
zero:
    ??
.text
.global round
    pushl   %ebp
    movl    %esp, %ebp
    movl 8(%ebp), %ecx

    cmpl $1, %ecx
je
    fldcw nearest

    cmpl $2, %ecx
je
    fldcw down

    cmpl $3, %ecx
je
    fldcw up

    cmpl $4, %ecx
je
    fldcw zero
leave
ret

我发现了这样的事情:

down:
    .byte 0x7f, 0x07
up:
    .byte 0x7f, 0x0b

但我不知道为什么有人用它。我知道我应该更改8位和9位,如下所示: 00 - 到最近的一周 01 - 向下舍入(向负无穷大) 10 - 向上舍入(向正无穷大) 11 - 向零舍去

1 个答案:

答案 0 :(得分:2)

舍入的类型由FPU的控制字中的两位确定。您可以在此处获取有关FPU的信息:http://www.website.masmforum.com/tutorials/fptute/fpuchap1.htm。仅更改这两位并保持其他位不变是有点棘手的。看看我的例子。我试图尽可能接近你的代码:

.data
    num:        .double 6.5     # play with the number!

    old:        .word 0
    nearest:    .word 0x0000
    down:       .word 0x0400
    up:         .word 0x0800
    zero:       .word 0x0C00
    result:     .double 0
    fmt1:       .asciz "nearest: %f -> %f\n"
    fmt2:       .asciz "down:    %f -> %f\n"
    fmt3:       .asciz "up:      %f -> %f\n"
    fmt4:       .asciz "zero:    %f -> %f\n"

.text
.globl main
main:

    fstcw old               # store old control word

    movw old, %ax
    andb $0b11110011, %ah   # clear RC field
    orw %ax, nearest
    orw %ax, down
    orw %ax, up
    orw %ax, zero

    fldcw nearest           # banker's rounding
    call round
    mov $fmt1, %esi
    call out

    fldcw down              # down toward -infinity
    call round
    mov $fmt2, %esi
    call out

    fldcw up                # up toward +infinity
    call round
    mov $fmt3, %esi
    call out

    fldcw zero              # truncating
    call round
    mov $fmt4, %esi
    call out

    fldcw old               # restore old control word

    xor %eax, %eax          # exit(0)
    ret                     # GCC only needs RET

round:
    fldl num
    frndint
    fstpl result
    ret

out:
    push result+4
    push result
    push num+4
    push num
    push %esi
    call printf             # "%f" needs a double
    add $20, %esp
    ret