Data Transfer Instructions 1

1 minute read

Data Transfer Instructions

데이터 전송 명령어

데이터 전송 명령어에는

  1. 일반적인 데이터의 이동 (General data movement)
  2. (데이터의) 교환 (Exchange)
  3. 스택 조작 (Stack manipulation)
  4. 자료형 변환 (Type conversion)

등이 있다.

1. General Data Movement - MOV instruction

상당히 까다롭다.
C나 C++ 프로그래밍에서 ‘=’ 같은 대입 연산자를 쓸 때처럼 막 할 수가 없다.

왜냐하면 이는 메모리 -> 메모리 가 불가능하다.

범용 레지스터 -> 메모리
세그먼트 레지스터 -> 메모리
범용 레지스터 -> 세그먼트 레지스터
범용 레지스터 -> 범용 레지스터
범용 레지스터 -> 제어 레지스터

상수 -> 범용 레지스터
상수 -> 메모리

상수를 제외한 위의 5개는 각각의 역도 가능하다.

근데 왜인지 메모리 -> 메모리 는 죽어도 불가능하다.
어셈블 시 operand 가 맞지 않는다며 에러를 띄운다.
또한, 상수를 메모리에 저장할 때는 그 크기를 지정해줘야 한다.

당연한 이야기지만 메모리 -> 제어 레지스터나, 세그먼트 레지스터는 안 된다.
애초에 그 레지스터에 메모리에 들어있는 값을 저장할 일이 없다.

cmov 라는 것도 있다.
이는 펜티엄 이상만 사용 가능한 명령어로,
conditional move 의 줄임말이다.

cmov? eax, ebx 같은 방식으로 쓰이는데,
?에 c, z, s, o, p 같은 EFLAGS 들을 붙일 수가 있다.
예를 들어,

cmovz eax, ebx

는 zflag가 1이면 mov 명령어를 실행하라는 뜻이다.
nasm 프로그래밍하면서 쓸 일은 없을 것 같은데,
최소값 저장할 때 거추장하게 if 블록 만들어서 저장하는 거보단 훨씬 편할 것 같다.

2. Exchange Instruction

xchg, 딱 봐도 exchange 의 줄임말 같다.

이것은 mov 보다 더 악독한 명령어이다.
범용 레지스터들끼리, 그리고 범용 레지스터와 메모리끼리만 교환이 가능하다.
그말은, 세그먼트 레지스터끼리, 혹은 메모리끼리는 교환이 불가능하다.
세그먼트 레지스터끼리는 값을 교환할 일이 없다지만,
메모리끼리의 교환이 불가한 것은 불편할 것 같다.
저급 언어라 컴퓨터 설계에 의존해서 그런 것 같다.

자매품으로 bswap, bit swap 이란 명령어가 있다.
이는 첫번째-네번째, 두번째-세번째 바이트를 서로 바꾼다.
즉 엔디안을 바꿀 때 필요하다.
인텔은 리틀 엔디안을 쓰는데,
이걸 서버로 전송할 때 쓰는 걸로 보인다.

리틀 엔디안은 우리가 흔히 아는 2진수의 순서의 반대이다.
빅 엔디안 방식으로 저장한 이진수가 1001010 이라고 했을 때,
이를 읽을 땐 우리가 읽는 순서대로 1001010 으로 읽지만
리틀 엔디안은 0101001 으로 반대로 읽고, 또 그렇게 저장된다.
리틀 엔디안은 수를 읽을 때 빅 엔디안보다 더 효율적이다.

레지스터가 아무리 32비트라지만, 일반적으로 우리가 수를 저장한다고 쳤을 때
30-31자리나 되는 양수를 쓸 확률이 높을까, (signed 기준)
아니면 기껏해야 4-5자리의 양수를 쓸 확률이 높을까?

마이크로프로세서는 보통 리틀 엔디안 방식이다.
그러니 여기서 컴퓨터끼리 데이터를 보낼 땐
그 반대인 빅 엔디안으로 보내야 그쪽에서 리틀 엔디안 방식으로 받는다.