sal k, D,D = D << k,左移。
shl,与sal相同。
sar k, D,D = D >> k,算术右移。
shr k, D,D = D >>(L) k,逻辑右移。
算术右移是指左边空出来的位填符号位。
逻辑右移是指左边空出来的位填0。
示例:
/*shift.c*/
int shift_left2_rightn(int x, int n)
{
x<<= 2;
x>>= n;
return x;
}
gcc -O1 -S -m32 shift.c
shift_left2_rightn:
pushl %ebp n
movl %esp, %ebp
movl 8(%ebp), %eax //把参数1:x的值装入eax。
sall $2, %eax // eax = eax << 2。
movl 12(%ebp), %ecx //把参数2:n的值装入ecx。
sarl %cl, %eax //ecx的低8位就是cl,所以cl=n,eax = eax>> n。
popl %ebp
ret
int arith(int x,int y,
int z)
{
int t1 = x+y;
int t2 = z*48;
int t3 = t1 & 0xFFFF;
int t4 = t2 * t3;
return t4;
}
gcc -O1 -S -m32 arith.c
arith:
pushl %ebp
movl %esp, %ebp
movl 16(%ebp), %eax //eax = z
leal (%eax,%eax,2), %eax // eax= 3*z
sall $4, %eax // eax = 3*16*z =48*z = t2
movl 12(%ebp), %edx // edx = y
addl 8(%ebp), %edx // edx = x +y = t1
andl $65535, %edx // edx = t1& 65535 = t1 & 0xffff = t3
imull %edx, %eax //eax = t3 * t2= t4
popl %ebp
ret
反汇编练习:
假设函数参数压栈顺序从右到左,函数声明是int func(int x, int y, int z);
movl 12(%ebp), %eax //eax = y
xorl 8(%ebp), %eax //eax = y ^x = t1
sarl $3, %eax // eax = (y^x)<<3 = t2= t1 << 3
notl %eax // eax = ~((y^x)<<3) = t3 =~t2
subl 16(%ebp), %eax // eax = eax – z = t4 =t3 - z
最终函数的代码如下:
int func(int x, int y, int z)
{
int t1 = y ^ x;
int t2 = t1<< 3;
int t3 = ~t2;
int t4 = t3 - z;
return t4;
}
进行反汇编验证:
gcc -O1 -S -m32 func.c
func:
pushl %ebp
movl %esp, %ebp
movl 12(%ebp), %eax
xorl 8(%ebp), %eax
sall $3, %eax
notl %eax
subl 16(%ebp), %eax
popl %ebp
ret