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

如何在C++内联汇编中实现数组负数求和?代码总返回0求排查

代码问题排查

你的代码始终返回0的核心原因及其他逻辑错误如下:

  • 最致命错误:你cmp ebx, 0比较的是数组的内存地址而非数组元素的值,用户态进程的数组地址永远是正数,所以永远触发jge bigger_case分支,总和自然一直是0。
  • 地址计算逻辑完全混乱:你在列循环中反复修改基址寄存器ebx,同时偏移esi的增量时机错误,导致访问的内存地址完全不是预期的数组元素位置。
  • 分支跳转逻辑漏洞:负数分支读取元素时先偏移了esi,读取的是下一个元素的值,累加逻辑完全错误。
  • 寄存器保护缺失:Windows下内联汇编中ebx属于被调用者保存寄存器,直接修改会破坏上层调用的上下文,需要先入栈保存,使用完后恢复。
  • 行偏移计算逻辑不可靠:原代码行跳转逻辑依赖esi的最终值,属于巧合可用的不稳定写法,应该直接按行字节大小计算跳转偏移。
  • 注意:该语法仅支持32位MSVC编译器,64位MSVC已废弃内联汇编功能,需要单独编写汇编源文件实现。

修复后可运行代码

#include <iostream>
using namespace std;

void func(const int* arr, size_t arr_rows, size_t arr_cols, int* result)
{
    int sum = 0;
    _asm
    {
        push ebx // 保存ebx寄存器,遵守调用约定
        mov ebx, [arr] // 保存数组基址,后续不再随意修改
        mov edx, 0 // 存储负数总和
        mov ecx, [arr_rows] // 初始化行循环计数器

    row_loop:
        push ecx // 暂存行循环计数器
        xor esi, esi // 列索引从0开始
        mov ecx, [arr_cols] // 初始化列循环计数器

    col_loop:
        // 读取当前元素:基址 + 列索引*4(int占4字节)
        mov eax, dword ptr [ebx + esi*4]
        cmp eax, 0 // 比较元素值而非地址
        jge next_col // 非负数直接跳过累加

        add edx, eax // 负数累加到总和

    next_col:
        inc esi // 列索引+1
        loop col_loop // 列循环跳转

        // 跳转至下一行起始地址
        mov eax, [arr_cols]
        lea ebx, [ebx + eax*4]
        pop ecx // 恢复行循环计数器
        loop row_loop // 行循环跳转

        mov [sum], edx // 保存最终总和
        pop ebx // 恢复ebx寄存器
    }
    cout << sum << " is answer" << endl;
    *result = sum; // 给输出参数赋值
}

// 测试用例
int main()
{
    int arr[2][3] = {{-1, 2, -3}, {4, -5, 6}};
    int res;
    func((const int*)arr, 2, 3, &res);
    // 预期输出:-9 is answer
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:36:03