概述
汇编之位操作指令
- 前言
- 逻辑运算指令
- AND
- OR
- XOR
- AND、OR和XOR
- TEST
- NOT
- 逻辑运算指令应用实例
- 移位指令
- 逻辑左移指令SHL和算术左移指令SAL
- 逻辑右移指令SHR和算术右移指令SAR
- 逻辑移位
- 左移和右移
- 循环移位指令
- 循环左移指令ROL和循环右移指令ROR
- 带CF位的循环左移指令RCL和循环右移指令RCR
- 移位指令实例
前言
位运算的特点是运算单元是位,一个位的变化不会对旁边位产生影响。
逻辑运算指令
逻辑运算指令是位运算指令的子集,逻辑运算指的就是位运算指令中的与或非
ALU是算术逻辑单元,之前我们已经写了汇编之算术运算指令这篇博文,已经研究了“运算”,现在我们来研究“逻辑”。所谓的硬件控制,其实也就是控制这几个逻辑运算指令。
逻辑运算指令的通用格式是
AND/OR/XOR/TEST mem/reg,mem/reg/imm
(imm表示立即数寻址)
逻辑运算指令都是按位进行操作的,其中
NOT指令执行后不影响任何标志位,其他指令执行后,标志位CF和OF一定是0;而SF、ZF和PF位则根据运算结果设置;AF位无定义。
换句话说,5个逻辑运算指令中只有NOT不影响标志位
AND
常用于截取或屏蔽若干位二进制数
屏蔽——强行置0
如果要将一个数的第0,3,5位置零,只需要把这个数和1101 0110做AND即可
OR
可用于组合成某个字,或将某位置置1
XOR
同一个单元进行异或,相当于对单元清零
AND、OR和XOR
都是将结果回送给原操作数
TEST
TEST和AND的区别就是TEST的结果不回送,根据结果设置标志位。
想想
SUB-CMP
AND-TEST
是不是挺类似的?可以类比记忆
TEST常用于判断操作数的某位或某几位是“0”还是“1”
看一个例子
TEST AL,01H
TEST AL,80H
第一句,TEST AL,01H
可以用于判断最低位是否为0
如果最低位是0,那么结果全0,这时可以用零标志位ZF判断,如果ZF=1,说明结果等于0,也就是说AL的最低位是0
如果最低位是1,那么结果是0000 0001,这是零标志位ZF=0,我们看到零标志位ZF=0,就能知道AL的最低位是1
根据最低位的0或1,可判断这个数的奇偶性,所以TEST也有判断奇偶的功能。
第二句,TEST AL,80H
可以用来判断最高位是否为0
类似的,TEST AL,0110 0000可以用来判断第5,6位是不是都是0
如果要你判断1,2,3,5,7位是否都为1,那要怎么做呢?
判断是否都为0是很简单的,直接TEST AL,1010 1110
如果运算结束后ZF=0,那么就说明这些位置全都为0
但是如果要判断都为1,那就比较麻烦,得一个一个判断,先TEST AL,0000 0010,再……
还有一种方法是先取反,然后就变成了判断这些位是否都为0,就比较简单了。
总之,TEST是进行与运算,结果不回送,但根据结果设置标志位。所以可以使用TEST指令,通过观察标志位,判断操作位的某位或某几位是0还是1。
NOT
NOT不同于与或异或,它是单操作数指令。
NOT就是求反,可以与NEG对比一下,他俩有点点像,但更多的是不同,NEG是求补指令,只针对负数。
逻辑运算指令应用实例
MOV AL,1011 1111
AND AL,1111 1100
结果是1011 1100
MOV AL,0100 0011
OR AL,0010 0000
结果是0110 0011
这两句的作用是把AL的第五位置1
MOV AL,0100 0000
TEST AL,1010 1111
结果是全0,说明0,1,2,3,5,7位全部为0
(其实我觉得PPT第一条语句里的040H没必要写成040H,写成40H就行了,它又不是字母开头的,不知道为什么要在前面加0)
整个前三条语句是看DL中的第二位是否为1
但是其实想看DL中的第二位是否为1,直接把DL和0000 0100相TEST就行了,这里的NOT对于判断第二位没什么用,可能加在这是为了迷惑你吧。
TEST的下一步常常是跳转指令,跳转条件是标识位。
第四句,jz exit,是跳到exit的意思
注意汇编中exit不是什么特殊的!exit就是一个自定义的标号。
注意PPT里的是汇编语句,汇编语句中用二进制是需要加B的!
寄存器AX清零
测试两个数是否相等,也就是AX和0100 0010是否相等,相等的话跳转到MATCH
移位指令
移位指令统一的格式:
SAL/SHR/SAR/ROL/ROR/RCL/RCR/SHL reg/mem,1/CL
移位次数可以是1或者CL寄存器的值:为1时二进制数各个数位只移动移位;如果需要移位的次数大于1,必须将移位次数送CL寄存器,再执行移位指令。
设OPR为操作数,OPR可以是mem和reg
移位次数记为CNT
CNT大于一时,要先把CNT存在CL中,再执行SHL OPR,CL
条件标志位:
OF的值的解释有点不清楚,目前来看意思是:最后一次移位后的符号位与最后一次的前一次移位后的符号位不同,OF=1。也就是说,最后一次移位有没有使最高有效位(或者叫符号位)发生变化,如果变化了,那OF就等于1;如果没有变化,那么OF=1.
再提醒一下,计算机中存的都是补码。
没有强调是有/无符号数时,用算数或逻辑移动都行。
移出的位都进入CF
逻辑左移指令SHL和算术左移指令SAL
SHL SAL
L表示左移
H表示逻辑
A表示算数
当目的操作数为无符号数时,采用逻辑左移指令SHL;当目的操作数为有符号数时,采用算术左移指令SAL
算术左移和逻辑左移的规则是完全一样的,就是都在右边添0,相当于原数乘2。
算术左移,可能你会觉得有点奇怪,可以参考这个有效的左移
总之,算术左移和逻辑左移,基本就是一样的,而且都是可以实现乘2的功能,这个是确定的,你记着就行(也可以看上面的网址理解一下)
注意移出的高位进入CF
逻辑右移指令SHR和算术右移指令SAR
注意右移并不等同于除2,右移是比较复杂的,咱们在这里先不研究。
无符号数使用逻辑移位。
无符号数的右移就是补0
有符号数使用算术移位
有符号数分为正数和负数
正数:右移左边补0
负数:右移左边补1
总之就是补符号位的数。
注意移出的位进入CF
逻辑移位
逻辑移位无论左移右移都补0
左移和右移
算术左移和算术右移主要用来进行有符号数的倍增、减半;
逻辑左移和逻辑右移主要用来进行无符号数的倍增、减半。
带符号数的移位总是会让人有点迷茫,先记住这两句就行,这两句没错。
循环移位指令
循环移位可以用来做流水小灯
循环左移指令ROL和循环右移指令ROR
循环不带CF,循环的是目的操作数,只是移出的位在CF里也存一份
带CF位的循环左移指令RCL和循环右移指令RCR
带着CF一起循环
请注意带不带CF循环的区别。
移位指令实例
SAR:算术右移
把DI中的数据指向的内存单元中的一个字取出来,右移五次
DS:SI
DS是数据段寄存器
SI表示操作数的偏移地址
0F800→0F8000
因此真正的地址是0F8000+180A=0F980A
将0F980A中的内容取出,值为0064H
即0000 0000 0110 0100
算数右移,说明应该把他当成有符号数,符号位为0,移位补充的应该和符号位保持一致。右移五次后结果应该是0000 0000 0000 0011
也就是0003H
相当于100/32,余数不要,结果是3
SI=1450H=0001 0100 0101 0000
逻辑左移2位,结果为
0101 0001 0100 0000
即5140H
并且移出去的都是0,CF=0,移了两位,相当于原来的数×4
移位运算一定要化成二进制再移!看16进制你是看不出来的!
“AX中的内容循环左移8次,就还是原来的内容”
你看看你上面这句话说的多错!所以真的不能想当然。尤其是8位,16位,左移8位,寄存器16位,很容易就迷惑了!
一定要先把寄存器内容实实在在写出来
AX中的内容是0012H
也就是0000 0000 0001 0010
循环左移8次,得到
0001 0010 0000 0000
也就是1200H
再和BX相或或者相加,都能得到(AX)=1234H
注意因为是想要AX=1234H,所以AX应该放在前面,作为目的操作数。
例:求CX*9
可以
MOV AX,CX
MOV BX,CX
MOV CL,3
SAL AX,CL
ADD AX,BX
原理就是先乘8,再加1
那就等于乘9了
如果要求CX*8
MOV AX,CX
MOV CL,3
SAL AX,CL
当然你也可以一次一次的移动,
SAL AX,1
把这条语句重复3次。
注意SAL是算数左移,用来做有符号数的倍增
当然题里没明确是是有符号数,其实用两种都可以
最后
以上就是暴躁小熊猫为你收集整理的汇编之位操作指令前言逻辑运算指令移位指令循环移位指令的全部内容,希望文章能够帮你解决汇编之位操作指令前言逻辑运算指令移位指令循环移位指令所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复