技巧“c”
一、逻辑运算符 1、或运算(c语言中的? ||? )? 条件真和假 :? 非零为真,零为假 ++为+(假假为假) 截断原理? if(a || b) 判断前面是否为真,把认为可能行大的放在最前面 c = i || j; if (c) {} 以汇编指令去看 /* 009E1014 |. C745 FC 330>mov [local.1],0x33 009E1028 |. 837D F4 00 cmp [local.3],0x0? ? ? ?// 如果为0不跳转, 则继续与第二个参数比较? (假假为假) 009E102C |. 75 09 jnz short 汇编.009E1037 ? */
2、按位或(c语言中的 |) 0x33 ==>>? ?00 11 00 11 | 0x66? ? ? ? ?+ 01 10 01 10 ? ? =? 0x77 ==>? = 01? 11 01 11? ?(假假为假)? /* 009E1046 |. 8B4D FC mov ecx,[local.1] ; msvcr100.72AD266D */ 汇编是使用 or 指令? ? 3、与运算 ==>>逻辑与(c语言中的 && ) 真真为真 c = a && b? ? //? 自己的代码? a 认为 是假 放在前面? ?。判断前面是否为假,把认为可能行大的放在最前面 if ( c ){} 截断原理 ==>>按位与 (c语言中的 &) 0x33 ==>>? ? 00 11 00 11 & 0x66? ? ? ? ?+ 01 10 01 10 ? ? =? 0x22 ==>? ?=? 00 10 0010? (真真为真)? /* 4、非运算 (1)逻辑取反(c语言中的 ! ) 假变真, 真变假 sete(setz)? ? ? ?取ZF标志位的值保存 setne(setnz)? ?将ZF标志位的值取反保存 ? (2)? 按位取反(c语言中的 ~ ) ? ? c语言代码中的汇编指令 #include <cstdio> /*
*/ __asm mov eax,eax
? ? ?
} NOT 指令 ? 5、异或运算 (1)按位异或(c语言中的^) 1^1 = 0,?0^0 = 0? ,相同为0 0^1 = 1,1^0 = 1?,? ?不同为1 eg :? ?1101 ? ?^ 0110 ? = 1011??
? ? ? ?? 经典练习题: (1)不借助第三个变量,将两个数交换(数值大的数会有问题,溢出) int a = 5,b = 7; a = a+b;? ?// a = 12 b = a - b;? // b = 12 - 7 = 5 a = a - b;? // a = 12 - 5 = 7 (2)用异或计算高效
? 逻辑运算指令总结: (1) or :? 按位或运算,假假为假(有1为1,全0为0) 如:101100 |? ?110101 =? 111101 (2)? and : 按位与运算,真真为真(有0为0,全1为1) 如: 101100 &? ?110101 =? ?100100 (3) Not: 取反运算 如:not? 1011 ? =? ?0100 (4)? xor : 异或运算(相同为0,不同为1) 如 :? ?101100 ^? 110101 =? 011001
二、字符操作相关指令 1、字符串的比较函数 strcmp 反汇编分析: 2、REPNE和SCASB指令 (1)SCASB指令: SCASB编译后: SCASB? BTYP PTR ES:[EDI]? char? ?s1[0]? ?byte 1?? //// SCASW WORD PTR [EDI]? ? ? short? s1[0]? word? 2 //// SCASD? DWORD PTR [EDI]? ?int? ? ? s1[0]? ?dword 4 相当于 cmp byte prt [edi],al ? 对标志位的影响相当于SUB指令,同时还会修改寄存器EDI的值 如果标志位DF为0, 则? inc? EDI 否则,dec EDI
(2)REPNE指令(连续执行) repnz scasb 编译后 :repne scas bype ptr es:[edi] 当ecx != 0 并且 ZF = 0 时,重复执行后边的指令?scas bype ptr es:[edi] 每执行一? 次EDI的值加1,ECX的值减1
? //? ?此汇编代码 是 获取字符的长度? (主要是实现逻辑思想) repne 和 repnz 是同一条指令的不同助记符 3、REPE/REPZ和CMPSB,CMPSW,CMPSD指令 (1)CMPS cmps byte ptr [edi],byte ptr [esi] cmps word ptr [edi],byte ptr [esi] cmps dword ptr [edi],byte ptr [esi] 对标志位的影响相当于sub指令, 同时还会修改寄存器EDI和ESI的值 如果标志DF为0, 则EDI,ESI按相对于大小(byte,word,dword) 递增 如果标志DF为1, 则EDI,ESI按相对于大小(byte word dword) 递减 (2)REPE/REPZ repe/repz cmpsb 当ecx!=0并且zf = 1时, 重复执行后面的指令 每执行一次ecx的值减1 (3)实例运用 比较串是否相等
(4)汇编编写字符串比较函数 (1)asm_strcmp 函数 _declspec(naked)? 告诉编译器用纯汇编方式编译函数, 不自动添加 寄存器保护和堆栈平衡代码 (2)STD/CLD指令(DF方向标志位相关) std? ?df = 1 cld? ?df =? 0 ?三、串存储和串的加载指令 (1)串存储指令STOSB、STOSW、STOSD STOSB? STOS BYTE PTR [EDI] STOSW? STOS WORD PTR [EDI] STOSD? STOS? DWORD PTR [EDI] 相当于: mov byte? ? ptr [edi],al mov word? ?ptr [edi],ax mov dword ptr [edi],eax ? ? rep stosb? ? rep stos byte ptr [edi] ? ?用al 的值 填充byte ptr [edi],每次ecx值减1,edi加1 定位main()函数位置的步骤: 第一步:打开程序, 程序启动后停在这里,直接jmp跳转 第二步:jmp跳转跟随之后, 找到call? dword ptr [<xxxxx.exit>]退出的代码的位置 第三步:call dword ptr [<xxxxx.exit >] 前一个call就是main函数。 (2) 串载入指令LODSB,LODSW,LODSD lodsb lods byte ptr [esi] lodsw lods woedptr [esi] lodsd lods dword ptr [esi]
rep lodsb ==>> rep lods byte ptr [esi] 用byte ptr [esi]? 的值, 填充al, 每次ecx值减1 , esi的值加1 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |