x86移位SHL、SHR、SAL、ROL、RCR等指令简介
SHL指令
SHL指令使dest左移count位,低位用0补充,高位的值移位到CF位(覆盖原CF位)
SHL指令的可用操作类型如下
SHL reg, imm8SHL mem, imm8SHL reg, CLSHL mem, CL
代码示例如下
; 代码示例.386.model flat, stdcall.stack 4096ExitProcess PROTO, dwExitCode:DWORDInclude Irvine32.inc ; .data.codemain PROCmov al, 01101110bmov cl, 1 shl al, cl ; 左移1位, 把MSB移入CF位, CF = 0, 低位补0, 此时al的值为 1101 1100,exitmain ENDPEND main
; 代码示例.386.model flat, stdcall.stack 4096ExitProcess PROTO, dwExitCode:DWORDInclude Irvine32.inc ; .data.codemain PROCmov al, 01101110bshl al, 2 ; 左移2位, 把从左往右移入第二位1移入CF位, CF = 1, 低位补0, 此时al的值为 1011 1000,exitmain ENDPEND main
关于OF位的实验数据
; 代码示例.386.model flat, stdcall.stack 4096ExitProcess PROTO, dwExitCode:DWORDInclude Irvine32.inc ; .data.codemain PROC;mov al, 01101110b;shl al, 1 ; 左移1位,相当于al * 2,并把msb移入cf位。假设此时al的值为有符号位数,; 有符号整数(正数) * 2乘以2,理论上只要不存在溢出,结果还是正数,、; 但此时得到的结果是 1101 1100,最高位为1是负数,所以 OF = 1mov al, 01101110b ; 左移三位,相当于al * 2 * 2 * 2,并把从左往右的第三位1移入cf位。shl al, 3 ;此时得到的结果是 0111 0000, 此时的溢出位OF = 1。 原因是在第二次; 移位的时候al的值时10111000最高位是1代表的是负数, 而负数*2(再次左移1位)结果应该还是负数; 但是此时al的是01110000最高位为0,所以溢出OF=1exitmain ENDPEND main
SHR指令
SHR指令使dest右移count位,高位用0补充,低位的值移位到CF位(覆盖原CF位)
SHR指令的操作类型和SHL一致
代码示例如下
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 01101111bshr al, 1 ; 右移1位,相当于al / 2(舍弃最低位),并把lsb移入cf位,CF = 1。高位补0, 此时结果是00110111exitmain ENDPEND main
;vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 01101111bshr al, 2 ; 右移2位,相当于al/2/2(舍弃最低的两位位),并把(从右到左)第二位移入cf位,CF = 1。高位补0, 此时结果是; 00011011exitmain ENDPEND main
关于OF位的实验数据
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 11101111bshr al, 1 ; 右移1位,相当于al/2(舍弃lsb),并把(从右到左)第1位移入cf位,CF = 1。高位补0, 此时结果是01110111; 因为最高位是1代表负数,除以2还是负数,但是结果是01110111, MSB是0,所以OF = 1exitmain ENDPEND main
SAL指令(算术左移)的操作和SHL一致
SAR指令(算术右移)
SAR指令使dest右移count位,高位用dest的最高位补充,低位的值移位到CF位(覆盖原CF位)
SAR指令的操作类型和SHL一致
代码示例如下
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 11101111bsar al, 1 ; 右移1位,相当于al/2(舍弃lsb),并把(从右到左)第1位移入cf位,CF = 1。高位补al的符号位, 此时结果是; 11110111mov al, 01101101bsar al, 2 ; 右移2位,相当于al/2/2(舍弃最低的两位),并把(从右到左)第2位移入cf位,CF = 0。高位补al的符号位, 此时结果是0011011exitmain ENDPEND main
ROL循环左移指令
ROL指令使dest左移count位,把所有位都向左移,最高位复制到进位标志位和最低位(移动一位的情况)
指令的操作格式和SHL一致
代码示例
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 00101111b rol al, 3 ; 循环左移3位, 将(从左往右)第三位移入CF位,CF位置为1, 低5位左移三位,并且将高三位001移入低三位,; 结果是01111 001exitmain ENDPEND main
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 7fh rol al, 4 ; 对调7F为F7,将al循环左移4位, exitmain ENDPEND main
ROR指令循环右移指令
ROR指令使dest右移count位,把所有位都向右移,最低位复制到进位标志位和最高位(移动一位的情况)
指令的操作格式和SHL一致
代码示例如下
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 01110100bror al, 3 ; 右移三位, 将低三位100移入高位,并且将(从右到左)第三位1移入CF位,; 将CF位置为1, 结果为100 01110exitmain ENDPEND main
RCL指令带进位循环左移
RCL指令把每一位都向左移, 进位标志位复制到LSB, MSB复制到进位标志位
指令的操作格式和SHL一致
代码示例如下
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 01110100brcl al, 2 ; 将 01110100左移2位, rcl al, 2相当于rcl al, 1执行两次。; 第一次执行时, CF=0, al的MSB=0,把MSB移入CF,CF移入LSB=0,所以执行之后的结果是CF=0, al的值是; 11101000。; 第二次执行时, CF=0, al的MSB=1,把MSB移入CF,CF移入LSB=0,所以执行之后的结果是CF=1,AL的值是; 11010000rcl al, 1 ; 执行时,CF=1,AL的MSB=1,把MSB移入CF,CF移入LSB=1,所以执行之后的结果是CF=1,AL的值是10100001exitmain ENDPEND main
RCR指令带进位的循环右移
RCL指令把每一位都向左移, 进位标志位复制到MSB, LSB复制到进位标志位
指令的操作格式和SHL一致
代码示例如下
; vs MASM环境代码示例.386.model flat, stdcall.stack 4096Include Irvine32.inc ; .data.codemain PROCmov al, 01110101brcr al, 2 ; 将 01110100右移2位, rcr al, 2相当于rcr al, 1执行两次。; 第一次执行时, CF=0, al的LSB=1,把LSB移入CF,CF移入MSB=0 ,所以执行之后的结果是CF=1, al的值是00111010。; 第二次执行时, CF=1, al的LSB=0,把LSB移入CF,CF移入MSB=0,所以执行之后的结果是CF=0,AL的值是10011101rcr al, 1 ; 执行时,CF=0,AL的LSB=1,把LSB移入CF,CF移入MSB=0,所以执行之后的结果是CF=1,AL的值是01001110exitmain ENDPEND main