태그 미디어로그 위치로그
shift 연산
알티베이스™ 라이프

32비트 컴퓨터에서

#include

int main(void)
{
unsigned int a = 1;

a <<= 33;
printf(”0x%08X\n”, a);

return 0;
}

위 코드의 출력값은 얼마일까?

제일 처음 떠오르는 답은 0×00000000 일 것이다.

조금 눈치가 빠른 사람이라면 0×00000000 이 상식적인 답이겠지만
답이 0×00000000 이 아니기 때문에 이런 문제를 내었으리라 짐작하고서는
뭔가가 있다고 생각할 것이다.

정말 뭔가가 있다.
컴파일을 하고,

$ gcc b.c
b.c: In function ‘main’:
b.c:7: warning: left shift count >= width of type

gcc 가 친절하게 warning 도 내어 준다.

실행을 시키면,
$ ./a.out 
0×00000002

마치 circular shift된 것 같은 결과가 나온다.
왜 그럴까?

컴파일러가 << 연산의 operand 에 modular 연산을 취할까?
단지 << 연산인데, 그냥 shl 같은 instruction으로 곧장 매핑시키지 않고
modular연산 따위를 컴파일러가 할까?
아무래도 그건 오버하는 것 같다.

cpu instruction manual 을 살펴 보았다.

Intel? 64 and IA-32 Architectures Software Developer’s Manual Volume 2B: Instruction Set Reference, N-Z 에서는 shift 연산에 대해서 아래와 같이 이야기하고 있다 :

The destination operand can be a register or a memory location. The count operand
can be an immediate value or the CL register. The count is masked to 5 bits (or 6 bits
if in 64-bit mode and REX.W is used).
 The count range is limited to 0 to 31 (or 63 if
64-bit mode and REX.W is used). A special opcode encoding is provided for a count
of 1.

역시나, 컴파일러가 오버하는 것이 아니었다.
인텔은 그렇다 해도 다른 CPU, ppc 나 sparc 은 어떨까?
sun 과 aix 에서 테스트 해 본 결과 마찬가지 결과가 나왔다.
sparc v9 instruction set reference manual을 보아도 마찬가지 설명(마스크 아웃한다는)이 나와 있다.

우연히 찾은 것이지만,
재미있는 것이라고 생각되어서 한번 적어 보았다.