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

C与汇编混合编程生成矩阵时对角线赋值错误问题排查

问题排查与修正方案

核心问题分析

  • 内存结构不匹配:你在C代码中分配的是分散的二维指针数组(每行单独通过malloc分配,内存地址不连续),但fillMatrix函数声明和汇编代码都将其当作连续的一维数组处理,直接导致指针访问逻辑完全错误。
  • 打印逻辑错误:最后打印矩阵时使用matrix[i * n + j],这是连续一维数组的访问方式,不适用于二维指针数组,正确写法应为matrix[i][j]。
  • 汇编寻址错误:汇编中直接操作r9(int**类型)时,用r10*8偏移是访问指针数组的元素(x64下指针占8字节),而非矩阵的int元素(占4字节);同时副对角线的索引计算逻辑完全错误。

修正方案

方案1:改为连续内存的一维数组(推荐,适配汇编高效处理)

将矩阵改为连续分配的一维数组,简化汇编寻址逻辑,避免二维指针的复杂操作。

修正后的C代码

#include <stdio.h>
#include <stdlib.h>

extern void fillMatrix(int n, int* matrix);

int main() {
    SetConsoleOutputCP(1251);
    int n;

    printf("Введите размерность матрицы: ");
#pragma warning(suppress : 4996)
    scanf("%d", &n);

    // 分配连续的一维数组模拟二维矩阵
    int* matrix = (int*)malloc(n * n * sizeof(int));
    if (matrix == NULL) {
        printf("Ошибка выделения памяти.\n");
        return 1;
    }

    printf("Сгенерированная матрица до вызова функции на ассемблере:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i * n + j] = rand() % 100;
            printf("%d ", matrix[i * n + j]);
        }
        printf("\n");
    }

    fillMatrix(n, matrix);
    printf("Сгенерированная матрица:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", matrix[i * n + j]);
        }
        printf("\n");
    }

    free(matrix);
    return 0;
}

修正后的汇编代码

.CODE
fillMatrix PROC
    ; rcx = n, rdx = 连续一维数组的起始指针
    mov     r8, rcx         ; 保存矩阵尺寸n到r8
    mov     r9, rdx         ; 保存矩阵起始地址到r9
    xor     r10, r10        ; 初始化循环索引i为0

fill_loop:
    cmp     r10, r8         
    jge     end_fill        ; 当i >=n时退出循环

    ; 处理主对角线:matrix[i*n + i] = 1
    mov     rax, r10
    imul    rax, r8         ; rax = i * n
    add     rax, r10        ; rax = i*n + i
    mov     dword ptr [r9 + rax*4], 1 ; int占4字节,偏移量*4

    ; 处理副对角线:matrix[i*n + (n-1 -i)] = 1
    mov     rax, r10
    imul    rax, r8         ; rax = i * n
    mov     r11, r8
    dec     r11             ; r11 = n-1
    sub     r11, r10        ; r11 = n-1 -i
    add     rax, r11        ; rax = i*n + (n-1 -i)
    mov     dword ptr [r9 + rax*4], 1

    inc     r10            
    jmp     fill_loop       

end_fill:
    ret
fillMatrix ENDP
END

方案2:保留二维指针数组(适配原内存结构)

若需保留原二维指针数组的内存分配方式,需修改汇编代码,先获取每行的指针再访问对应元素。

修正后的C代码

#include <stdio.h>
#include <stdlib.h>

extern void fillMatrix(int n, int** matrix);

int main() {
    SetConsoleOutputCP(1251);
    int n;

    printf("Введите размерность матрицы: ");
#pragma warning(suppress : 4996)
    scanf("%d", &n);

    int** matrix = (int**)malloc(n * sizeof(int*));
    if (matrix == NULL) {
        printf("Ошибка выделения памяти.\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
        if (matrix[i] == NULL) {
            printf("Ошибка выделения памяти.\n");
            return 1;
        }
    }

    printf("Сгенерированная матрица до вызова функции на ассемблере:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i][j] = rand() % 100;
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }

    fillMatrix(n, matrix);
    printf("Сгенерированная матрица:\n");
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d ", matrix[i][j]); // 修正为二维指针的正确访问方式
        }
        printf("\n");
    }

    // 释放内存
    for (int i = 0; i < n; i++) {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

修正后的汇编代码

.CODE
fillMatrix PROC
    ; rcx = n, rdx = 二维指针数组的起始地址(int**)
    mov     r8, rcx         ; 保存矩阵尺寸n到r8
    mov     r9, rdx         ; 保存指针数组地址到r9
    xor     r10, r10        ; 初始化循环索引i为0

fill_loop:
    cmp     r10, r8
    jge     end_fill

    ; 处理主对角线:matrix[i][i] = 1
    mov     rax, [r9 + r10*8] ; 获取第i行的指针(x64下指针占8字节)
    mov     dword ptr [rax + r10*4], 1 ; 访问第i行的第i个int元素(int占4字节)

    ; 处理副对角线:matrix[i][n-1 -i] = 1
    mov     r11, r8
    dec     r11             ; r11 = n-1
    sub     r11, r10        ; r11 = n-1 -i
    mov     dword ptr [rax + r11*4], 1 ; 访问第i行的对应副对角线元素

    inc     r10
    jmp     fill_loop

end_fill:
    ret
fillMatrix ENDP
END

关键错误总结

  1. 内存结构不匹配:二维指针数组与连续一维数组的寻址逻辑完全不同,不能混用。
  2. 数据宽度混淆:x64架构下指针占8字节,int占4字节,汇编偏移计算需对应正确类型的宽度。
  3. 副对角线索引错误:原代码未正确计算副对角线的列索引,正确公式为n-1 -i。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:29:53