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);
}
所以我正在编写一个 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);
}