首页 > 解决方案 > C 内核因浮点数而疯狂

问题描述

所以我正在编写一个 C 内核(在保护模式下运行)并且我正在涉足浮点数。首先,我编写了这个 C 程序,以确保不会出现任何问题(在我的物理机器上运行,而不是作为内核的一部分),它使用循环每次for递增一个float值并显示按预期工作的结果:1.0f

#include <stdio.h>

int main() {
    float numba;
    for(int i = 0; i < 100; i++) {
        numba = numba + 1.0f;
        printf("%d\n", (unsigned int)numba);
    }
}

1
2
3
4
...
99
100

考虑到我不能printf在我的内核中使用,我不得不以其他方式实现它:P。使用像素绘图例程:

void putPixel(MODEINFOBLOCK mib, unsigned int x, unsigned int y, unsigned int color);

...我可以做出完美的对角线。如何?通过增加for循环的计数器 和 numba,我可以将它们用作例程的 X 和 Y 坐标:

float numba;
for(int i = 0; i < 100; i++) {
    numba = numba + 1.0f;
    putPixel(mib, i, (unsigned int)numba, 0xFFFFFF);
}

但是,当我运行内核时,我得到了这个:

现实

显然它numba = 0每次都给我,因此它不能按预期工作: 通过查看内核的反汇编,我没有发现任何非常可疑的东西:

期望(请不要问我这个截图是怎么拍的:PP)

 1ef:   83 c4 10                add    esp,0x10
 1f2:   bb 00 00 00 00          mov    ebx,0x0
 1f7:   d9 44 24 08             fld    DWORD PTR [esp+0x8]
 1fb:   d8 05 f4 10 10 00       fadd   DWORD PTR ds:0x1010f4
 201:   d9 54 24 08             fst    DWORD PTR [esp+0x8]
 205:   83 ec 0c                sub    esp,0xc
 208:   68 ff ff ff 00          push   0xffffff
 20d:   d9 7c 24 1e             fnstcw WORD PTR [esp+0x1e]
 211:   0f b7 44 24 1e          movzx  eax,WORD PTR [esp+0x1e]
 216:   80 cc 0c                or     ah,0xc
 219:   66 89 44 24 1c          mov    WORD PTR [esp+0x1c],ax
 21e:   d9 6c 24 1c             fldcw  WORD PTR [esp+0x1c]
 222:   df 7c 24 10             fistp  QWORD PTR [esp+0x10]
 226:   d9 6c 24 1e             fldcw  WORD PTR [esp+0x1e]
 22a:   ff 74 24 10             push   DWORD PTR [esp+0x10]
 22e:   53                      push   ebx
 22f:   81 ec 18 01 00 00       sub    esp,0x118
 235:   be 40 1c 10 00          mov    esi,0x101c40
 23a:   b9 46 00 00 00          mov    ecx,0x46
 23f:   89 e7                   mov    edi,esp
 241:   f3 a5                   rep movs DWORD PTR es:[edi],DWORD PTR ds:[esi]
 243:   e8 2c 01 00 00          call   0x374
 248:   83 c3 01                add    ebx,0x1
 24b:   81 c4 30 01 00 00       add    esp,0x130
 251:   83 fb 64                cmp    ebx,0x64
 254:   75 a1                   jne    0x1f7
 256:   e8 0c 00 00 00          call   0x267
 25b:   e8 0d 00 00 00          call   0x26d
 260:   83 c4 10                add    esp,0x10
 263:   5b                      pop    ebx
 264:   5e                      pop    esi
 265:   5f                      pop    edi

如您所见,内核正在使用 FPU 指令。但是,由于某种原因,该程序没有。

问题是……为什么会发生这种情况?保护模式下的 FPU 有什么问题吗?

注意:这实际上是我第一次处理 FP 号码,所以我知道这个问题的答案对你们来说似乎很明显(我希望。)

标签: cx86floating-pointprotected-mode

解决方案


numba未初始化。

// float numba;
float numba = 0.0f;

for(int i = 0; i < 100; i++) {
    numba = numba + 1.0f;
    putPixel(mib, i, (unsigned int)numba, 0xFFFFFF);
}

推荐阅读