[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: ...
随机推荐
- 应用火山引擎 DataTester“避坑”,抖音实现用 A/B 实验快速试错
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 A/B 测试产品可以说是企业科学决策的基础"设施",能够帮助企业快速迭代产品. 在字节跳动,每 ...
- Dom4j 保存XML HL7-V3
dom4j selectNodes 取不到值 因为XML带有命名空间 HL7 Dom4j 保存XML String xmlPath = "D:\\BS004.xml"; Strin ...
- linux day1:VMware虚拟机配置 CentOS系统配置
目录 运维岗位说明 计算机的种类 服务器的种类 服务器的品牌 服务器内部组成 缓存和缓冲 服务器磁盘阵列 raid5 linux系统发展史 去IOE运动 虚拟化技术 虚拟化软件下载 VMware安装 ...
- POJ - 1611 : The Suspects (普通并查集)
思路: 模板题,一步一步加入集合,最后判断有多少人跟0在同一个集合就行了. #include<iostream> #include<cstdio> using namespac ...
- 前端科普系列(2):Node.js 换个角度看世界
本文首发于 vivo互联网技术 微信公众号 链接: https://mp.weixin.qq.com/s/fPNMaeNYgU3eJsh0SLMRRg作者:孔垂亮 [前端科普系列]往期精彩内容: &l ...
- 推荐收藏!年度Top20开源许可证风险等级
开源许可现状 开发人员经常在软件中引入开源的代码片段.函数.方法和操作代码.因此,软件代码中经常会包含各种声明不同许可证的子组件.这些子组件的许可证条款和条件与项目整体主许可证的条款和条件冲突时,就会 ...
- 如何把thinkphp5的项目迁移到阿里云函数计算来应对流量洪峰?
原文链接:https://developer.aliyun.com/article/982746 1. 为什么要迁移到阿里云函数? 我的项目是一个节日礼品领取项目,过节的时候会有短时间的流量洪峰.平时 ...
- SpringBoot-mybatisplus-@select用法
mybatisplus查询本生已经挺丰富,但有的时候还是想自己写sql语句,怎么写?这时候就需要使用@select来实现,具体用法如下: 1.数据准备 CREATE TABLE XY_DIC_BLOC ...
- vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
上传文档格式 1 <template> 2 <div> 3 <div class="upload"> 4 <div> 5 <d ...
- 【KEIL】User's Guide
µVision User's Guide