C 内核为浮点数疯狂

C kernel is going crazy with floating point numbers

所以我正在编写一个 C 内核(运行 处于保护模式)并且我正在研究浮点数。首先,我编写了这个 C 程序以确保没有任何错误(运行s 在我的物理机器上,而不是内核的一部分)使用 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 因此它没有按预期工作:



通过查看内核的反汇编,我没有发现任何非常可疑的东西:

 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 数字,所以我知道这个问题的答案对你们来说似乎很明显(我希望。)

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);
}