代码之家  ›  专栏  ›  技术社区  ›  jtbandes

在内联汇编中使用双精度数字(GCC,IA-32)

  •  5
  • jtbandes  · 技术社区  · 16 年前

    我刚开始在我的计算机科学课上学习汇编,我有一个作业,用指定的舍入模式对浮点值进行舍入。我已经尝试使用 fstcw , fldcw ,及 frndint . 我修改舍入控制位,对数字进行舍入,然后恢复以前的控制位(分配的要求)。

    当前突出的问题是教学质量不高 fld %1 st(0) 浮点寄存器(例如,如果我调用值为2.6207的函数,则会将数字-1.9427(…)e-29加载到寄存器中)。这可能是由于使用不当造成的 gcc 是内联的 asm()

    double roundD (double n, RoundingMode roundingMode)
    {
        // control word storage (2 bytes for previous, 2 for current)
        char *cw = malloc(4*sizeof(char));
        char *cw2 = cw + 2;
    
        asm("fstcw %3;" // store control word in cw
            "mov %3,%4;" // copy control word into cw2
            "and $0xF3FF,%4;" // zero out rounding control bits
            "or %2,%4;" // put new mode into rounding control bits
            "fldcw %5;" // load the modified control word
            "fld %1;" // load n into st(0)
            "frndint;" // round n
            "fstp %0;" // load st(0) back into n
            "fldcw %3;" // load the old control word from cw
            : "=m" (n)
            : "m" (n), "m" (roundingMode),
              "m" (cw), "r" (cw2), "m" (cw2) // mov requires one argument in a register
            );
    
        free(cw);
    
        return n;
    }
    

    如果有人能指出代码的错误,特别是与 fld%1 线与线 asm

    3 回复  |  直到 13 年前
        1
  •  2
  •   tyranid    16 年前

    当前代码中至少有一个问题是它使用的是fld和fstp的单精度浮点版本。如果用fldl和fstpl替换它们,它可能会工作。

        2
  •  2
  •   C. K. Young    16 年前

    这是我得到的。它没有经过测试,但希望您能少用它。:-)

    double
    roundd(double n, short mode)
    {
        short cw, newcw;
    
        __asm__("fstcw %w0" : "=m" (cw));
        newcw = cw & 0xf3ff | mode;
        __asm__("fldcw %w0" : : "m" (newcw));
        __asm__("frndint" : "+t" (n));
        __asm__("fldcw %w0" : : "m" (cw));
        return n;
    }
    

    尽管如此,如果您不需要使用汇编来实现舍入模式,请考虑使用中的函数 <fenv.h> 取而代之的是:-)

        3
  •  0
  •   Thorsten S.    16 年前

    从0,1,2开始。。。但是如果访问两个字节,地址必须是0,2,4。。。。万一 地址的两倍数必须是8:0,8,16的偶数

    因此,请检查用于加载值的地址是否可除以8。Assembly具有align关键字以确保数据正确对齐。

    推荐文章