汇编之循环语句

今天看了《加密与解密》循环语句部分,接下来将从do-while循环,while循环,for循环三个方面去学习循环的汇编。

0x01 do-while循环

do-while循环的流程是:先执行语句块,在进行表达式判断,当表达式为真时,在继续执行语句块。接下来先看一段C语言代码

 #include "stdafx.h"

    int main(int argc, char* argv[])
    {
        int nCount=0;
        do{
            printf("%d\r\n",nCount);
            nCount++;   
        }
            while(nCount<argc);   argc为整型,用来统计程序运行时发送给main函数的命令行参数的个数,在VS中默认值为1return 0;
    }

切到反汇编模式
汇编之循环语句_第1张图片
可以看到,先执行了输出语句和nCount的自增,然后比较nCount和argc的大小,若小于则循环,否则将线性向下执行。
下面是我写的汇编代码


 #include "stdafx.h"

    int main(int argc, char* argv[])
    {
            //int nCount=0;
            char *str="%d\r\n";
            _asm{
                          mov eax,0
        circle:           push eax
                          push str
                         call printf       //调用printf函数
                          add esp,8       //平衡栈
                          inc eax         //nCount自增,         
                        cmp eax,dword ptr [ebp+8]
                       jl circle             //if (nCount<argc),跳转到circle循环执行
                       xor eax,eax     //设置返回值为0
            }
    }

成功运行!
在IDA Pro里面识别do—while循环
汇编之循环语句_第2张图片汇编之循环语句_第3张图片

0x02 while循环

while循环的流程是:先进行表达式判断,在执行语句块,当表达式为真时,会继续执行语句块,示例如下

#include
void main()
{
      char *str="%d\n";
_asm{
                  mov eax,1             //i=1
                  mov ebx,0            //sum=0
circle:           cmp eax,100
                  jg   end
                 add ebx,1              //sum++
                 inc eax,1            //i++
                 jmp circle
end:
                 push ebx
                 push str
                 call printf
                 add esp,8
}
}

切入到反汇编:
汇编之循环语句_第4张图片
可以看到,先比较i与100的大小,若i<=100,则执行语句块,否则就直接输出sum。
下面是我写的汇编代码

#include<stdio.h>
void main()
{
      char *str="%d\n";
_asm{
                    mov eax,1             //i=1
                  mov ebx,0            //sum=0
circle:           cmp eax,100
                  jg   end
                 add ebx,1              //sum++
                  inc eax,1            //i++
                 jmp circle
end:
                  push ebx
                  push str
                  call printf
                 add esp,8
}
}

在IDA Pro里面识别while循环
汇编之循环语句_第5张图片汇编之循环语句_第6张图片
循环的特点是会向低地址跳转。while循环和do-while循环区别:
1.while循环使用的是jmp循环,while循环使用的是jxx汇编指令需要取反
2.while循环比do循环多一次if判断,因此性能上while循环不如do循环高,在Release版本中,编译器会把while循环优化成等价的do循环。

0x03 for循环

for语句由赋初值,循环条件,循环步长三条语句组成,示例如下:

  #include "stdafx.h"

    int main(int argc, char* argv[])
    {
        for(int nCount=0; nCount<argc;nCount++)
               {
                            printf("%d\r\n",nCount);
               }
                    return 0;
    }

切入到反汇编
汇编之循环语句_第7张图片
在这里可以看到,对nCount赋值以后,就跳到判断的位置,如果判断结果为真,就跳上去执行语句块
接下来是我写的汇编代码

   #include "stdafx.h"

    int main(int argc, char* argv[])
    {
          char *str="%d\r\n";
    _asm{
                mov eax,0   
                         jmp judge
    circle:      add eax,1
    judge:     cmp eax,dword ptr[ebp+8]
                                 jge circle
                          push eax
                          push str
                          call printf
                add esp,8
                xor eax,eax
    }
    }

在IDA Pro里面识别for循环
汇编之循环语句_第8张图片汇编之循环语句_第9张图片关于循环语句的学习就先到这里。

eax加1,可以有如下两种表示:

    inc eax
    add eax,1

复制代码
虽然功能一样,可还是有以下区别:
(1) 机器码长度不同,inc短,add长。(这不是关键)
(2)INC不改变标志位CF,而ADD则改变CF。(这点很关键。)
例如:

        number dw 0FFFFH,1234H,0,0,0
       表示的80位数1234FFFFH,希望给它加2。
        MOV SI,OFFSET NUMBER
         MOV CX,4              ;4个高位的字单元
        ADD WORD PTR [SI],2   ;最低位加2
L1:
         INC SI
         ADC WORD PTR [SI],0   ;把产生的进位加到高位
        LOOP L1

若把INC SI换成ADD SI,1就会出错。原因是 ADD WORD PTR [SI],2产生了CF,若用ADD SI,1就会把CF清0,从而后面的ADC就不能把前面的进位加上。

   dec eax
   sub eax,1

复制代码
eax减1,dec和sub的区别也和加1类似。

你可能感兴趣的:(#,汇编)