This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Shifting: what's going on?
- From: "Facundo Ciccioli" <facundofc at gmail dot com>
- To: gcc-help at gcc dot gnu dot org
- Date: Thu, 29 Mar 2007 02:55:49 -0300
- Subject: Shifting: what's going on?
Hi. What follows applies to gcc (GCC) 3.4.2 (mingw-special), platform
x86-32bits.
This code:
int main() {
unsigned long long a= 1;
unsigned s= 63;
a= (a << s);
return 0;
}
generates this assembler (removing preamble and prologue stuff):
movl $1, -8(%ebp)
movl $0, -4(%ebp)
movl $63, -12(%ebp)
movl -12(%ebp), %ecx
movl -8(%ebp), %eax
movl -4(%ebp), %edx
shldl %cl,%eax, %edx
sall %cl, %eax
testb $32, %cl
je L2
movl %eax, %edx
movl $0, %eax
L2:
movl %eax, -8(%ebp)
movl %edx, -4(%ebp)
This is fine, and works as I expect.
However, this code:
int main() {
unsigned long long a;
unsigned s= 63;
a= (1 << s);
return 0;
}
generates this assembler:
movl $63, -12(%ebp)
movl -12(%ebp), %ecx
movl $1, %eax
sall %cl, %eax
cltd
movl %eax, -8(%ebp)
movl %edx, -4(%ebp)
which is... wrong. Not only the results aren't what they should, but
looking a little harder, the assembler generated doesn't seem to make
sense. What's with the CLTD instruction there? If I change s (the
shifted amount) to be 63 (31 is equivalent, because only 5 bits of %cl
are used) then the result are a bunch of 1's because the sign of %eax
goes all over %edx. And that's only one problem. If s is between 62
and 32, the 1 appears in %eax instead of being in %edx, where it
should.
This is obviusly not urgent, since the first code is perfectly
acceptable and applicable to what I am doing, but I just got curious.
Thanks a lot.
FaQ