[3] 以逆向的角度来看循环语句——do、while、for的比较
[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的比较的更多相关文章
- Python学习【第五篇】循环语句
Python循环语句 接下来将介绍Python的循环语句,程序在一般情况下是按顺序执行的. 编程语言提供了各种控制结构,允许更复杂的执行路径. 循环语句允许我们执行一个语句或语句组多次. Python ...
- 高性能JavaScript 循环语句和流程控制
前言 上一篇探讨了达夫设备对于代码性能的影响,本文主要探讨并且测试各种常见的循环语句的性能以及流程控制中常见的优化. 循环语句 众所周知,常用的循环语句有for.while.do-while以及for ...
- 【C语言探索之旅】 第一部分第七课:循环语句
内容简介 1.课程大纲 2.第一部分第七课: 循环语句 3.第一部分第八课预告: 第一个C语言小游戏 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语言编 ...
- 子数涵数·C语言——循环语句
之前,我们讲过了编程中的三种结构(顺序.条件.循环),现在我们来看一下循环语句如何编写. 一.while循环语句(先判断后执行) 1 #include<stdio.h> 2 int m ...
- python3 第七章 - 循环语句
为了让计算机能计算成千上万次的重复运算,我们就需要循环语句. Python中的循环语句有 while for 循环语句的执行过程,如下图: while 循环 Python中while语句的一般形式: ...
- Python 学习笔记8 循环语句 while
While循环是哟中利用条件语句,不断的执行某一段代码块,达到批量操作输出等一系列的操作,直到条件不满足或者被强制退出为止. 其工作流程如下: (图片来源菜鸟教程:http://www.runoob. ...
- 第二节 Python基础之变量,运算符,if语句,while和for循环语句
我们在上一节中,我们发现当我们用字符串进行一些功能处理的时候,我们都是把整个字符串写下来的,比如"jasonhy".startwith("j"),如果我们在程序 ...
- #7 Python顺序、条件、循环语句
前言 上一节讲解了Python的数据类型和运算,本节将继续深入,涉及Python的语句结构,相当于Python的语法,是以后编写程序的重要基础! 一.顺序语句 顺序语句很好理解,就是按程序的顺序逻辑编 ...
- Kotlin入门(7)循环语句的操作
上一篇文章介绍了简单分支与多路分支的实现,控制语句除了这两种条件分支之外,还有对循环处理的控制,那么本文接下来继续阐述Kotlin如何对循环语句进行操作. Koltin处理循环语句依旧采纳了for和w ...
- python2.7入门---循环语句(for&嵌套循环)
咱们直接先来看for循环.Python for循环可以遍历任何序列的项目,如一个列表或者一个字符串.然后再来看一下它的语法结构: for iterating_var in sequence: ...
随机推荐
- 阿里OSS文件访问变成下载
将 ECS 挂载 OSS 多Bucket ,进行文件存储后,发现PDF.图片在浏览器中访问URL,变成了下载,页不是预览. 1. 解决办法,文件类型 application/octet-stream ...
- AC(AtCoder) Library 文档翻译
AC(AtCoder) Library Document下载使用 如何安装 首先在 Github 上找到 ac-library 仓库.下载最新版本 解压 zip 文件后将 atcoder ,放置GCC ...
- 方法记录 | 文件批量导入Goodnotes
一般来说通常资料都是用网盘下载了很多文件,想用Goodnotes来写批注,记笔记等,但是由于网盘不能直接分享.也不能批量分享到Goodnotes,给学习带来了很大的麻烦. 当然有钱的大佬们呢直接开了 ...
- L2-007 家庭房产 (25 分) (并查集)
给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数.人均房产面积及房产套数. 输入格式: 输入第一行给出一个正整数N(≤1000),随后N行,每行按下列格式给出一个人的房产: 编号 父 ...
- linux安装pyarmor踩坑记录
现有环境 centos 7.8 python 3.7.6 pip 20.0 找度娘学习安装pyarmor pip install pyarmor 然后查看版本 pyarmor --version 进入 ...
- 图扑 HT for Web 风格属性手册教程
图扑软件明星产品 HT for Web 是一套纯国产化独立自主研发的 2D 和 3D 图形界面可视化引擎.HT for Web(以下简称 HT)图元的样式由其 Style 属性控制,并且不同类型图元的 ...
- 面试重点:webpack
webpack 熟练掌握Webpack的常用配置,能够自己构建前端环境,并进行项目优化; 001.谈谈你对webpack的看法: webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编 ...
- d3生成器--line,area,diagonal
https://blog.csdn.net/qq_31396185/article/details/78147612
- SpringBoot 动态多线程并发定时任务
一.简介 实现定时任务有多种方式: Timer:jdk 中自带的一个定时调度类,可以简单的实现按某一频度进行任务执行.提供的功能比较单一,无法实现复杂的调度任务. ScheduledExecutorS ...
- 基于python开发的口罩供需平台
基于python开发的口罩供需平台 预览地址:https://i.mypython.me 开发语言:python/django 意见反馈:net936艾特163.com