Windows逆向安全(一)之基础知识(九)

2023-05-16

汇编比较三种循环

众所周知,在C语言可以使用可以使用三种循环,分别是:while、do…while和for

本文从汇编的角度出发,观察这三种循环的差异

范例代码

先贴出三种循环的代码,分别用这三种循环计算

0+1+2+3+4+5+6+7+8+9(从0一直加到9)

#include "stdafx.h"
int loop1(){
        int i=0,j=0;
        for(i=0;i<10;i++){
                j=j+i;
        }
        return j;
}

int loop2(){
        int i=0,j=0;
        while(i<10){
                j=j+i;
                i=i+1;
        }
        return j;
}
int loop3(){
        int i=0,j=0;
        do {
                j=j+i;
                i=i+1;
        } while(i<10);
        return j;
}

int main(int argc, char* argv[])
{
        int result=0;
        result=loop1();
        printf("%d\n",result);
        result=loop2();
        printf("%d\n",result);
        result=loop3();
        printf("%d\n",result);
        return 0;
}

运行结果

在这里插入图片描述

显然,这三种循环都能正确地计算出结果,接下来挨个分析这三种循环的汇编代码

for循环

省去汇编代码中保护现场、提升堆栈、初始化堆栈、恢复现场和返回的代码,直接看代码的对应汇编

9:        int i=0,j=0;
0040D748   mov         dword ptr [ebp-4],0
0040D74F   mov         dword ptr [ebp-8],0
10:       for(i=0;i<10;i++){
0040D756   mov         dword ptr [ebp-4],0
0040D75D   jmp         loop1+38h (0040d768)
0040D75F   mov         eax,dword ptr [ebp-4]
0040D762   add         eax,1
0040D765   mov         dword ptr [ebp-4],eax
0040D768   cmp         dword ptr [ebp-4],0Ah
0040D76C   jge         loop1+49h (0040d779)
11:           j=j+i;
0040D76E   mov         ecx,dword ptr [ebp-8]
0040D771   add         ecx,dword ptr [ebp-4]
0040D774   mov         dword ptr [ebp-8],ecx
12:       }
0040D777   jmp         loop1+2Fh (0040d75f)
13:       return j;
0040D779   mov         eax,dword ptr [ebp-8]
14:   }

头两行汇编对应将i和j初始化为0,没什么好说的

9:        int i=0,j=0;
0040D748   mov         dword ptr [ebp-4],0
0040D74F   mov         dword ptr [ebp-8],0

在这里插入图片描述
接下来看循环语句部分:

第一行为:

0040D756   mov         dword ptr [ebp-4],0

对应for(i=0;i<10;i++)中的i=0

接下来是一个绝对跳转指令:

0040D75D   jmp         loop1+38h (0040d768)

跳转的地址为:0040d768

0040D768   cmp         dword ptr [ebp-4],0Ah
0040D76C   jge         loop1+49h (0040d779)

这里就是比较 i 和0Ah(十六进制的10),也就是对应for(i=0;i<10;i++)中的i<10

jge指令:jump greater equal,当大于等于时跳转(有符号)

所以这里就是判断i是否大于10,如果大于10就跳转到0040d779

接下来看0040d779对应的代码:

13:       return j;
0040D779   mov         eax,dword ptr [ebp-8]

这里就是返回的语句了,已经在循环的外部了,即上面的跳转其实就是退出循环的语句

如果前面的i<10,则继续向下看汇编语句:

11:           j=j+i;
0040D76E   mov         ecx,dword ptr [ebp-8]
0040D771   add         ecx,dword ptr [ebp-4]
0040D774   mov         dword ptr [ebp-8],ecx

先将j赋值给ecx,然后用ecx加上i,最后将ecx赋值给j,即j=j+i,也就是我们循环里要执行的内容

执行完上面的j=j+1后,下一行指令是一个绝对跳转:

12:       }
0040D777   jmp         loop1+2Fh (0040d75f)

跳转的地址为0040d75f,继续观察:

0040D75F   mov         eax,dword ptr [ebp-4]
0040D762   add         eax,1
0040D765   mov         dword ptr [ebp-4],eax
0040D768   cmp         dword ptr [ebp-4],0Ah

先将i的值赋给eax,然后eax加一后把eax赋给i,对应for(i=0;i<10;i++)中的i++

然后就回到了之前的步骤,比较i是否大于等于10,是则退出循环,否则继续循环执行

for循环总结

通过前面的分析大致可以知道for循环的执行流程为:

在这里插入图片描述

while循环

省去汇编代码中保护现场、提升堆栈、初始化堆栈、恢复现场和返回的代码,直接看代码的对应汇编

17:       int i=0,j=0;
0040D7A8   mov         dword ptr [ebp-4],0
0040D7AF   mov         dword ptr [ebp-8],0
18:       while(i<10){
0040D7B6   cmp         dword ptr [ebp-4],0Ah
0040D7BA   jge         loop2+40h (0040d7d0)
19:           j=j+i;
0040D7BC   mov         eax,dword ptr [ebp-8]
0040D7BF   add         eax,dword ptr [ebp-4]
0040D7C2   mov         dword ptr [ebp-8],eax
20:           i=i+1;
0040D7C5   mov         ecx,dword ptr [ebp-4]
0040D7C8   add         ecx,1
0040D7CB   mov         dword ptr [ebp-4],ecx
21:       }
0040D7CE   jmp         loop2+26h (0040d7b6)
22:       return j;
0040D7D0   mov         eax,dword ptr [ebp-8]
23:   }

头两行初始化i和j,和前面一样,不属于循环的内容,这里给出i和j对应的地址

在这里插入图片描述

下面正式来看循环的内容:

18:       while(i<10){
0040D7B6   cmp         dword ptr [ebp-4],0Ah
0040D7BA   jge         loop2+40h (0040d7d0)

比较 i 和 10

jge:jump greater equal,大于等于就跳转(有符号)

综上两句就是用来判断 i<10 对应while(i<10)中的 判断条件 i<10

如果i>=10,则跳转到0040d7d0,退出循环

22:       return j;
0040D7D0   mov         eax,dword ptr [ebp-8]

这里就是返回的语句了,已经在循环的外部了

如果i<10,也就是没有跳转,接着看下面的语句:

19:           j=j+i;
0040D7BC   mov         eax,dword ptr [ebp-8]
0040D7BF   add         eax,dword ptr [ebp-4]
0040D7C2   mov         dword ptr [ebp-8],eax
20:           i=i+1;
0040D7C5   mov         ecx,dword ptr [ebp-4]
0040D7C8   add         ecx,1
0040D7CB   mov         dword ptr [ebp-4],ecx
21:       }

就是执行我们while里面所写的代码(执行循环内的代码)

接着看下面的语句,是一个无条件跳转,跳转到前面的0040d7b6

0040D7CE   jmp         loop2+26h (0040d7b6)

来看看0040d7b6,就是最开始的判断语句,如果i<10则继续执行,否则跳出循环

0040D7B6   cmp         dword ptr [ebp-4],0Ah
0040D7BA   jge         loop2+40h (0040d7d0)

while循环总结

通过前面的分析大致可以知道while循环的执行流程为

在这里插入图片描述

do while循环

省去汇编代码中保护现场、提升堆栈、初始化堆栈、恢复现场和返回的代码,直接看代码的对应汇编

25:       int i=0,j=0;
0040D888   mov         dword ptr [ebp-4],0
0040D88F   mov         dword ptr [ebp-8],0
26:       do {
27:           j=j+i;
0040D896   mov         eax,dword ptr [ebp-8]
0040D899   add         eax,dword ptr [ebp-4]
0040D89C   mov         dword ptr [ebp-8],eax
28:           i=i+1;
0040D89F   mov         ecx,dword ptr [ebp-4]
0040D8A2   add         ecx,1
0040D8A5   mov         dword ptr [ebp-4],ecx
29:       } while(i<10);
0040D8A8   cmp         dword ptr [ebp-4],0Ah
0040D8AC   jl          loop3+26h (0040d896)
30:       return j;
0040D8AE   mov         eax,dword ptr [ebp-8]
31:   }

头两行初始化i和j,和前面一样,不属于循环的内容,这里给出i和j对应的地址

在这里插入图片描述
下面正式来看循环的内容:

26:       do {
27:           j=j+i;
0040D896   mov         eax,dword ptr [ebp-8]
0040D899   add         eax,dword ptr [ebp-4]
0040D89C   mov         dword ptr [ebp-8],eax
28:           i=i+1;
0040D89F   mov         ecx,dword ptr [ebp-4]
0040D8A2   add         ecx,1
0040D8A5   mov         dword ptr [ebp-4],ecx

直接执行我们do while里面所写的代码(执行循环内的代码)

接着看下面的代码:

29:       } while(i<10);
0040D8A8   cmp         dword ptr [ebp-4],0Ah
0040D8AC   jl          loop3+26h (0040d896)

先是比较 i 和 10

然后 jl :jump less (有符号数),当i<10的时候才跳转

跳转地址为0040d896,也就是前面的代码

26:       do {
27:           j=j+i;
0040D896   mov         eax,dword ptr [ebp-8]

如果没有跳转则执行下面的代码

30:       return j;
0040D8AE   mov         eax,dword ptr [ebp-8]

注意到这里已经是退出循环的状态了,返回j

do while循环总结

过前面的分析大致可以知道do while循环的执行流程为:

在这里插入图片描述

比较

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

从流程图就不难看出,三种循环的复杂程度:

for循环>while循环>do while循环

因此执行效率则是:

do while循环>while循环>for循环

  • for循环是先判断条件是否不满足i<10,也就是是否满足i>=10,不满足条件则跳出循环并返回;满足条件则执行循环内的代码,执行完循环内代码后无条件跳转到计数增加i=i+1再回到判断条件
  • while循环也是先判断条件是否不满足i<10,也就是是否满足i>=10,不满足条件则跳出循环并返回;满足条件则执行循环内的代码,执行完循环内代码后无条件跳转到判断条件处
  • do while循环则是先执行循环内的语句,然后再判断条件,判断条件是否满足i<10,满足条件则跳回去继续执行循环内的代码
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Windows逆向安全(一)之基础知识(九) 的相关文章

  • 在 C# 中创建 Cron 作业

    我正在用 C 编写一个调度类型应用程序 并允许用户存储他们想要在特定时间运行的任务 现在 我为他们提供了指定运行频率 每日 每周 每月 以及指定时间的选项 然后将其存储在数据库中 我在理解其背后的伪代码时遇到了一些麻烦 并且正在寻找一些有关
  • 如何“安装”自定义 Windows 驱动程序?

    我计划用 C 语言编写一个基本的 Windows 注册表过滤器 该过滤器的目的是挂钩所有 用户和内核特权 注册表调用 以便我可以在我的程序中使用它们 我基本上是复制 Mark Rusinovich 的 regmon 进程监视器 但更基本 我
  • 没有名为“_pywrap_tensorflow_internal”的模块

    在尝试验证tensorflow gpu的安装时 在尝试执行 import tensorflow as tf 时出现ImportError 我在 Windows 7 上使用 Quadro K620 Tensorflow 是使用 pip 安装的
  • 自动将 Linux 文件名重命名为 Windows 中合法的新文件名

    我想将 linux 文件重命名为在 windows 中合法的文件名 它的长度不应超过允许的长度 并且不应包含 Windows 中不允许的字符 有时我将论文的标题复制到文件名 它们有特殊字符 例如 or 另外 从 pdf 中复制和粘贴标题时
  • 无法在 Windows 的多处理环境中“pickle”Tkinter 对象

    我正在尝试创建一个应用程序 其中 Tkinter GUI 由不断获取数据的其他对象更新 我在使用多线程时遇到问题 因此我决定尝试使用多处理模块 我发现您无法在其中运行 Tkinter 窗口multiprocessing Process 这是
  • 使用 git 客户端和 SVN 存储库的最佳工具/方法

    我已经使用 SVN 大约两年了 主要是通过 TortoiseSVN 和 IntelliJ 并尝试了 git 主要是通过 TortoiseGIT 在这里检测到模式 我们公司正在使用 SVN 作为存储库 他们不会考虑很快进行切换 在本地使用 g
  • 设置 eclipse 进行 Windows 驱动程序开发

    我正在尝试使用 WDK 7 1 0 编写用户模式 Windows XP Vista 和 7 虚拟打印机驱动程序 我打算使用 eclipse IDE 进行开发 所以想知道是否可以进行相同的设置 我希望做以下事情 1 Eclipse 能够识别
  • 转储 $mft 文件的内容

    对于一些商业的我正在做的项目我需要能够读取 mft 文件中存储的实际数据 我找到了一个gpl lib http www codeproject com KB files NTFSParseLib aspx artkw ntfs这可能会有所帮
  • 生成唯一硬件 ID 的可靠方法

    问题 我必须为每个联网客户端提供唯一的 ID 例如 一旦客户端软件安装在目标计算机上 它 ID 应该持续存在 并且如果在同一台计算机和相同的操作系统安装上重新安装软件 它应该继续存在 如果以大多数方式修改硬件配置 除了更改主板 它不应该改变
  • Ruby on Rails 安装问题 (Windows)

    我从 RuyInstaller 安装了 Ruby 2 0 0 和 DevKit 创建新项目时出现错误消息 rails new testtest d mysql a lot of output here Installing mysql2 0
  • 如何从 Python (2.7) 中生成的进程中消除 Windows 控制台? [复制]

    这个问题在这里已经有答案了 可能的重复 在没有控制台的情况下使用 Popen 在 python 中运行进程 https stackoverflow com questions 1813872 running a process in pyt
  • C# Dns.GetHostEntry() - 异常:没有这样的主机已知

    From 文档 https learn microsoft com en us dotnet api system net dns gethostentry view netframework 4 8 Dns GetHostEntry 将主
  • 适用于 Windows 的免费内存调试器? [复制]

    这个问题在这里已经有答案了 可能的重复 有 Windows 的良好 Valgrind 替代品吗 https stackoverflow com questions 413477 is there a good valgrind substi
  • 打开文件选择器对话框时出现 Glib-GIO-ERROR

    我在 Windows 7 中使用 GTK3 codeblcks IDE glade3 在我的应用程序中 我有一个按钮 单击该按钮应打开一个 gtk file chooser dialog 但给出填充错误 Glib GIO 错误 系统上未安装
  • Windows批量编程中读取文件名

    我想在Windows批处理编程中读取文件的名称 我尝试使用不同的方法但失败了请帮助 下面给出了场景 我的文件夹中有不同的文件 但所有文件的文件名长度相同 例如 1000342578 30062011 PDF 1000342329 30062
  • 同步通过 LAN 电缆连接的两台 Windows 7 计算机之间的时间

    我有许多笔记本电脑 它们运行我们的应用程序 同时通过以太网电缆成对连接 但未连接到任何外部网络或互联网 时间 我需要连接对来同步其系统时间 但由于每台计算机都需要能够与任何其他计算机同步 因此我无法将一台计算机定义为时间服务器 而另一台计算
  • 如何从 Emacs 中运行 Cygwin Bash Shell?

    我在 Windows 上运行 GNU Emacs 因此输入 M x shell 启动 Windows 命令行 DOS shell 但是 我希望能够从 Emacs 中运行 Cygwin Bash Shell 或任何其他非 Windows sh
  • CTRL+C 和 CTRL+Break 不同吗?

    我一直认为它们绝对是一样的 但我刚刚在以下位置找到了一些值 CTRL C EVENT 和 CTRL BREAK EVENT设置控制台Ctrl处理程序 http msdn microsoft com en us library ms68601
  • Cygwin setup.exe 在安装 Windows 8 期间挂起?我该怎么继续?

    因此 过去几年我断断续续地使用过 Cygwin 并且安装过几次 但是 我从未在安装过程中经历过安装挂起的情况 发生这种情况时 安装实际上会冻结并且不会 一点 移动 我读到这是一个有点常见问题 http cygwin com ml cygwi
  • 轻量级 Windows 应用程序的最佳开源示例是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi

随机推荐

  • ESP32 micro-usb 多数据量并简单加密的串口通信

    文章目录 前言一 ESP32和上位机的环境二 上位机部分1 串口通信的准备2 数据的准备与发送 三 下位机部分1 ESP32串口通信准备2 数据的接收四 同时测试 总结 前言 最近在研究单片机与上位机的串口通信 xff0c 刚好手头有一块E
  • boost之跨平台 错误处理

    system C 43 43 中处理错误的最佳方式是使用异常 xff0c 但操作系统和许多底层AP工不具有这个能力 xff0c 它们一般使用更通用也更难以操作的错误代码来表示出错的原因 xff0c 不同的操作系统的错误代码通常不是兼容的 x
  • 记录一下vector基本用法(简单易懂)

    vector容器的初始化 vector的使用首先需要加一个头文件 include lt vector gt xff1b vector lt int gt a 最一般的初始化方法 xff0c 就是定义一个容器啊a xff1b vector l
  • MPU6050基本原理介绍及程序配置

    一 MPU6050简介 1 内部主要结构 xff1a 陀螺仪 加速度计 数字运动处理器DMP xff08 Digital Motion Processor xff09 PS MPU6050还含有第二IIC接口 xff0c 用于连接一个 第三
  • Robomaster上位机视觉摘要——比赛规则篇

    本文是笔者多日来总结的2023赛季中针对上位机组的比赛规则摘要 xff0c 力求一文让你看懂上位机在赛场中的飒爽身影 目录 电力元件 电池 遥控器 激光 涂装 机器人 飞镖 雷达 空中机器人 工程机器人 哨兵机器人 英雄与步兵机器人 视觉应
  • C语言:结构体——关于内存字节对齐图文详解

    前言 xff1a 我们在学到c语言内存管理的时候总是一遍惊叹 xff0c 其聪明的内存管理策略 xff0c 一遍抱怨其难以理解的方法 xff0c 网上的资料要不讲究的太详细 xff0c 要不没能讲解清楚 xff0c 今天我们根据实例来学习一
  • 结构体+联合体 详解

    文章目录 一 结构体1 结构体变量2 特殊声明3 结构体的引用1 嵌套调用2 自引用 三 结构体的初始化四 结构体的内存对齐1 用法2 练习题3 修改对齐数 五 位段1 用法2 练习题 六 联合体1 用法2 练习题1 正常算法题2 用联合体
  • Ubuntu20.04——一篇文章让你从零配置VINS_Mono环境以及运行(2023年最新)

    注 xff1a 文末包含该文章涉及的所有安装包的网盘链接 零 换源 xff08 也可以先不换 xff0c 后面觉得下载慢再换也行 xff09 1 备份原来的源 sudo cp etc apt sources list etc apt sou
  • 学C语言推荐的书和软件—C Primer Plus和Dev C++

    写这个的目的是复习巩固C Primer Plus的知识 xff0c 我会一直更新这个系列 对于这本书 xff0c 入门C语言是完全够了 xff0c 后面的链表 队列和二叉树比较综合 xff0c 难度大一些 用这本书学C语言非常好 xff0c
  • mavlink python

    from pymavlink import mavutil Create the connection m 61 mavutil mavlink connection 39 udpin 0 0 0 0 14550 39 dir m mav
  • C++Vector浅析,Vector用法大全

    vector基本概念 功能 xff1a vector数据结构和数组非常相似 xff0c 也成为单端数组 vector与普通数组的区别 xff1a 不同之处在与数组是静态空间 xff0c 而vector可以动态扩展 动态扩展 xff1a 并不
  • 网络通信--Linux

    文章目录 网络通信的基础通信模型IP地址和端口port 网络套接字网络字节序初识UDP与TCP两种协议sockaddr结构体家族认识一些网络常用基础函数 UDP实现简单通信TCP实现简单通信总结 网络通信的基础 网络通信是建立在多层协议之下
  • Git分支和版本(标签)

    目录 一 Git分支 1 1 四大环境 xff08 分支 xff09 1 1 1 分支和标签的关系 1 2 分支的作用 1 3 演示分支 1 3 1 在Gitee中创建项目 1 3 2 克隆到本地 1 3 3 建立分支 1 3 4 切换分支
  • 前端必会算法——栈和队列

    上一篇 前端必会算法 标准快速排序 栈和队列 栈 xff08 Stack xff09 可以理解为是一个箱子 xff0c 存放东西的容器 栈结构的特点 xff1a 先入后出 xff0c 栈相当于一个箱子 xff0c 先放进去的东西被压在了下面
  • OpenMV的单颜色识别讲解

    OpenMV的官方教程 xff1a 寻找色块 xff1b single color rgb565 blob tracking示例讲解 xff1b 视频讲解 需要提前看的文章 xff1a 程序烧录 xff1b 颜色阈值设置 目录 thresh
  • STM32CubeMX串口通讯

    串口的简单介绍 RS 232与TTL 根据通讯使用的电平标准不同 xff0c 串口通讯可分为 TTL 标准及 RS 232 标准 而STM32的串口是TTL电平标准的 如果需要使用到RS 232则需要一个电平转换芯片 单工通信 半双工通信和
  • 自制超简易通讯协议(中断接收)

    前言 在做蓝牙语音小车时 xff0c 总遇到各式各样的问题 本文主题是笔者在解决串口不够并且数据量小的问题时突发奇想自定义一个简易的通讯协议 由于是用89c51做的主控 xff0c 外设的资源比较紧张 串口只有一个 xff0c 但两个系统需
  • 【Java杂谈】Iterator(迭代器)的使用

    x1f3b8 Iterator是什么 xff1f 迭代器是Java提供的一种访问集合的方法 xff0c Iterator 是 Java 迭代器最简单的实现 xff0c 常用来访问ArrayList HashMap等类的对象 Iterator
  • orb 纯背景物体识别

    include lt chrono gt include lt iostream gt include lt opencv2 core core hpp gt include lt opencv2 features2d features2d
  • Windows逆向安全(一)之基础知识(九)

    汇编比较三种循环 众所周知 xff0c 在C语言可以使用可以使用三种循环 xff0c 分别是 xff1a while do while和for 本文从汇编的角度出发 xff0c 观察这三种循环的差异 范例代码 先贴出三种循环的代码 xff0