每种汇编语言都有进行操作数移位的指令,移位和循环移位指令在控制硬件设备,加密数据,以及实现高速图形运算时特别有用,移位指令也是汇编语言中最具特征的指令集,移位(Shifting)
的含义是在操作数内向左或向右移动数据位,Intel处理器提供了多种移位指令,具体如下表所示:
指令集 |
含义 |
指令集 |
含义 |
SHL |
逻辑左移(无符号数) |
SHR |
逻辑右移(无符号数) |
SAL |
算数左移(有符号数) |
SAR |
算数右移(有符号数) |
ROL |
循环左移(无符号数) |
ROR |
循环右移(无符号数) |
RCL |
循环左移(带进位的) |
RCR |
循环右移(带进位的) |
SHLD |
双精度左移(无符号) |
SHRD |
双精度右移(无符号) |
SHL指令: 对目标操作数执行逻辑左移(针对无符号数)
操作,其左移后最低位
以0填充
,而移动出去的最高位则会送入CF(进位标志)
中,原来的进位标志位中的值将被覆盖.
Intel处理器中定义,执行移位的源操作数的范围必须在0-255
之间,在任何处理器上都可以使用CL寄存器
存放移位位数,例如在下面的指令中,AL寄存器
被左移一位,最高位被复制到了进位标志中,最低位被清零:
01251006 | B3 8F | mov al,10001111b | AL = 10001111b 01251008 | D0E3 | shl al,1 | CF = 1,AL = 00011110b
01251006 | B0 01 | mov al,10000000b | AL = 10000000b 01251008 | C0E0 02 | shl al,2 | CF = 0,AL = 00000000b
01251006 | B0 01 | mov al,10000000b | AL = 10000000b 01251008 | C0E0 01 | shl al,1 | CF = 1,AL = 00000000b
01251006 | B0 01 | mov al,10100000b | AL = 10100000b 01251008 | C0E0 03 | shl al,2 | CF = 0,AL = 10000000b
|
另外使用SHL指令还可以进行2的次幂
的高速乘法运算,任何操作数左移动N位,就相当于乘以2的N次方,如下例子:
01311002 | B0 05 | mov al,5 | AL 左移动1位 01311004 | D0E0 | shl al,1 | al*2=10
01311007 | B0 05 | mov al,5 | AL左移2位 01311009 | C0E0 02 | shl al,2 | al*4=20
01311007 | B0 05 | mov al,5 | AL左移3位 01311009 | C0E0 03 | shl al,3 | al*8=40
|
SHR指令: 对目标操作数执行逻辑右移(针对无符号数)
操作,移出的数据位用0代替,最低位被复制到CF进位标志
中,原来的进位标志位丢失.
0131100D | B0 01 | mov al,10001111b | AL = 10001111b 0131100F | D0E8 | shr al,1 | CF = 1,AL = 01000111b
0131100D | B0 01 | mov al,10001111b | AL = 10001111b 0131100F | D0E8 | shr al,2 | CF = 1,AL = 00100011b
|
另外任何无符号操作数逻辑右移N位,就相当于该操作数除以2的N次方
,如下例子:
01311012 | B2 20 | mov dl,20 | DL 右移1位 01311014 | D0EA | shr dl,1 | dl/2 = 10
01311012 | B2 20 | mov dl,20 | DL 右移2位 01311014 | D0EA | shr dl,2 | dl/4 = 5
|
MUL和IMUL指令分别进行有符号整数和无符号整数的乘法操作,MUL(无符号乘法)
指令有三种格式.
8位乘法: 计算AL寄存器
和BL寄存器
相乘,积数默认放在AX寄存器中,进位标志CF清零,因为AH高位等于零.
00111002 | B0 05 | mov al,5 | al = 5 00111004 | B3 10 | mov bl,10 | bl = 10 00111006 | F6E3 | mul bl | AX=50,CF=0
|
16位乘法: 将16操作数2000h和100h相乘,乘积高位在DX中,低位在AX中.CF=1因为乘机高半部分DX=0
0008100F | 66:B8 0020 | mov ax,2000 | ax=2000 00081013 | 66:BB 0001 | mov bx,100 | bx=100 00081017 | 66:F7E3 | mul bx | ax*bx
|
32位乘法: 将32操作数12345h和1000h相乘,得到64位乘积,其高位在EDX中,低位在EAX中.
0008101B | B8 45230100 | mov eax,12345 | 00081020 | BB 00100000 | mov ebx,1000 | 00081025 | F7E3 | mul ebx |
|
IF-ENDIF 伪指令: 32位汇编中支持决策伪指令,通过使用该伪指令可以节约判断跳转的时间,提高开发效率.
.code main PROC mov eax,100 mov ebx,200 .IF (eax == ebx) && (ebx == ebx) xor eax,eax xor ebx,ebx .ELSEIF (eax >= 100) || (ebx == ebx) add eax,100 add ebx,100 .ENDIF main ENDP END main
|
WHILE-ENDW(伪指令):
.data Count DWORD 10 SumNum DWORD 0
.code main PROC xor eax,eax .WHILE (eax < Count) add SumNum,1 inc eax .ENDW main ENDP END main
|
REPEAT-UNTIL(伪指令): 以下代码利用循环伪指令,完成了1-10相加.
.data Count DWORD 10 SumNum DWORD 0 .code main PROC xor eax,eax .REPEAT inc eax add SumNum,1 .UNTIL (eax >= Count) main ENDP END main
|
BREAK(伪指令): 以下是个死循环,当eax寄存器的值等于5时,则执行.break结束程序的运行.
.code main PROC mov eax,10 .while (1) dec eax .break .if(eax == 5) .endw ret main ENDP END main
|
CONTINUE(伪指令): 当EAX的值小于等于5时执行continue,否则执行inc ebx
,总循环数为10.
.code main PROC mov eax,0 mov ebx,0 .repeat inc eax .continue .if(eax <= 5) inc ebx .until (eax >= 10) ret main ENDP END main
|
FOR 字符替换(伪指令): 该伪指令并不是循环,而是分别将指定的指令批量的替换到程序中.
.code main PROC for num,<1,2,3> xor eax,eax add eax,DWORD PTR [num] endm ret main ENDP END main
|
FORC字串替换(伪指令): 该伪指令并不是循环,而是分别将指定的字串批量的替换到程序中.
.code main PROC forc code,<@#$%^&*()<>> BYTE "&code" endm ret main ENDP END main
|