Assembly 布尔型按位运算
有四个普遍的布尔型运算符,它们是:AND,OR,XOR和NOT。真值表展示了每一个可能的操作数得到的运算结果。
AND运算符
两个比特位的AND运算结果只有当这两位都是1时才为1,否则结果就为0,就像真值表3.1展示的一样。
处理器支持这些运算指令对数据的所有位平等地进行独立的运算。例如:如果对AL和BL里的内容进行AND运算,那么基本的AND运算将应用于在这两个寄存器里的8对比特位中的每一对,像图3.2 展示的一样。下面是一个代码例子:
1 mov ax, 0C123H
2 and ax, 82F6H ; ax = 8022H
2 and ax, 82F6H ; ax = 8022H
OR运算符
两个比特位的包含OR运算结果只有当这两位都是0时才为0,否则结果就为1,就像真值表3.2展示的一样。下面是一个代码例子:
1 mov ax, 0C123H
2 xor ax, 0E831H ; ax = E933H
2 xor ax, 0E831H ; ax = E933H
XOR运算
两个比特位的互斥XOR运算结果只有当这两位相等时为0,否则结果就为1,就像真值表3.3展示的一样。下面是一个代码例子:
1 mov ax, 0C123H
2 xor ax, 0E831H ; ax = 2912H
2 xor ax, 0E831H ; ax = 2912H
NOT运算
NOT运算符是一元运算符(也就是说,它只对一个操作数进行运算,而不像二元运算符,如:AND)。一个比特位的NOT运算结果是这个位值的相反数,像真值表3.4展示的一样。下面是一个代码例子:
1 mov ax, 0C123H
2 not ax ; ax = 3EDCH
2 not ax ; ax = 3EDCH
注意,NOT能得到一个数的补码。与其它按位运算不同的是,NOT指令并不修改在FLAGS寄存器里的任何一位。
TEST指令
TEST指令执行一次AND运算,但是并不储存结果。它会基于可能的结果对FLAGS寄存器进行设置(非常像CMP指令执行了一次减法操作但是只是设置了FLAGS)。例如:如果结果是0,那么ZF就被置位了。
位操作的应用
位操作对于操纵数据单个位而不修改其它位来说是非常有用的。表3.5展示了这些操作的三个普遍的应用。下面是一些实现了这些想法的代码例子。
AND运算还可以用来得到除以2的几次方之后的余数。要得到除以数2i之后的余数,只需对这个数和等于2i -1的掩码进行AND运算。这个掩码从位0到位2i - 1都为1,也就是这些位包含了余数。AND运算的结果将保留这些位,而将其它位输出为0。下面是一个得到100除以16的商和余数的代码小片断。
使用CL寄存器,就使得修改数据中的任何一位变得有可能。下面是一个对EAX任意比特位置位(开启)的例子。需要置位的比特位储存在BH中。
求反任意一个比特位的代码留给了读者,做为一个习题。在一个80x86程序中看到这个莫名其妙的指令是很平常的:
xor eax, eax ; eax = 0
一个数字与自己进行XOR运算,其结果总是0。这条指令被使用是因为它产生的机器代码比功能相同的MOV指令要少。