c - 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
每次都给我,因此它不能按预期工作:
通过查看内核的反汇编,我没有发现任何非常可疑的东西:
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);
}
推荐阅读
- php - 在中间件中添加的日志头
- vue.js - 如何渲染节点混合功能组件和 html 字符串?
- android - 按下 POWER_KEY 时不调用“onSurfaceTextureUpdated”方法
- css - 重复多个 css 动画
- sql-server - 如果网页上的类型不同,在哪里转换数据库的输入类型
- c# - 如何摆脱epc中的归档0?
- user-interface - WUI 是 GUI 的子集吗?
- python - 如何在 Python 刮板中将名字和姓氏与电子邮件匹配
- c# - 无法使用多个一对一关系执行从一个表到另一个表的删除操作?
- php - Symfony / API 平台 - 自定义操作 - 使用 VichUploaderBundle 替换文件的 PUT 方法