Data Transfer Instructions 1
Data Transfer Instructions
데이터 전송 명령어
데이터 전송 명령어에는
- 일반적인 데이터의 이동 (General data movement)
- (데이터의) 교환 (Exchange)
- 스택 조작 (Stack manipulation)
- 자료형 변환 (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자리의 양수를 쓸 확률이 높을까?
마이크로프로세서는 보통 리틀 엔디안 방식이다.
그러니 여기서 컴퓨터끼리 데이터를 보낼 땐
그 반대인 빅 엔디안으로 보내야 그쪽에서 리틀 엔디안 방식으로 받는다.