【问题标题】:- assembly sse - segmentation fault - move a matrix row in another matrix- 装配 sse - 分段错误 - 在另一个矩阵中移动一个矩阵行
【发布时间】:2014-05-30 21:36:46
【问题描述】:

我有两个矩阵 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 ,我在程序集中调用程序集 'exportRow(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

为什么最后一条指令会导致分段错误?哪里有问题? 如果我在最后一条指令中将 [xb] 替换为 [xa](仅用于测试),我没有任何错误。

---编辑---

如果我修改[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

案例 alignb 32: 如果我得到 [xa+16] ,我有分段错误。

案例 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 是完整的。为什么?

【问题讨论】:

  • 可能只是内存错位。
  • 如何对齐?我测试一下
  • 是的,问题就在这里!改变 [xb],因为这些改变对矩阵 B 也没有影响?

标签: c assembly matrix


【解决方案1】:

xb 没有 16 字节对齐的内存地址。如果以十六进制检查内存地址,则要求始终以 0 结尾。如果不是,则需要使用 movups 而不是 movaps。

不过,简单地对齐 64 字节几乎总是更好。

在 Windows 结帐时:_aligned_malloc

编辑:所以看看你的 .bss 部分,你似乎没有做你认为你正在做的事情。您正在将存储在“EAX”中的指针复制到单字节“xa”指向的地址。这不可能是正确的。

您需要确保您的原始分配是 16 字节对齐的。从那里,您可以直接通过 movaps 将 A 指向的矩阵的一条线直接移动到 B 到 xmm0 寄存器,然后从该寄存器中再移动另一条 movaps!

编辑 2:总之 xa 和 xb 毫无意义。

movaps  xmm0,[eax+16]
movaps  [ebx],xmm0 

虽然 malloc 分配的内存必须是 16 字节对齐的......

【讨论】:

  • 实际上 xa 和 xb 以 32 个字节对齐。做一个小改动: movaps xmm0,[xa+16] movaps [xb],xmm0 printps [xb],1 我得到“SEGMENTATION FAULT”... [xa+16] 是矩阵的第二行(浮点数)4x4?
  • @user3661321 我有兴趣查看指针值。使用 movups 时还会出现崩溃吗?如果你这样做了,你就没有正确分配内存,如果没有,那么内存不是 32 字节对齐的!
  • @user3661321:为什么你认为 malloc 返回 32 字节对齐?可能不会。还有……你尝试过 movups 实验吗?
  • @user3661321:矩阵不在 .bss 部分,别忘了!!
  • 我的目标是有一个变量 X 指向数组的内存块的开头,这样我就可以轻松访问位置 X [i]。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-10
  • 2022-11-21
相关资源
最近更新 更多