movdqu

mov : asm 에서의 mov 와 유사한 의미
dq  : double quad (word) 로 quad word는 word 의 4배 인 8 byte 와 
      앞의 double 이 붙어 2*8 = 총 16 바이트인데 word 가 기본 pack 사이즈를 말함으로 2바이트씩 나눈 배열을 말함
u   : unalign 으로 메모리에 있는 값들이 정렬되지 않은 값을 레지스터로 옮길때 붙이는 첨자
      (정렬되지 않은것은 캐쉬미스가 발생하여 오래 걸릴수 있음, 하단 그림 참조)



movdqa

a : align  : 메모리가 정렬된 상태로 정렬돈 메모리를 레지스터로 복사 시킬때에는 16개의 바이트의 메모리가 모두
             붙어 있기 때문에 캐쉬에서 레지스터로 옮길때 부하없이 로드할 수 있다 (하단 그림 참조)
a를 제외한 나머지는 movdqu 에서 movdq 들과 동일한 의미









SIMD 로 배열 copy 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
int main(int argc, char* argv[])
 
{
 
    short A[8= {1,2,3,4,5,6,7,8};
 
    short B[8= {0};        
 
    __asm
 
    {
 
        pushad
 
        movdqu  xmm0, A    //한 사이클에 모두 복사된다    
 
        movdqu  B, xmm0    //한 사이클에 모두 복사된다    
 
        popad
 
        emms
 
    }
 
    printf("B : %d,%d,%d,%d,%d,%d,%d,%d\n",B[7],B[6],B[5],B[4],  B[3],B[2],B[1],B[0]);
 
    return 0;
 
}

cs



배열에서 xmm0 레지스터로 copy 되는 내역을 볼 수 있는데 순서는 반대로 copy 된다
xmm0 에서 배열로 copy 될때도 반대로
그리하여 다시 배열로 올때는 일반적으로 예상할 수 있는 A 상태 그대로의 순서대로 오는 것을 알 수 있다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-        xmm0    {m128_f32= {1.837e-40#DEN, 3.673e-40#DEN, 5.510e-40#DEN, 7.347e-40#DEN}  m128_f64= {5.562748306789e-309#DEN, ...} ...}    __m128
+        m128_f32    {1.837e-40#DEN, 3.673e-40#DEN, 5.510e-40#DEN, 7.347e-40#DEN}    float[4]
+        m128_f64    {5.562748306789e-309#DEN, 1.112551783418e-308#DEN}    double[2]
+        m128_i8    "\x1"    char[16]
-        m128_i16    {12345678}    short[8]
        [0]    1    short
        [1]    2    short
        [2]    3    short
        [3]    4    short
        [4]    5    short
        [5]    6    short
        [6]    7    short
        [7]    8    short
+        m128_i32    {131073262147393221524295}    int[4]
+        m128_i64    {11259127918755852251829878849541}    __int64[2]
+        m128_u8    "\x1"    unsigned char[16]
+        m128_u16    {12345678}    unsigned short[8]
+        m128_u32    {131073262147393221524295}    unsigned int[4]
+        m128_u64    {11259127918755852251829878849541}    unsigned __int64[2]
        eax    39226256    unsigned int

cs



XMM0 = 0008000700060005-0004000300020001 

XMM1 = 0000000000000000-0000000000000000 

XMM2 = 0000000000000000-0000000000000000 

XMM3 = 0000000000000000-0000000000000000 

XMM4 = 0000000000000000-0000000000000000 

XMM5 = 0000000000000000-0000000000000000 

XMM6 = 0000000000000000-0000000000000000 

XMM7 = 0000000000000000-0000000000000000 





결과

B : 8,7,6,5,4,3,2,1





[movdqa]
정렬된 데이이터의 데이터 복사

__declspec(align(16)) 과 movdqa를 사용한 예이며 결과는 movdqu 와 동일하다


단 주의해야하는 점은 movdqa 의 경우 정렬된 데이터를 취급함으로 __declspec(align(16)) 를 배열에서 빼고
실행할 경우 크래쉬가 발생한다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main(int argc, char* argv[])
{
 
    __declspec(align(16)) short A[8= {1,2,3,4,5,6,7,8};
    __declspec(align(16)) short B[8= {0};
    __asm
    {
        pushad
        movdqa  xmm0, A        
        movdqa  B, xmm0        
        popad
        emms
    }
    printf("B : %d,%d,%d,%d,%d,%d,%d,%d\n",B[7],B[6],B[5],B[4],  B[3],B[2],B[1],B[0]);
    return 0;
}
 

cs



반응형

+ Recent posts