MMX
MMX는 인텔이 설계한 SIMD(Single Instruction Multiple Data) 명령어 집합으로 여러개의 정수에 대한 병렬 연산을 제공한다. MM0부터 MM7까지의 8개의 64비트 레지스터로 연산을 처리한다.
MM 레지스터
총 64비트로 64 비트 정수 하나를 저장하거나, 16, 8, 4, 2, 1 바이트 크기와 같은 더 작은 크기의 정수를 여러개 저장할 수 있다. 여러개의 정수를 하나의 레지스터에 저장하는 형태를 'Packed' 라 한다. 하나의 MMX의 명령어는 두개의 32비트 정수, 네개의 16비트 정수, 여덟개의 8비트 정수를 처리한다.
이동 명령어 MOVD, MOVQ
각각 Doubleword (4바이트), Quadword (8바이트)를 의미한다.
MOVD의 경우 메모리에서 mm 레지스터로 값을 옮길 때, 상위 32비트는 0으로 채워진다.
Unpack
SIMD 프로그래밍에서 Unpack은 여러개의 벡터를 합쳐 더 큰 벡터를 만드는 것이다.예를 들어, [1,1,1,1] 과 [2,2,2,2]를 합쳐 [1,1,1,1,2,2,2,2]를 생성하는 식이다. MMX에도 이러한 기능을 지원하는 명령어가 있다. 각 레지스터의 절반을 사용하여 전체 레지스터를 채운다.
Unpack 명령어
| 명령어 | 의미 |
| punpcklbw | unpack lower-half byte to word |
| punpcklwd | unpack lower-half word to doubleword |
| punpckldq | unpack lower-half doubleword to quadword |
| punpckhbw | unpack higher-half byte to word |
| punpckhwd | unpack higher-half word to doubleword |
| punpckhdq | unpack higher-half doubleword to quadword |
많은 어셈블리 명령어가 그렇듯 unpack 명령어도 줄임말이다. mov같은 간단한 명령어는 직관적으로 의미가 와닿지만 unpack 명령어는 그렇지 않다. 그래서 뜻을 풀어서 이해해야 의미를 잘 알 수 있다고 생각한다. 오른쪽에 명령어의 의미를 풀어서 써놨다. 맨 앞에 공통적으로 붙은 p는 packed된 레지스터 값에 대한 명령어임을 나타내는 것이라고 이해했다.
punpcklbw는 레지스터의 하위 절반을 사용하여 byte를 word로 만드는 것이다. 이게 무슨 소리인지는 그림을 보면서 이해해야 한다.

위의 그림은 puncklbw mm0, mm1을 도식화 한 것이다. 두 레지스터의 하위 32 비트('lower half')를 합친다. 이 때, byte를 두개 합쳐 word를 만드는데, 첫번째 피연산자 레지스터에서 1 바이트, 두번째 비연산자 레지스터의 바이트를 차례대로 배치하여 word를 만든다. 결과는 첫번째 피연산자 레지스터에 저장된다.
puncklbw 외의 다른 연산자도 같은 방식으로 동작한다. 하위 32 비트 또는 상위 32 비트를 정해진 비트 크기만큼 번갈아가며 배치하여 그 크기의 두배 크기의 비트 수 정수를 만든다. 즉, word 두개로 doubleword를, doubleword 두개로 quadword를 만든다.
예시 코드
#define ALIGN8 __declspec(align(8))
ALIGN8 int v[4] = { 0x01234567, 0x89ABCDEF, 0xFFFFFFFF, 0xFFFFFFFF};
ALIGN8 short r[4] = {0xABCD, 0xABCD, 0xABCD, 0xABCD};
void __declspec(naked) foo() {
__asm {
movd mm0, v
movq mm1, r
punpckhwd mm0, mm1
punpckldq mm0, mm0
punpckhwd mm0, mm0
movq r, mm0
emms //mmx 상태 clear
ret
}
}
int main() {
foo();
return 0;
}
위 코드에서 foo()를 실행한 직후에 배열 r에는 다음과 같이 값이 저장된다. 참고로 1바이트 씩 보여주는 메모리 뷰이다.

각 명령어에 따른 mmx 레지스터 및 메모리 변화를 추적해보면 unpack에 대해 더 잘 이해할 수 있을 것이다.
'assembly language' 카테고리의 다른 글
| [POCU 아카데미] COMP2300 어셈블리 프로그래밍 수강 후기 (0) | 2023.08.21 |
|---|---|
| [X86 어셈블리] FPU 프로그래밍 / 구의 부피 계산하기 / fmul, fmulp, fdiv, fdivp (0) | 2023.08.04 |
| [X86 어셈블리] FPU 프로그래밍 / 8087 / 주요 명령어 정리 (0) | 2023.08.03 |
| [X86 어셈블리] strncpy 구현하기 / movsb 명령어 / 문자열 (0) | 2023.08.02 |
| [X86 어셈블리] strncmp 구현하기 / cmpsb, cmpsw, repe 명령어 (0) | 2023.08.01 |