程序集 - 将 float 舍入到 -∞ 的 0.001 精度

标签 assembly x86 masm irvine32

我正在尝试将所有浮点数写入到 -∞ 的 .001 精度。我已将 RC 字段设置为 01 二进制,但我只能打印出具有所需精度的初始浮点数,此后它忽略舍入。我想我可能在如何处理 -∞ 精度方面遗漏了一些明显的东西,但我不确定。

INCLUDE Irvine32.inc

.data

ctrlWord  WORD  010000000000b ; set the RC field to round down toward -∞.

.code

     fild   sum                         ; load integer into ST(0)
     fidiv  count                       ; divide ST(0) by mem int
     fstcw  ctrlWord                    ; store control word
     fldcw  ctrlWord                    ; load control word
     call   WriteFloat                  ; +2.5000000E+000

     fild   stdDev                      ; load variance integer into ST(0)
     fidiv  count                       ; average the result 
     fsqrt                  ; ST(0) = square root
     call   WriteFloat                  ; +2.5495097E+000

最佳答案

FPU 的舍入模式仅适用于最后一个 二进制 浮点尾数的位数。它不能用于 十进制四舍五入。该舍入规则有一个异常(exception):FRNDINT .该指令“根据当前舍入模式(FPU 控制字的 RC 字段的设置)将 ST(0) 寄存器中的源值舍入到最接近的整数值,并将结果存储在 ST(0) 中。” ( Intel Manual )。

对于小数舍入,您可以使用 FRNDINT有一个技巧:首先计算 n * 10^x (x 是小数部分所需的小数精度)。然后使用 FRNDINT它舍入整数部分并截断小数部分。最后,您可以将数字除以 10^x,也可以将数字转换为字符串并适当插入小数点。

看看这个例子(这是你的代码,只是稍微修改了一下):

INCLUDE Irvine32.inc

.data

newCtrlWord  WORD 010000000000b ; set the RC field to round down toward -∞.
oldCtrlWord  WORD ?
sum WORD 25
count WORD 10
stdDev WORD 65
thousand WORD 1000

.code
main:

    fstcw oldCtrlWord               ; store control word
    mov ax, oldCtrlWord
    and ah, 11110011b               ; clear _only_ RC field
    or  ah, 00000100b               ; set _only_ RC field (rounding to -∞)
    mov newCtrlWord, ax
    fldcw newCtrlWord               ; load control word

    fild   sum                      ; load integer into ST(0)
    fidiv  count                    ; divide ST(0) by mem int
    fimul thousand                  ; thousand=10^3 - preserve three decimal digits of the fractional part
    frndint                         ; only for this you need the control word
    fidiv thousand                  ; adjust integer to a correct rational number (reverse the `fimul thousand`)
    call WriteFloat                 ; +2.5000000E+000
    call CRLF

    fild stdDev                     ; load variance integer into ST(0)
    fidiv count                     ; average the result
    fsqrt                           ; +2.5495097E+000
    fimul thousand                  ; thousand=10^3 - preserve three decimal digits of the fractional part
    frndint                         ; only for this you need the control word
    fidiv thousand                  ; adjust integer to a correct rational number (reverse the `fimul thousand`)
    call WriteFloat                 ; +2.5490000E+000
    call CRLF

    fldcw  oldCtrlWord              ; restore control word

    exit

END main

关于程序集 - 将 float 舍入到 -∞ 的 0.001 精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23358537/

相关文章:

assembly - x86 中没有段的直接寻址?

c++ - IRQ 处理程序三重故障

assembly - 字大小的 OUT 到字节 IO 寄存器?使用旧 VGA 代码中的指令设置序列 Controller 寄存器

c - 无法在 Windows 操作系统上的 Eclipse 中交叉编译 C

assembly - 在 MASM 的宏中使用本地标签的问题

assembly - SYSRET 与 SYSRETQ 区别及兼容模式

c - 调用系统调用的不同方式

assembly - 处理两个分支结果的管道处理器设计

c - 将 C 代码翻译成汇编

assembly - MASM shellcode 和 NASM shellcode 之间有区别吗