shift 연산

Computing 2008. 5. 20. 17:01
32비트 컴퓨터에서


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

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

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

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

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

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

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

마치 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을 보아도 마찬가지 설명(마스크 아웃한다는)이 나와 있다.

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

: