32位汇编语言学习笔记(4)--移位操作



sal k, DD = D << k,左移。

shl,与sal相同。

sar k, DD = D >> k,算术右移。

shr k, DD = 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 //把参数1x的值装入eax

         sall   $2, %eax // eax = eax << 2

         movl          12(%ebp), %ecx //把参数2n的值装入ecx

         sarl  %cl, %eax //ecx的低8位就是cl,所以cl=neax = 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

你可能感兴趣的:(32位汇编语言学习笔记(4)--移位操作)