Visual Studio中C内嵌浮点累加器汇编代码抛异常求助
问题分析与修正方案
触发0xC0000005访问违例的核心原因是混淆了FPU浮点栈和x86通用整数栈,手动修改ESP破坏了函数调用的栈平衡,导致后续printf调用时栈帧错乱。
具体错误点
- 错误操作通用栈:
FLD/FSTP操作的是FPU专用浮点栈,和ESP管理的通用整数栈完全无关。你代码里的add ESP,4是完全错误的,直接破坏了栈结构,导致printf调用时无法正确访问栈上的参数或返回地址,触发访问违例。 - FPU栈操作冗余:原代码中
FLD [ESI]→FLD sum→FADD→FSTP sum之后,FPU栈已经被清空,不需要任何额外的栈清理操作。
修正后的代码
以下是修复后的完整代码,同时做了小幅度优化:
#include <time.h> #include <stdio.h> #include <stdlib.h> #include <math.h> #define NUM_OF_POINTS 1000000 int main(void) { float* vector = (float*)malloc(NUM_OF_POINTS * sizeof(float)); for (int i = 0; i < NUM_OF_POINTS; i++) vector[i] = 10000; float sum = 0; int i = 0, k = NUM_OF_POINTS * 4; _asm { mov ESI, vector; // 把数组基址存入ESI,循环内无需重复加载 looop: mov EAX, k; cmp i, EAX; je end; FLD sum; // 将累加器sum加载到FPU栈顶 FADD DWORD PTR [ESI + i]; // 栈顶sum与当前数组元素相加,结果留在栈顶 FSTP sum; // 将结果弹出到sum,清空FPU栈 add i, 4; // 偏移量+4,指向下一个float元素 jmp looop; end: } printf("here you go: %f", sum); free(vector); // 别忘了释放内存,避免泄漏 return 0; }
额外优化建议
- 可以把
k的值预先存入寄存器(比如EBX),避免每次循环都执行mov EAX, k,减少指令开销。 - 如果是x86-64环境,也可以考虑使用SSE/AVX指令实现浮点累加,效率会比传统FPU指令更高,但作为学校项目,先保证正确性即可。
内容的提问来源于stack exchange,提问作者Emiliano
相关产品推荐
相关产品推荐

