gcc - 在内联汇编中使用 double 字 (GCC, IA-32)

标签 gcc assembly x86

我刚开始在我的计算机科学课上学习汇编,我有一项作业,使用指定的舍入模式对浮点值进行舍入。我尝试使用 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输入/输出。 (当然,如果你能发现其他问题,也可以随时告诉我。)我不希望任何人为我做功课,只要指出正确的方向。谢谢!

最佳答案

这就是我所拥有的。它没有经过测试,但希望您使用它时不会那么粗糙。 :-)

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> 中的函数。反而。 :-)

关于gcc - 在内联汇编中使用 double 字 (GCC, IA-32),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2249917/

相关文章:

c - 为什么 gcc 在读取时保留被调用者保存寄存器?

c++ - gcc: undefined reference 错误

c - -fstack-usage 对于叶函数是否错误?

debugging - 如果图像在只读内存中,调试器如何设置断点?

assembly - 使用 JMP 代替 CALLS

c - 汇编 x86 中的 Math.h 库函数?

assembly - 跳转到 64 位长模式时出现三重故障

c++ - 如何使特征接受参数包?

linux - readelf如何翻译入口点

assembly - NASM - 如何将 8 位寄存器移动到完整的 32 位寄存器?