无瑕黑心肠 发表于 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:,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:,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:,0x1         ; 比较tmp,1
   004032DB    0F85 07000000      jnz tmp_ASM.004032E8                     ; 判断(tmp = 1)
   004032E1    C745 FC 02000000   mov dword ptr ss:,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:,0x2         ; 比较tmp,2
   004032F1    0F85 07000000      jnz tmp_ASM.004032FE                     ; 如果真(tmp = 2)
   004032F7    C745 FC 03000000   mov dword ptr ss:,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:,0x3         ; 比较tmp,3
   00403307    0F85 0C000000      jnz tmp_ASM.00403319                     ; 如果(tmp = 3)
   0040330D    C745 FC 04000000   mov dword ptr ss:,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:,0x4         ; 比较tmp,4
   00403322    0F85 09000000      jnz tmp_ASM.00403331                     ; 判断循环首(tmp = 3)
   00403328    C745 FC 05000000   mov dword ptr ss:,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:,0x6         ; tmp = 6
   0040333D    837D FC 05         cmp dword ptr ss:,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:,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:,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:            ; 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:,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:,eax         ; tmp = eax(2)

伪代码:
           比较 tmp, 0x1
           初始化 eax 寄存器
           将 ZF 标志赋值给 al
           eax做"与"运算
           如果 结果是 0 则跳到 A, 否则不跳
           eax = 2
           跳到 B
   A:        eax = 3
   B:        tmp = 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:,0x0         ; 初始化变量tmp
   00403320    C745 FC 01000000mov dword ptr ss:,0x1         ; tmp = 1
   00403327    8B45 FC         mov eax,dword ptr ss:         ; 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:    ; 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:,eax         ; tmp = eax(2)

伪代码:
                   初始化变量 tmp(0)
                   tmp = 1
                   eax = tmp(将 tmp 作为多项选择的 "索引")
                   如果 eax < 1 (超出"多项选择"索引范围), 这里是条件成立既"跳"到错误提示并结束易语言程序, 不成立则继续执行
                   如果 eax < 5 (超出"多项选择"索引范围), 这里则是条件不成立程序"走"到错误提示并结束易语言程序, 成立跳到"正常"代码出
   错误:        调用错误提示CALL
   正常:        取得EIP的CALL
                   计算跳转地址(是编译器早已计算好跳转跳转偏移数组, 里面存储着跳到"多项选择"的那个索引位置执行代码,      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, 然后利用它加上预先计算好的"跳转偏移"数组的值来达到"多项选择"的目的. 本期主要是对易语言的流程控制进行详细的分析, 不含有太多技术成. 主要是记录学习的总结.

无瑕黑心肠 发表于 2016-6-14 15:09

YsGer 发表于 2016-6-14 13:34
我用前辈的置入代码中的参数用易语言转化为文本数据输出是乱码!还请前辈赐教

当然了, 因为这时汇编代码的十六进制格式. 转为文本是看不到信息的. 除非特殊情况(文本常量)

无瑕黑心肠 发表于 2016-6-14 15:07

YsGer 发表于 2016-6-14 13:29
前辈你好,打扰一下请问下源代码中的"置入代码"命令参数中的那个字节集在汇编中是不变的吗?与之对应的汇编 ...

1.对它是不变的.
2.对应的汇编代码是NOP(90)

pk8900 发表于 2016-6-14 10:22

学习了,有时间研究一下。

conosc 发表于 2016-6-14 10:32

研究下,感谢楼主,本菜鸟晕乎乎的。

猪肉供应商 发表于 2016-6-14 11:29

来学习学习

cwz 发表于 2016-6-14 11:32

谢谢分享技术。

sunfly 发表于 2016-6-14 11:48

收藏研究 多谢

jackfang 发表于 2016-6-14 12:08

学习下 谢谢分享

帝天 发表于 2016-6-14 12:13

分析的不错。。。不早点弄出来。想当年我一个一个写一个一个对。。。

YsGer 发表于 2016-6-14 13:29

本帖最后由 YsGer 于 2016-6-14 13:49 编辑

前辈你好,打扰一下请问下源代码中的"置入代码"命令参数中的那个字节集在汇编中是不变的吗?与之对应的汇编代码是?

YsGer 发表于 2016-6-14 13:34

本帖最后由 YsGer 于 2016-6-14 13:49 编辑

我用前辈的置入代码中的参数用易语言转化为文本数据输出是乱码!还请前辈赐教
页: [1] 2
查看完整版本: 详解易语言流程控制极其反汇编