学 Win32 汇编[22] - 逻辑运算指令: AND、OR、XOR、NOT、TEST
AND: 逻辑与
;该指令会置 CF=OF=0; 其结果影响 SF、ZF、PF;指令格式:AND r/m, r/m/i; Test22_1.asm - 使用 AND 运算将一个数的第二、四位清零.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain proc? mov al, 00001111b? and al, 11110101b ? PrintHex al ;05 - 00000101b? retmain endpend main; Test22_2.asm - 使用 AND 运算将字母转大写.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? szText db 'Delphi', 0.codemain proc? lea esi, szText? mov ecx, lengthof szText - 1@@: and byte ptr [esi], 11011111b ;大写字母和小写字母只有第五位不同? inc esi? loop @B? PrintString szText ;DELPHI? retmain endpend main
OR: 逻辑或
;该指令会置 CF=OF=0; 其结果影响 SF、ZF、PF;指令格式:OR r/m, r/m/i; Test22_3.asm - 使用 OR 运算确保一个数的第二、四位是 1.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain proc? mov al, 11110001b? or al, 00001010b ? PrintHex al ;FB - 11111011b? retmain endpend main; Test22_4.asm - 使用 OR 运算将字母转小写.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? szText db 'Delphi', 0.codemain proc? lea esi, szText? mov ecx, lengthof szText - 1@@: or byte ptr [esi], 00100000b ;大写字母和小写字母只有第五位不同? inc esi? loop @B? PrintString szText ;delphi? retmain endpend main
XOR: 逻辑异或
;该指令会置 CF=OF=0; 其结果影响 SF、ZF、PF;指令格式:XOR r/m, r/m/i; Test22_5.asm - 两次和一个相同的数 XOR 恢复到原来的数.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain proc? mov eax, 12345? xor eax, 88888888? PrintDec eax? ;88892929? xor eax, 88888888? PrintDec eax? ;12345? retmain endpend main; Test22_6.asm - 使用 XOR 加密与解密字符串.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? szText db 'Hello World!', 0.codemain proc ;加密? lea esi, szText? mov ecx, lengthof szText - 1@@: xor byte ptr [esi], 123 ;使用 123 做密码? inc esi? loop @B? PrintString szText? ;显示乱码? ;解密? lea esi, szText? mov ecx, lengthof szText - 1@@: xor byte ptr [esi], 123? inc esi? loop @B? PrintString szText? ;Hello World!? retmain endpend main
NOT: 逻辑取反
;该指令不影响 EFlags;指令格式:NOT r/m; Test22_7.asm - 使用 NOT 加密与解密字符串.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? szText db 'Hello World!', 0.codemain proc ;加密? lea esi, szText? mov ecx, lengthof szText - 1@@: not byte ptr [esi]? inc esi? loop @B? PrintString szText ;显示乱码? ;解密? lea esi, szText? mov ecx, lengthof szText - 1@@: not byte ptr [esi]? inc esi? loop @B? PrintString szText ;Hello World!? retmain endpend main
TEST: 测试逻辑与
;该指令会置 CF=OF=0; 其结果影响 SF、ZF、PF;指令格式:TEST r/m, r/m/i;TEST 同 AND, 但它不修改运算数, 只改变标志寄存器; 也就是尝试 AND 的结果;常用到它对 ZF 的影响(结果为0时ZF=1);TEST 之后常常跟着条件跳转指令 JZ、JNZ; Test22_8.asm - 观察 TEST 之后的零标志位(ZF).386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain proc ;判断字母 A 二进制(01000001)的其最后一位是否是 0, 如果是 0 那么 ZF=1? mov al, 'A'? test al, 00000001b? lahf? PrintHex ah ;02 - 00000010b (ZF=0)? ;判断字母 B 二进制(01000010)的其最后一位是否是 0, 如果是 0 那么 ZF=1? mov al, 'B'? test al, 00000001b? lahf? PrintHex ah ;46 - 01000110b (ZF=1)? ;判断 ecx 是否为空? mov ecx, 1? test ecx, ecx? lahf? PrintHex ah ;06 - 00000010b (ZF=0, 不为空)? ? xor ecx, ecx? test ecx, ecx? lahf? PrintHex ah ;06 - 01000110b (ZF=1, 为空)? retmain endpend main; Test22_9.asm - 判断字符串中每个字符的二进制位的最后一位是 1 还是 0.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? szText db 'Delphi', 0.codemain proc ;清空两个寄存器用于计数? xor eax, eax? xor edx, edx? ? lea esi, szText? ? ? ? ;字符串地址? mov ecx, lengthof szText - 1 ;字符串长度L1: test byte ptr [esi], 00000001b ;循环测试每个字符的最后一位是 1 还是 0? jz L2 ;如果是 0 则跳到 L2 给 edx+1? inc eax ;反之给 eax+1? jmp L3L2: inc edxL3: inc esi? loop L1? ? PrintDec eax ;2 - 这是最后一位是 1 的字符的个数: e、i? PrintDec edx ;4 - 这是最后一位是 0 的字符的个数: D、l、p、h? retmain endpend main