好友
阅读权限25
听众
最后登录1970-1-1
|
无瑕黑心肠
发表于 2016-6-14 09:43
易语言基本的流程控制语句:
OD中易语言的流程控制的反汇编代码:
004032B6 55 push ebp ; 堆栈平衡操作
004032B7 8BEC mov ebp,esp ; 堆栈平衡操作
004032B9 81EC 08000000 sub esp,0x8 ; 堆栈平衡操作
004032BF C745 FC 00000000 mov dword ptr ss:[ebp-0x4],0x0 ; 初始化变量tmp
004032C6 90 nop
004032C7 90 nop
004032C8 90 nop
004032C9 90 nop
004032CA 90 nop
004032CB C745 FC 01000000 mov dword ptr ss:[ebp-0x4],0x1 ; tmp = 1
004032D2 90 nop
004032D3 90 nop
004032D4 90 nop
004032D5 90 nop
004032D6 90 nop
004032D7 837D FC 01 cmp dword ptr ss:[ebp-0x4],0x1 ; 比较tmp,1
004032DB 0F85 07000000 jnz tmp_ASM.004032E8 ; 判断(tmp = 1)
004032E1 C745 FC 02000000 mov dword ptr ss:[ebp-0x4],0x2 ; tmp = 2
004032E8 90 nop
004032E9 90 nop
004032EA 90 nop
004032EB 90 nop
004032EC 90 nop
004032ED 837D FC 02 cmp dword ptr ss:[ebp-0x4],0x2 ; 比较tmp,2
004032F1 0F85 07000000 jnz tmp_ASM.004032FE ; 如果真(tmp = 2)
004032F7 C745 FC 03000000 mov dword ptr ss:[ebp-0x4],0x3 ; tmp = 3
004032FE 90 nop
004032FF 90 nop
00403300 90 nop
00403301 90 nop
00403302 90 nop
00403303 837D FC 03 cmp dword ptr ss:[ebp-0x4],0x3 ; 比较tmp,3
00403307 0F85 0C000000 jnz tmp_ASM.00403319 ; 如果(tmp = 3)
0040330D C745 FC 04000000 mov dword ptr ss:[ebp-0x4],0x4 ; tmp = 4
00403314 E9 00000000 jmp tmp_ASM.00403319 ; 易语言如果语句是JNZ...JMP结构
00403319 90 nop
0040331A 90 nop
0040331B 90 nop
0040331C 90 nop
0040331D 90 nop
0040331E 837D FC 04 cmp dword ptr ss:[ebp-0x4],0x4 ; 比较tmp,4
00403322 0F85 09000000 jnz tmp_ASM.00403331 ; 判断循环首(tmp = 3)
00403328 C745 FC 05000000 mov dword ptr ss:[ebp-0x4],0x5 ; tmp = 5
0040332F ^ EB ED jmp short tmp_ASM.0040331E
00403331 90 nop
00403332 90 nop
00403333 90 nop
00403334 90 nop
00403335 90 nop
00403336 C745 FC 06000000 mov dword ptr ss:[ebp-0x4],0x6 ; tmp = 6
0040333D 837D FC 05 cmp dword ptr ss:[ebp-0x4],0x5 ; 比较tmp,5
00403341 ^ 74 F3 je short tmp_ASM.00403336 ; 循环判断尾(tmp = 5)
00403343 90 nop ; 可以看出易语言的循环判断尾是je结构
00403344 90 nop
00403345 90 nop
00403346 90 nop
00403347 90 nop
00403348 33C9 xor ecx,ecx ; ecx置0 (计次循环首的次数)
0040334A 41 inc ecx ; ecx++
0040334B 51 push ecx ; 压入ecx(相当于备份)
0040334C 83F9 01 cmp ecx,0x1 ; 比较ecx,1
0040334F 0F8F 0A000000 jg tmp_ASM.0040335F ; ecx > 循环次数(1)时跳出 等于不算
00403355 C745 FC 07000000 mov dword ptr ss:[ebp-0x4],0x7 ; tmp = 7
0040335C 59 pop ecx ; 弹出ecx(相当于还原)
0040335D ^ EB EB jmp short tmp_ASM.0040334A
0040335F 83C4 04 add esp,0x4 ; 堆栈平衡操作, 因为跳之前压入了ecx, 跳出来没用执行到弹出指令, 所以要平衡堆栈
00403362 90 nop
00403363 90 nop
00403364 90 nop
00403365 90 nop
00403366 90 nop
00403367 B9 01000000 mov ecx,0x1 ; ecx = 1
0040336C 51 push ecx ; 压入ecx(相当于备份)
0040336D 83F9 02 cmp ecx,0x2 ; 比较ecx,2
00403370 0F8F 0B000000 jg tmp_ASM.00403381 ; ecx > 循环次数(2)时跳出 等于不算
00403376 C745 FC 08000000 mov dword ptr ss:[ebp-0x4],0x8 ; tmp = 8
0040337D 59 pop ecx ; 弹出ecx(相当于还原)
0040337E 41 inc ecx ; ecx++
0040337F ^ EB EB jmp short tmp_ASM.0040336C
00403381 83C4 04 add esp,0x4 ; 堆栈平衡操作, 因为跳之前压入了ecx, 跳出来没用执行到弹出指令, 所以要平衡堆栈
00403384 90 nop
00403385 90 nop
00403386 90 nop
00403387 90 nop
00403388 90 nop
00403389 BB 06000000 mov ebx,0x6
0040338E E8 1BFFFFFF call tmp_ASM.004032AE
00403393 68 01030080 push 0x80000301
00403398 6A 00 push 0x0
0040339A 68 00000000 push 0x0
0040339F 68 01030080 push 0x80000301
004033A4 6A 00 push 0x0
004033A6 FF75 FC push dword ptr ss:[ebp-0x4] ; tmp_ASM.004032AA
004033A9 68 04000000 push 0x4
004033AE BB 00030000 mov ebx,0x300
004033B3 E8 58000000 call tmp_ASM.00403410 ; 弹出信息框显示 tmp 的值
004033B8 83C4 34 add esp,0x34
004033BB 8BE5 mov esp,ebp
004033BD 5D pop ebp ; tmp_ASM.004032AA
004033BE C3 retn
易语言的"选择"命令:
OD中易语言的"选择"命令的反汇编代码:
004032D7 837D FC 01 cmp dword ptr ss:[ebp-0x4],0x1 ; 比较tmp,1
004032DB B8 00000000 mov eax,0x0 ; eax = 0
004032E0 0F94C0 sete al ; al = ZF(详细解释: 将ZF标志位的值赋予al)
004032E3 85C0 test eax,eax ; eax & eax
004032E5 0F84 0A000000 je tmp_ASM.004032F5 ; eax != 0,条件不成立(不跳)
004032EB B8 02000000 mov eax,0x2 ; eax = 2
004032F0 E9 05000000 jmp tmp_ASM.004032FA ; 跳到004032F5
004032F5 B8 03000000 mov eax,0x3 ; eax = 3
004032FA 8945 FC mov dword ptr ss:[ebp-0x4],eax ; tmp = eax(2)
伪代码:
比较 tmp, 0x1
初始化 eax 寄存器
将 ZF 标志赋值给 al
eax做"与"运算
如果 结果是 0 则跳到 A, 否则不跳
eax = 2
跳到 B
A: eax = 3
B: tmp = eax ([eax] = 2)
易语言的"多项选择"命令:
OD中易语言的"多项选择"命令的反汇编代码:
00403310 55 push ebp ; 堆栈平衡操作
00403311 8BEC mov ebp,esp ; 堆栈平衡操作
00403313 81EC 08000000 sub esp,0x8 ; 堆栈平衡操作
00403319 C745 FC 00000000mov dword ptr ss:[ebp-0x4],0x0 ; 初始化变量tmp
00403320 C745 FC 01000000mov dword ptr ss:[ebp-0x4],0x1 ; tmp = 1
00403327 8B45 FC mov eax,dword ptr ss:[ebp-0x4] ; eax = tmp(以tmp作为"多项选择"的索引)
0040332A 83F8 01 cmp eax,0x1 ; 比较eax,1
0040332D 7C 05 jl short tmp2_ASM.00403334 ; 如果 eax < 1 则跳, 等于不算
0040332F 83F8 05 cmp eax,0x5 ; 比较eax,5
00403332 7C 0D jl short tmp2_ASM.00403341 ; 如果 eax < 5 则跳, 等于不算
00403334 68 09000000 push 0x9 ; 压入易语言专属的错误标识
00403339 E8 CB000000 call tmp2_ASM.00403409 ; 提示"多项选择"索引超出了范围, 这个防范做的不错
0040333E 83C4 04 add esp,0x4 ; 报错后的堆栈平衡操作
00403341 48 dec eax ; eax--(把eax-1, 好像索引转正一样( 其他语言的数组索引都是从0开始)
00403342 E8 00000000 call tmp2_ASM.00403347 ; CALL 0(感觉像花指令...难道是为了取得ESP?)
00403347 5B pop ebx ; 弹出esp的值给ebx(取得EIP的方法)
00403348 031C85 CB304000 add ebx,dword ptr ds:[eax*4+0x4030CB] ; ebx += 0xa(计算跳转的)
0040334F FFE3 jmp ebx ; 跳到计算后的ebx的索引, 也就是第一个
00403351 B8 02000000 mov eax,0x2 ; eax = 2
00403356 E9 19000000 jmp tmp2_ASM.00403374 ; 跳出"多项选择"
0040335B B8 03000000 mov eax,0x3
00403360 E9 0F000000 jmp tmp2_ASM.00403374
00403365 B8 04000000 mov eax,0x4
0040336A E9 05000000 jmp tmp2_ASM.00403374
0040336F B8 05000000 mov eax,0x5
00403374 8945 FC mov dword ptr ss:[ebp-0x4],eax ; tmp = eax(2)
伪代码:
初始化变量 tmp(0)
tmp = 1
eax = tmp(将 tmp 作为多项选择的 "索引")
如果 eax < 1 (超出"多项选择"索引范围), 这里是条件成立既"跳"到错误提示并结束易语言程序, 不成立则继续执行
如果 eax < 5 (超出"多项选择"索引范围), 这里则是条件不成立程序"走"到错误提示并结束易语言程序, 成立跳到"正常"代码出
错误: 调用错误提示CALL
正常: 取得EIP的CALL
计算跳转地址([eax*4+0x4030CB]是编译器早已计算好跳转跳转偏移数组, 里面存储着跳到"多项选择"的那个索引位置执行代码, eax就是数组索引, 4030CB也是编译器预计算好的固定值)
跳到索引 A
A: eax = 2
跳到"多项选择"的"末尾"
B: eax = 3
跳到"多项选择"的"末尾"
C: eax = 4
跳到"多项选择"的"末尾"
D: eax = 5
末尾: tmp = eax(2)
总结:
初学时看易语言的视频, 讲师说"判断"命令比"如果"、"如果真"好, 现在一看, 感觉还是一个样子, 只是"判断"编译时会优化一下(判断后只有一个条件成立的地方有代码, 另一个条件成立的地方没用代码编译器就会省略JMP指令), 而"如果"不会进行省略. 像是"判断循环"、"计次循环"、"变量循环"这些都是很类似的循环指令, 只不过是小小不同, 掌握一个基本了解其他循环了. 还有易语言的"选择"命令, 其实也和"判断"、"如果"命令差不多的, 只不过会出现一个新的指令"SETE"(将ZF标志位的值赋予指定寄存器), 让人觉得不同罢了. 不过值得一提的是易语言的"多项选择"命令, 它会预先计算好跳转的地址, 例如文中的"4030CB", 还有具体"选择"索引的"跳转偏移"数组(文中的"[eax*4+0x4030CB]"), 而且它还巧妙的利用"call tmp2_ASM.00403347"取得了当前的EIP, 然后利用它加上预先计算好的"跳转偏移"数组的值来达到"多项选择"的目的. 本期主要是对易语言的流程控制进行详细的分析, 不含有太多技术成. 主要是记录学习的总结.
|
免费评分
-
查看全部评分
本帖被以下淘专辑推荐:
- · 学习及教程|主题: 1126, 订阅: 1118
|