位运算

 

 

汇编中的移位指令

1、算术移位指令

 

 

  • SAL(Shift Arithmetic Left):算术左移

  • SAR(Shift Arithmetic Right):算术右移

  • 格式:SAL/SAR Reg/Mem, CL/Imm

即算数移位指令后面的第一个操作数是寄存器或者内存;

第二个操作数是寄存器或者立即数

SAL eax,2
SAL ax,1
SAL al,3


举例:
SAR al,1         //al:10000001右移一位最高位补原来符号位,最低位移入CF,即11000000 / CF:1
SAL al,2         //al:10000001左移两位最高位移入CF,最低位补0,即00000100 /  CF:0

2.逻辑移位指令

 

  • SHL(Shift Left):逻辑左移

  • SHR(Shift Right):逻辑右移

  • 格式:SHL/SHR Reg/Mem, CL/Imm

    SHL eax,2
    SHR word ptr es:[ebp],1
    SHL al,1

    举例:
    SHR al,1         //al:10000001右移一位最高位补0,最低位移入CF,即01000000 /  CF:1
    SHL al,1         //al:01000001左移一位最高位移入CF,最低位补0,即10000010 /  CF:0

     

3.循环移位指令

 

  • ROL(Rotate Left):循环左移

  • ROR(Rotate Right):循环右移

  • 格式:ROL/ROR r/m, i8/CL

    ROL eax,3
    ROL cx,1
    ROR cl,2

    举例
    ROL al,1   //al:10000001循环左移一位最高位补到最低位,最高位移入CF,即00000011 /  CF:1
    ROR al,1   //al:10000001循环右移一位最低位补到最高位,最低位移入CF,即11000000 /  CF:1

4.带进位的循环移位指令

 

  • RCL(Rotate through Carry Left):带进位循环左移

  • RCR(Rotate through Carry Right):带进位循环右移

  • 格式:RCL/RCR r/m, i8/CL

RCL eax,1
RCR cx,2
RCR al,1

举例:
RCL al,1 //al:10000001,CF:0循环左移一位最高位移入CF,CF原来的数补到最低位,即al:00000010 / CF:1
RCR al,1 //al:10000001,CF:0循环右移一位最低位移入CF,CF原来的数补到最高位,即al:01000000 / CF:1

C语言中的移位运算

与运算 &

printf("%d",2&3); //2

或运算 |

printf("%d",2|3); //3

非运算 ~

printf("%d",~2); //-3,因为%d打印的是有符号的整数

异或运算 ^

printf("%d",2^3); //1

移位运算 << >>

左移运算,有符号和无符号是无区别的

int a = 8;
printf("%d",a<<1);  //16
unsigned int b = 8;
printf("%d",b<<1);  //16

查看反汇编:生成的汇编指令都是shl,逻辑左移

img

右移运算,有符号对应SAR即算数右移,无符号对应SHR即逻辑右移

int a = 0xF0000000;
printf("%d",a>>1);  //-134217728
unsigned int b = 0xF0000000;
printf("%d",b>>1);  //2013265920

查看反汇编:有符号右移生成的指令为SAR,无符号右移生成的指令为SHR

img

作业

 

#include "stdafx.h"
​
​
    void Function_1_1()     
    {
            unsigned char x=0xf5,y=0xff;
            int i;
            scanf("%d",&i);
        /*  if((x=x&(y<<i))==0)
                (printf("第%d位是0",i+1));
            else
                (printf("第%d位是1",i+1));
*/
    printf("第%d位是%x",i,x=x&(y>>(8-i))); 
        //  printf("%x",x);
            
    }       
​
​
​
int main()
{           
​
        Function_1_1();             
​
    return 0;
​
}
 

 

  • 用十六进制文本编辑器分别打开一个.exe、.dll、.sys、.txt、.doc、.jpg、.pdf等将前两个字节写在下面

.exe:内存中显式为4D 5A,我们读作0x5A4D .dll:同样是4D 5A .sys:4D 5A开头,但也有25 75 .txt:0A 66,读作0x660A .doc:D0 CF,读作0xCFD0 .jpg:FF D8 .pdf:25 50,读作0x5025

  • 将一个在十六进制编辑器中打开的.exe文件,拖拽到最后,观察文件中的大小和硬盘上的大小

可以发现用十六进制编辑器打开一个.exe文件,它的最大地址0x0829CDF0,换算成10进制,就刚好等于这个文件的大小136957440字节 img

posted on 2022-11-03 11:03  骑着驴子追宝马  阅读(205)  评论(0编辑  收藏  举报

导航