我想知道,我应该使用什么值来改变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 - 向零舍去
答案 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