- assembly sse - 分段错误 - 在另一个矩阵中移动矩阵行

时间:2014-05-30 21:36:47

标签: c assembly matrix

我有两个矩阵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中以flo​​at *分配。 从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完好无损。为什么呢?

1 个答案:

答案 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字节对齐...