x86汇编错误:写入位置0x0081D45C时出现访问违例求助
解决汇编代码中的访问违规错误及逻辑问题
嘿,我来帮你搞定这个问题!你的代码触发访问违规主要是因为汇编内存寻址的错误,同时还有逻辑流程的问题,我一步步给你拆解:
问题根源分析
1. 非法的内存寻址(直接导致访问违规)
在x86汇编的寻址规则里,[基址 + 比例*变址]这种格式里的变址必须是寄存器,不能是内存变量。你的代码里直接用[ecx + 4 * k1],而k1是C语言的局部变量(存在内存里),这种写法是不合法的,会导致CPU无法正确计算内存地址,直接触发访问违规。
2. 逻辑流程完全错误
- 不管元素是>=10还是小于10,你的代码都会执行
mai_mare_egal段的代码,结果就是所有元素被同时塞进vmic和vmare数组,完全不符合你“分开放置”的需求。 - 你先递增计数器
k1/k2再赋值,导致数组的第一个有效元素从索引1开始,索引0的位置是空的,输出时还会多打印一个未初始化的垃圾值。
修正后的完整代码
我重新调整了汇编部分的寄存器分配,修复了逻辑错误,同时优化了输出逻辑:
#include <iostream> #include <cstdio> using namespace std; int main() { // 将x中>=10的元素放入vmic,其余放入vmare,遇到0停止 int x[] = { 1,2,3,4,5,14,22,0 }; int vmic[10] = {0}; // 初始化避免未初始化值干扰 int vmare[10] = {0}; int n = 10; int k1 = 0; // vmic的元素个数 int k2 = 0; // vmare的元素个数 _asm { mov ebp, 0; // ebp作为x数组的索引,从0开始 lea ebx, x; // ebx存储x数组的基地址 lea esi, vmic; // esi存储vmic数组的基地址 lea edi, vmare; // edi存储vmare数组的基地址 mov ecx, n; // ecx存储阈值10 mov eax, 0; // eax作为vmic的当前索引(k1的寄存器版) mov edx, 0; // edx作为vmare的当前索引(k2的寄存器版) bucla: mov r8d, [ebx + 4 * ebp] // 取出x[ebp]的值到r8d(32位环境可替换为mov ecx, [ebx+4*ebp],注意调整寄存器) cmp r8d, 0; // 遇到0就退出循环 je afara; cmp r8d, ecx; // 比较当前元素和阈值10 jge store_to_vmic; // >=10则跳去存vmic // 处理<10的元素:存入vmare mov [edi + 4 * edx], r8d; inc edx; // vmare索引+1 jmp next_iter; store_to_vmic: // 处理>=10的元素:存入vmic mov [esi + 4 * eax], r8d; inc eax; // vmic索引+1 next_iter: inc ebp; // x数组索引+1 jmp bucla; afara: // 将寄存器中的计数器值写回C变量 mov k1, eax; mov k2, edx; } // 输出原数组 printf("原数组x:"); int i; for (i = 0; x[i] != 0; i++) { printf(" %d", x[i]); } printf("\n"); // 输出vmic数组 printf("vmic数组(>=10的元素):"); for (i = 0; i < k1; i++) { printf(" %d", vmic[i]); } printf("\n"); // 输出vmare数组 printf("vmare数组(<10的元素):"); for (i = 0; i < k2; i++) { printf(" %d", vmare[i]); } printf("\n"); return 0; }
关键修正点说明
- 寄存器合理分配:用独立的寄存器管理不同的变量(数组基地址、索引、计数器),避免寄存器重用导致的值覆盖,同时把计数器先存在寄存器里,最后再写回C变量,彻底解决内存寻址的问题。
- 逻辑流程修复:
- 取出元素后先判断是否为0,符合条件立即退出循环。
- 通过分支判断,把元素存入对应的数组,不会重复存储。
- 先赋值到数组的当前索引,再递增计数器,确保数组从索引0开始存储有效元素。
- 输出优化:原数组的输出循环改为判断
x[i] !=0,不用硬编码次数;vmic和vmare的输出用i < k1/i <k2,避免多输出空元素。 - 数组初始化:给vmic和vmare初始化全0,防止输出时出现垃圾值。
内容的提问来源于stack exchange,提问作者Alina
相关产品推荐
相关产品推荐

