Zero-extending과 Sign-extending은 작은 크기의 데이터를 더 큰 크기의 레지스터로 복사할 때 사용하는 방법입니다. 두 방법 모두 데이터를 소스에서 대상으로 복사하는데 사용되지만, 빈 공간을 채우는 방식이 다릅니다.
Zero-extending (movz
class):
0
으로 채웁니다.movzbw
는 바이트(byte)를 워드(word, 2바이트)로 확장할 때 사용되며, 복사된 바이트 외의 바이트는 0
으로 채워집니다.Sign-extending (movs
class):
movsbw
를 사용하여 워드로 확장할 때 나머지 바이트도 1
로 채워집니다.각 명령어의 이름 뒤에 있는 두 문자는 소스와 대상의 크기를 나타냅니다. 예를 들어, movzbw
에서 b
는 바이트(byte)를, w
는 워드(word)를 나타냅니다.
이러한 확장 명령어는 주로 작은 데이터 타입에서 큰 데이터 타입으로 변환할 때 사용됩니다. 변환하는 동안 데이터의 원래 의미를 유지하기 위해 위와 같은 확장 방법이 필요합니다.
각 레지스터의 접미사는 해당 레지스터의 크기를 나타냅니다:
b
: 바이트 (1 바이트)w
: 워드 (2 바이트)l
: 더블 워드 (4 바이트)q
: 쿼드 워드 (8 바이트)이를 기반으로 각 명령의 접미사를 결정할 수 있습니다:
mov__ %eax, (%rsp)
%eax
는 더블 워드 크기의 레지스터입니다.movl
mov__ (%rax), %dx
%dx
는 워드 크기의 레지스터입니다.movw
mov__ $0xFF, %bl
%bl
는 바이트 크기의 레지스터입니다.movb
mov__ (%rsp,%rdx,4), %dl
%dl
는 바이트 크기의 레지스터입니다.movb
mov__ (%rdx), %rax
%rax
는 쿼드 워드 크기의 레지스터입니다.movq
mov__ %dx, (%rax)
%dx
는 워드 크기의 레지스터입니다.movw
이로써 각 명령어에 대한 올바른 접미사를 결정할 수 있습니다.
Q. 3번에서 $0xFF의 크기를 고려하지 않고 %bl의 크기를 고려하는 이유는 뭔가요?
좋은 질문입니다. x86 어셈블리에서 mov
명령어의 경우 대상 레지스터의 크기가 주어진 데이터를 이동시키는 데 사용됩니다. mov
의 경우 소스 데이터의 크기는 무시되며 대상 레지스터의 크기만 고려됩니다.
3번 예제에서 $0xFF
는 1바이트 값을 나타냅니다. 그러나 실제로 이 값을 2바이트 레지스터 또는 4바이트 레지스터에 이동할 수도 있습니다. 그래서 실제로 어떤 레지스터로 데이터가 이동되는지 확인하여 접미사를 결정합니다. 여기서 %bl
는 바이트 크기의 레지스터이므로, movb
를 사용합니다.
이러한 방식으로 mov
명령어는 소스 데이터의 크기를 알 필요 없이 대상 레지스터의 크기에 따라 데이터를 이동시킬 수 있습니다.