打印转置矩阵时触发内存访问错误的排查求助
矩阵转置汇编函数引发内存访问错误的问题
我在打印转置后的矩阵第一行时出现了内存访问不可用的错误,麻烦帮忙排查问题出在哪里——是C++代码的问题,还是汇编函数的问题?
调用汇编函数的C++代码
#include <iostream> #include <windows.h> extern "C" void transpose(INT64**, INT64); // 打印矩阵的函数 void printMatrix(INT64** matrix, INT64 n) { for (INT64 i = 0; i < n; ++i) { for (INT64 j = 0; j < n; ++j) { std::cout << matrix[i][j] << " "; } std::cout << std::endl; } } int main() { INT64 n = 8; // 矩阵大小 // 初始化矩阵A INT64** A = new INT64 * [n]; for (INT64 i = 0; i < n; ++i) { A[i] = new INT64[n]; for (INT64 j = 0; j < n; ++j) { A[i][j] = i * n + j; // 填充矩阵A } } std::cout << "转置前的矩阵:" << std::endl; printMatrix(A, n); // 打印转置前的矩阵 // 调用转置函数 transpose(A, n); std::cout << "转置后的矩阵:" << std::endl; printMatrix(A, n); // 打印转置后的矩阵 // 释放内存 for (INT64 i = 0; i < n; ++i) { delete[] A[i]; } delete[] A; return 0; }
汇编实现的transpose函数
; TransposeSquareMatrix(A, n) mov rdi, rcx mov rsi, rdx mov rbx, rdi ; Address A is in RDI mov rcx, rsi ; Dimension n is in RSI imul r8, rsi, 8 ; Step between rows dec rcx jz .c ; It's a (1 x 1) matrix .a: push rcx ; (1) mov rsi, rbx ; Column address mov rdi, rbx ; Row address .b: add rsi, 8 ; To next element in this row add rdi, r8 ; To next element in this column mov rax, [rsi] ; Swap 2 elements mov rdx, [rdi] mov [rdi], rax mov [rsi], rdx dec rcx jnz .b lea rbx, [rbx + r8 + 8] ; To next element on main diagonal pop rcx ; (1) dec rcx jnz .a ; Continu until (1 x 1) matrix .c: ret
问题根源分析
核心问题是汇编代码的内存模型和C++创建的矩阵不匹配:
- C++里你创建的是
INT64**类型的指针数组式矩阵,每一行的内存是独立分配的(new INT64[n]),行与行之间的物理内存不一定连续,甚至可能完全分散。 - 但你的汇编代码默认矩阵是连续的一维内存块(比如栈上直接分配的
INT64 A[8][8]),用imul r8, rsi, 8计算行间距,然后用add rdi, r8跳转下一行——这会直接访问到错误的内存地址,触发内存访问越界错误。
另外,你的汇编循环逻辑也有问题:循环计数的递减逻辑会导致交换次数超出矩阵的上三角范围,不过这是次要问题,先解决内存模型不匹配的问题才能正常运行。
修正思路
要处理INT64**类型的矩阵,汇编里必须先通过指针数组拿到每行的实际地址:
- 从传入的矩阵指针
rdi中,取出第i行的地址:mov r10, [rdi + i*8](因为每个行指针是8字节)。 - 再从该行地址中取出第j列的元素:
mov rax, [r10 + j*8]。 - 转置时需要交换
A[i][j]和A[j][i],所以要分别拿到这两个元素的实际内存地址,再执行交换操作。
内容的提问来源于stack exchange,提问作者szyjas
相关产品推荐
相关产品推荐

