[3] 以逆向的角度来看循环语句——do、while、for的比较

1. do循环

​ 先执行循环体,后比较判断

#include <stdio.h>
int main(int argc, char* argv[]) {
int sum = 0;
int i = 0;
do {
sum += i;
i++;
}
while(i <= argc);
return sum;
}

汇编标识:

;x86_vs
00401000 push ebp
00401001 mov ebp, esp
00401003 sub esp, 8
00401006 mov dword ptr [ebp-8], 0 ;sum=0
0040100D mov dword ptr [ebp-4], 0 ;i=0
{
00401014 mov eax, [ebp-8] ;do_while语句块代码
00401017 add eax, [ebp-4]
0040101A mov [ebp-8], eax ;sum+=i
0040101D mov ecx, [ebp-4]
00401020 add ecx, 1
00401023 mov [ebp-4], ecx ;i+=1
}00401026 mov edx, [ebp-4]
00401029 cmp edx, [ebp+8]
0040102C jle short loc_401014 ;如果i<=argc,跳转到do_while语句块代码
0040102E mov eax, [ebp-8] ;do_while结束代码块
00401031 mov esp, ebp
00401033 pop ebp
00401034 retn ;x86_gcc
00401510 push ebp
00401511 mov ebp, esp
00401513 and esp, 0FFFFFFF0h
00401516 sub esp, 10h
00401519 call ___main
0040151E mov dword ptr [esp+0Ch], 0 ;sum=0
00401526 mov dword ptr [esp+8], 0 ;i=0
{
0040152E mov eax, [esp+8] ;do_while语句块代码
00401532 add [esp+0Ch], eax ;sum+=i
00401536 add dword ptr [esp+8], 1 ;i+=1
0040153B mov eax, [esp+8]
0040153F cmp eax, [ebp+8]
00401542 jg short loc_401546 ;如果i>argc,跳转到do_while结束代码块
}
00401544 jmp short loc_40152E ;跳转到do_while语句块代码
00401546 mov eax, [esp+0Ch] ;do_while结束代码块

逆向总结:

​ x86_vs:while语句的比较数是相同的

{
DO_WHILE语句代码块
...
}
执行影响标志位指令
JXX跳转到DO_WHILE语句代码块

​ x86_gcc:while语句的比较数是相反的

{
DO_WHILE语句代码块
执行影响标志位指令
JXX跳转到DO_WHILE结束代码块
...
}
跳转到DO_WHILE语句代码块
DO_WHILE结束代码块

2. while循环:先比较判断,后执行循环体

#include <stdio.h>
int main(int argc, char* argv[]) {
int sum = 0;
int i = 0;
while(i <= argc) {
sum += i;
i++;
}
return sum;
}

汇编标识:

00401000  push    ebp
00401001 mov ebp, esp
00401003 sub esp, 8
00401006 mov dword ptr [ebp-8], 0 ;sum=0
0040100D mov dword ptr [ebp-4], 0 ;i=0
{
00401014 mov eax, [ebp-4] ;while语句代码块
00401017 cmp eax, [ebp+8]
0040101A jg short loc_401030 ;如果i>argc,则跳转到while结束代码块
0040101C mov ecx, [ebp-8]
0040101F add ecx, [ebp-4]
00401022 mov [ebp-8], ecx ;sum+=i
00401025 mov edx, [ebp-4]
00401028 add edx, 1
0040102B mov [ebp-4], edx ;i+=1
}
0040102E jmp short loc_401014 ;跳转到while语句代码块
00401030 mov eax, [ebp-8] ;while结束代码块

注意:

​ while循环结构中使用了两次跳转指令完成循环,因为多使用了一次跳转指令,所以while循环比do循环效率低一些

​ while循环结构很可能被优化成do循环结构,被转换后的while结构需要检查是否可以被成功执行一次,通常会被嵌套在if单分支结构中

逆向总结:

{
while语句代码块
执行影响标志位指令
JXX跳转到while结束代码块
...
}
JMP跳转到while语句代码块
while结束代码块

3. for循环:先初始化,再比较判断,最后执行循环体

#include <stdio.h>
int main(int argc, char* argv[]) {
int sum = 0;
for (int i = 0; i <= argc ; i++) {
sum += i;
}
return sum;
}

汇编标识:

00401006  mov     dword ptr [ebp-8], 0         ;sum=0
{
0040100D mov dword ptr [ebp-4], 0 ;赋初值语句代码块,i=0
}
00401014 jmp short loc_40101F ;跳转到for语句代码块
{
00401016 mov eax, [ebp-4] ;步长语句代码块
00401019 add eax, 1
0040101C mov [ebp-4], eax ;i+=1
}
{
0040101F mov ecx, [ebp-4] ;for语句代码块
00401022 cmp ecx, [ebp+8]
00401025 jg short loc_401032 ;如果i>argc,则跳转到for结束语句块
00401027 mov edx, [ebp-8]
0040102A add edx, [ebp-4]
0040102D mov [ebp-8], edx ;sum+=i}
00401030 jmp short loc_401016 ;跳转到步长语句代码块
00401032 mov eax, [ebp-8] ;for结束语句块

逆向总结:

赋初值语句代码块
JMP跳转到for语句代码块
{
步长语句代码块
...
}
{
for语句代码块
执行影响标志位的指令
JXX跳转到for结束语句块
...
}
JMP跳转到步长语句代码块
for结束语句块

​ 计数器变量被赋初值后,利用jmp跳过第一次步长计算。然后,通过3个跳转指令还原for循环的各个组成部分:

​ 1)第一个jmp指令之前的代码为初始化部分;

​ 2)从第一个jmp指令到循环条件比较处之间的代码为步长计算部分;

​ 3)在条件跳转指令jxx之后寻找向上跳转的jmp指令,且其目标是到步长计算的位置,在jxx和这个jmp指令之间的代码即为循环语句块

4. 三种循环结构的效率比较

Release优化

​ 1)do循环效率最高

​ 2)while循环执行两次JMP跳转,效率低于do循环,可将其优化为if嵌套的do循环提高效率

int LoopWhile(int count){
int sum = 0;
int i = 0; if(count >= 0){
do {
sum += i;
i++;
}
while(i <= count)
}
return sum;
}

​ 3)for循环执行三次JMP跳转,效率最低,可将其优化为if嵌套的do循环提高效率

[3] 以逆向的角度来看循环语句——do、while、for的比较的更多相关文章

  1. Python学习【第五篇】循环语句

    Python循环语句 接下来将介绍Python的循环语句,程序在一般情况下是按顺序执行的. 编程语言提供了各种控制结构,允许更复杂的执行路径. 循环语句允许我们执行一个语句或语句组多次. Python ...

  2. 高性能JavaScript 循环语句和流程控制

    前言 上一篇探讨了达夫设备对于代码性能的影响,本文主要探讨并且测试各种常见的循环语句的性能以及流程控制中常见的优化. 循环语句 众所周知,常用的循环语句有for.while.do-while以及for ...

  3. 【C语言探索之旅】 第一部分第七课:循环语句

    内容简介 1.课程大纲 2.第一部分第七课: 循环语句 3.第一部分第八课预告: 第一个C语言小游戏 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编 ...

  4. 子数涵数·C语言——循环语句

      之前,我们讲过了编程中的三种结构(顺序.条件.循环),现在我们来看一下循环语句如何编写. 一.while循环语句(先判断后执行) 1 #include<stdio.h> 2 int m ...

  5. python3 第七章 - 循环语句

    为了让计算机能计算成千上万次的重复运算,我们就需要循环语句. Python中的循环语句有 while for 循环语句的执行过程,如下图: while 循环 Python中while语句的一般形式: ...

  6. Python 学习笔记8 循环语句 while

    While循环是哟中利用条件语句,不断的执行某一段代码块,达到批量操作输出等一系列的操作,直到条件不满足或者被强制退出为止. 其工作流程如下: (图片来源菜鸟教程:http://www.runoob. ...

  7. 第二节 Python基础之变量,运算符,if语句,while和for循环语句

    我们在上一节中,我们发现当我们用字符串进行一些功能处理的时候,我们都是把整个字符串写下来的,比如"jasonhy".startwith("j"),如果我们在程序 ...

  8. #7 Python顺序、条件、循环语句

    前言 上一节讲解了Python的数据类型和运算,本节将继续深入,涉及Python的语句结构,相当于Python的语法,是以后编写程序的重要基础! 一.顺序语句 顺序语句很好理解,就是按程序的顺序逻辑编 ...

  9. Kotlin入门(7)循环语句的操作

    上一篇文章介绍了简单分支与多路分支的实现,控制语句除了这两种条件分支之外,还有对循环处理的控制,那么本文接下来继续阐述Kotlin如何对循环语句进行操作. Koltin处理循环语句依旧采纳了for和w ...

  10. python2.7入门---循环语句(for&嵌套循环)

        咱们直接先来看for循环.Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串.然后再来看一下它的语法结构: for iterating_var in sequence: ...

随机推荐

  1. Codeforces Round 908 (Div. 2)

    总结 T1 题目大意: A,B两人玩游戏,游戏规则如下: 整场游戏有多轮,每轮游戏先胜 \(X\) 局的人获胜,每场游戏先胜 \(Y\) 局的人获胜. 你在场边观看了比赛,但是你忘记了 \(x\) 和 ...

  2. cookie与session简介 django操作cookie django操作session

    目录 cookie与session简介 早期cookies 随机字符串解决cookies安全问题 禁止浏览器保存cookies django操作cookie set_cookie set_signed ...

  3. 如临现场的视觉感染力,NBA决赛直播还能这样看?

    在6月16日结束的NBA总决赛中,勇士4-2击败凯尔特人,问鼎总冠军!今年的NBA总决赛吸引了众多关注,互联网各大平台的赛事直播气氛也异常热烈. 平台如何既能展现专业的赛事解说,又能与球迷观众深入互动 ...

  4. 用ArcGIS模型构建器生成、导出Python转换空间坐标系的代码

      本文介绍在ArcMap软件中,通过创建模型构建器(ModelBuilder),导出地理坐标系与投影坐标系之间相互转换的Python代码的方法.   在GIS领域中,矢量.栅格图层的投影转换是一个经 ...

  5. P1914 小书童——凯撒密码

    1.题目介绍 小书童--凯撒密码 题目背景 某蒟蒻迷上了 "小书童",有一天登陆时忘记密码了(他没绑定邮箱 or 手机),于是便把问题抛给了神犇你. 题目描述 蒟蒻虽然忘记密码,但 ...

  6. arm-none-eabi-objcopy 使用说明

    译文 NAME objcopy - copy and translate object files 概要 objcopy [-F bfdname|--target=bfdname] [-I bfdna ...

  7. 【BUS】LIN Bus

    概述 随着汽车内电子设备的增多,市场上对于成本低于 CAN 的总线的需求日益强烈,不同的车厂相继开发各自的串行通信(UART/SCI)协议,以在低速和对性能要求不高的场合取代CAN.由于不同车厂定义的 ...

  8. 2023年江苏“领航杯”MISC一个很有意思的题目(别把鸡蛋放在同一个篮子里面)

    别把鸡蛋放在同一个篮子里面 题目附件:https://wwzl.lanzoue.com/i6HmX16finnc 1.题目信息 解压压缩包打开附件,获得5141个txt文档,每个文档都有内容,发现是b ...

  9. CSS 动画 : 3D翻页动画

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. HttpClient获取不到最新的系统代理

    默认情况下,HttpClient是默认采用系统代理,但是,如果你在程序运行过程中,手动修改系统代理,对于HttpClient是无效的,它依然会用老的代理去访问. 解决方法 使用下面的代码,你可以自己实 ...