You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键修正点说明

  1. 寄存器合理分配:用独立的寄存器管理不同的变量(数组基地址、索引、计数器),避免寄存器重用导致的值覆盖,同时把计数器先存在寄存器里,最后再写回C变量,彻底解决内存寻址的问题。
  2. 逻辑流程修复:
    • 取出元素后先判断是否为0,符合条件立即退出循环。
    • 通过分支判断,把元素存入对应的数组,不会重复存储。
    • 先赋值到数组的当前索引,再递增计数器,确保数组从索引0开始存储有效元素。
  3. 输出优化:原数组的输出循环改为判断x[i] !=0,不用硬编码次数;vmic和vmare的输出用i < k1/i <k2,避免多输出空元素。
  4. 数组初始化:给vmic和vmare初始化全0,防止输出时出现垃圾值。

内容的提问来源于stack exchange,提问作者Alina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:40:51