Short answer: the Intel processor masks the shift count to 5 bits (maximum 31). In other words, the shift actually performed is ( 32 | 31 ) = 0 bits (no change).
The same result appears using gcc on a Linux 32-bit PC.
I assembled a shorter version of this program because I was puzzled by why a left shift of 32 bits should result in a non-zero value at all:
int main(){
int y = 32;
unsigned int z = 1 << y;
unsigned int k = 1;
k <<= y;
printf("z: %u, k: %u\n", z, k);
}
..using the command gcc -Wall -o a.s -S deleteme.c
(comments are my own)
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $32, -16(%ebp) ; y = 32
movl -16(%ebp), %ecx ; 32 in CX register
movl $1, %eax ; AX = 1
sall %cl, %eax ; AX <<= 32(32)
movl %eax, -12(%ebp) ; z = AX
movl $1, -8(%ebp) ; k = 1
movl -16(%ebp), %ecx ; CX = y = 32
sall %cl, -8(%ebp) ; k <<= CX(32)
movl -8(%ebp), %eax ; AX = k
movl %eax, 8(%esp)
movl -12(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
Ok so what does this mean? It's this instruction that puzzles me:
sall %cl, -8(%ebp) ; k <<= CX(32)
Clearly k is being shifted left by 32 bits.
You've got me - it's using the sall
instruction which is an arithmetic shift. I don't know why rotating this by 32 results in the bit re-appearing in the initial position. My initial conjecture would be that the processor is optimised to perform this instruction in one clock cycle - which means that any shift by more than 31 would be regarded as a don't care. But I'm curious to find the answer to this because I would expect that the rotate should result in all bits falling off the left end of the data type.
I found a link to http://faydoc.tripod.com/cpu/sal.htm which explains that the shift count (in the CL register) is masked to 5 bits. This means that if you tried to shift by 32 bits the actual shift performed would be by zero bits (i.e. no change). There's the answer!