
어제 오퍼랜드에 관해서 글을 작성했는데요.
가장 많이 사용되는 인스트럭션(명령)은 데이터를 한 위치에서 다른 위치로 복사하는 명령입니다.
오퍼랜드 표시방법의 일반성 때문에 여러 개의 인스트럭션이 필요했을 이동 인스트럭션이 간단해졌어요.
그래서 이번에는 어떤 데이터 이동 인스트럭션이 있는지 그 종류를 말해보려 합니다.
들어가기 전에
우선, 인스트럭션 명령어들을 살펴보기 전에 알아야 할 정보가 하나 있어서 그것부터 짚고 넘어갈게요.
인텔 프로세서들이 16비트 구조를 사용하다가 추후에 32비트로 확장했기 때문에
인텔은 "워드"라는 단어를 16비트 데이터 타입을 말할 때 사용해요.
여기에 기초해서
그래서 이걸 표로 한번 살펴보면..!
| C Data Type | Assembly Suffix | Size (Bytes) | 설명 |
|---|---|---|---|
char | b (byte) | 1 | 부호 있음: signed char |
short | w (word) | 2 | 16비트 정수 |
int | l (long) | 4 | 32비트 정수 (x86 기준) |
long | q (quad) | 8 | 64비트 정수 (x86-64 기준) |
char * | q (quad) | 8 | 포인터는 64비트 (주소) |
float | s (scalar) | 4 | 단정도 부동소수점 |
double | l (long) | 8 | 배정도 부동소수점 |
1바이트(8bit)는 'b'
2바이트(16bit)는 'w'
4바이트(32bit)는 'ㅣ'
8바이트(64bit)는 'q' 입니다.
이것은 인스트럭션에서 접미사로 쓰이니까 알아둬야해요.
Q: 근데 4바이트는 double word 인데 왜 접미사가 'L' 이냐고요?
Q: int도 'l' 접미사고 double도 'l' 접미사인데 헷갈리지 않냐고요?
자 이제 접미사 알았으니까 이동 인스트럭션 쓰러 부릉~ 가요~!
| 어셈블리 명령어 | 설명 | 원본 크기 → 목적지 크기 | C 코드 예시 |
|---|---|---|---|
| movb | 바이트 복사 | 1B → 1B | char a = b; |
| movw | 워드 복사 | 2B → 2B | short a = b; |
| movl | 더블워드 복사 | 4B → 4B | int a = b; |
| movq | 쿼드워드 복사 | 8B → 8B | long a = b; 또는 char *p = q; |
이건 정말 간단한 데이터 이동 인스트럭션인데요.
mov 가 제일 앞에 있고 그 뒤에 접미사로
"b" , "w" , "l" , "q" 가 있죠?
해당 사이즈와 동일한 사이즈로 데이터를 이동시킨다는 뜻입니다.
별 거 없죠?
실제로 어떤 c 명령어가 어셈블리에서 변경되는지 보기 쉬우라고 c코드 예시도 적어놨어요.
감사합니다 챗선생님.
" 0의 확장 " 아시죠?
movz < 접두사가 붙은 인스터럭션들은 목적지의 남은 바이트들을 전부 0으로 채워줘요.
그래서 mov 뒤에 z 가 붙었답니다?
| 어셈블리 명령어 | 설명 | 원본 크기 → 목적지 크기 | C 코드 예시 |
|---|---|---|---|
| movzbw | Zero-extend byte → word | 1B → 2B | unsigned short a = (unsigned char)b; |
| movzbl | Zero-extend byte → long | 1B → 4B | unsigned int a = (unsigned char)b; |
| movzbq | Zero-extend byte → quad | 1B → 8B | unsigned long a = (unsigned char)b; |
| movzwl | Zero-extend word → long | 2B → 4B | unsigned int a = (unsigned short)b; |
| movzwq | Zero-extend word → quad | 2B → 8B | unsigned long a = (unsigned short)b; |
movz 뒤에는
"bw" , "bl" , "bq" , "wl" , "wq" 가 붙었는데요.
어떤 사이즈로 변경되는지 명시하는거예요.
bw 는 byte => word
bl 는 byte => double word
bq 는 byte => quater word
wl 는 word => double word
wq 는 word => quater word
그리고 남는 비트는 0으로 채워주기!
엥??? 근데 님아
왜 movzlq 없음?
double word => quater word 가 없는데?????
짜잔~ 그거는 movl 로 대체하기로 했답니다.
movl 명령어는 4바이트 데이터를 복사할 때, 상위 비트를 0으로 채우기로 했는데요.
그건 상위비트를 0으로 채우는 movzlq 명령어랑 똑같잖아요?
그래서 그냥 그거로 쓰기로 했대요.
왜냐고요?
"그냥 옛날부터 그랬으니까"
| 어셈블리 명령어 | 설명 | 원본 크기 → 목적지 크기 | C 코드 예시 |
|---|---|---|---|
| movsbw | Sign-extend byte → word | 1B → 2B | short a = (char)b; |
| movsbl | Sign-extend byte → long | 1B → 4B | int a = (char)b; |
| movsbq | Sign-extend byte → quad | 1B → 8B | long a = (char)b; |
| movswl | Sign-extend word → long | 2B → 4B | int a = (short)b; |
| movswq | Sign-extend word → quad | 2B → 8B | long a = (short)b; |
| movslq | Sign-extend long → quad | 4B → 8B | long a = (int)b; |
z (zero 확장) 이랑 똑같은데 이름만 s (sign-extend)로 바뀌었네~~
그리고 movzlq 는 0으로 채우는 거라 없었는데
movslq 는 부호 확장이라 있습니다!
정리
책으로 읽을땐 어려웠는데
이동 > 0의 확장 > 부호 확장 순으로 가니까 차이가 확 보이고 쉽죠?
mov 는 굉장히 많이 일어나는 인스트럭션이라 외워두시면
어셈블리어를 읽고 작성하는데 많은 도움이 될 것 같아요.