我有两个矩阵nxn,A和B.
A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
B = [1 1 1 1; 1 1 1 1; 1 1 1 1; 1 1 1 1]
两个矩阵在C中以float *分配。 从main.c开始,我在程序集中调用一个过程&export;出口(A,B,n);'
在汇编中,
...
mov eax,[ebp+a]
mov ebx,[ebp+b]
mov [xa],eax
mov [xb],ebx
printps [xa],1
printps [xb],1
movaps xmm0,[xa]
movaps [xb],xmm0 ;casuses segmentation fault
...
printps是一个宏,它只用于打印xa和xb的一个位置内存(它们是dword)。 我想用xa和xb作为矩阵的指针。
输出:
[1,2,3,4]
[1,1,1,1]
SEGMENTATION FAULT
为什么最后一条指令导致分段错误?问题出在哪儿? 如果我在最后一条指令中用[xa]替换[xb](仅用于测试),我没有任何错误。
- EDIT ---
如果我修改[xb],修改也不应该影响B?
然而,稍加修改:(实际上xa和xb是resd并且以32字节对齐。)
movaps xmm0,[xa+16]
movaps [xb],xmm0
printps [xb],1
分段故障......
---编辑----
这是代码的一个小例子:
int main(){
int m=4;
int n=4;
float* A=malloc(sizeof(float)*m*n);
float* B=malloc(sizeof(float)*m*n);
for(int i=0;i<m*n;i++){
A[i]=i;
B[i]=1;
}
printMatrix(A,m,n);
printMatrix(B,m,n);
exportRow(A,B,n); //procedure assembly
printMatrix(B,m,n);
}
汇编代码:
section .data
A equ 8
B equ 12
n equ 16
section .bss
alignb 32
xa resd 1
alignb 32
xb resd 1
section .text
global exportRow
exportRow: push ebp
mov ebp,esp
push ebx
push esi
push edi
mov eax,[ebp+a]
mov ebx,[ebp+b]
mov [xa],eax
mov [xb],ebx
printps [xb],1
printps [xa+16],1
movaps xmm0,[xa+16]
movaps [xb],xmm0
printps [xb],1
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
输出:
A=[1 2 3 4 ; 5 6 7 8 ; 9 10 11 12 ; 13 14 15 16]
B=[1 1 1 1 ; 1 1 1 1 ; 1 1 1 1 ; 1 1 1 1 ]
[1,1,1,1]
SEGMENTATION FAULT
case alignb 32: 如果我得到[xa + 16],我就会出现分段错误。
case alignb 16: 如果我得到[xa + 16],我有[1 1 1 1],为什么?我以为结果是[5 6 7 8]。
另一个问题(我认为两个问题是相关的): 使用帖子顶部的代码:
mov eax,[ebp+a]
mov ebx,[ebp+b]
mov [xa],eax
mov [xb],ebx
printps [xa],1
printps [xb],1
movaps xmm0,[xa]
movaps [xb],xmm0
printps [xb],1
输出:
A=[1 2 3 4 ; 5 6 7 8 ; 9 10 11 12 ; 13 14 15 16]
B=[1 1 1 1 ; 1 1 1 1 ; 1 1 1 1 ; 1 1 1 1 ]
[ 0.000000 1.000000 2.000000 3.000000 ]
[ 1.000000 1.000000 1.000000 1.000000 ]
[ 0.000000 1.000000 2.000000 3.000000 ]
B=[1.000000 1.000000 1.000000 1.000000
1.000000 1.000000 1.000000 1.000000
1.000000 1.000000 1.000000 1.000000
1.000000 1.000000 1.000000 1.000000]
我修改了xb,但矩阵B完好无损。为什么呢?
答案 0 :(得分:2)
xb没有16字节对齐的内存地址。如果以十六进制检查内存地址,则必须始终以0结尾。如果不是,则需要使用movup而不是movaps。
然而,简单地以64字节对齐几乎总是更好。
在Windows结帐时:_aligned_malloc
编辑:所以看看你的.bss部分,你似乎没有做你认为你在做的事情。您正在将存储在“EAX”的指针复制到单字节“xa”指向的地址。这可能不正确。
您需要确保原始分配是16字节对齐。从那里你可以通过一个movaps直接将A指向的矩阵的一行直接移动到一个xmm0寄存器,然后另一个从该寄存器移出!
编辑2:总之,xa和xb毫无意义。
movaps xmm0,[eax+16]
movaps [ebx],xmm0
虽然malloc分配的内存必须是16字节对齐...