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逆向安全(一)之基础知识(九) 的相关文章

  • 为什么tcl/tkinter只支持BMP字符?

    我正在尝试在基于 tkinter 和 tcl 构建的 gui 中查询和显示 utf 8 编码字符 但是 我发现 tkinter 无法显示 4 字节字符 即大于 U FFFF 的 unicode 代码点 为什么会这样呢 实现非 BMP 字符对
  • 在 Docker 中启动 tomcat 时无法在端口 8080 上打开网页

    在我的本地计算机 Windows 10 64 位 上 我启动 docker Toolbox 然后我拉取 Tomcat 映像并运行它 如下所示 docker run it tomcat 就跑成功了 31 Dec 2019 17 54 27 5
  • 强制窗口在打开时获得焦点

    我有一个 WPF 应用程序 它通过套接字连接与 C MFC 应用程序进行通信 如果用户按下 C 应用程序中的特定按钮 则会显示一个新的 WPF 窗口 以下是调用以启动 WPF 窗口的代码 var window new Window wind
  • Windows 计算机上出现“来自守护程序的错误响应:无法创建填充程序:OCI 运行时创建失败”错误

    我正在尝试构建一个简单的 Python 映像 然后在 Windows 上以交互方式访问容器 构建过程有效 但运行容器失败 这是 Dockerfile FROM python 3 10 4 WORKDIR app 生成文件 IMAGE scr
  • 获取已创建进程的进程句柄 Windows

    我需要获取运行程序时刚刚创建的所有进程的句柄或 PID 到目前为止 我已经使用了这段代码 每次创建进程时都会告诉我 问题是我只获取有关创建的进程的信息 但没有有关进程本身的任何信息 https msdn microsoft com en u
  • 在 Windows 11 上无需管理员权限即可运行 Visual Studio 2022

    我在 Windows 11 上安装了 Visual Studio 2022 当我启动它时 它始终以管理员权限运行 我想在没有管理员权限的情况下运行它 我的 Windows 只有一个帐户 该帐户具有管理员权限 x 我做了什么 确认VS2022
  • 如何在 PowerShell 中键入 TAB 字符?

    Task 默认情况下 在 Windows 命令提示符中按 TAB 键将输出文件名 而在 PowerShell 中则不会执行任何操作 我希望能够在交互模式下键入 TAB 字符 而不是通过脚本 Research 我在这个网站上和通过谷歌搜索发现
  • 在 Windows 上将 Mercurial (hg) 存储库转换为 Git (7)

    我现在真的很沮丧 我有一个现有的 hg 存储库 其中有几个月的编码历史 我想将其放入私有 Github 存储库中 以便我可以从那里对其进行处理 不幸的是我使用的是 Windows 我似乎找不到any转换我实际上可以正常工作的存储库的方法 实
  • R 脚本自动化时的不同结果

    以下命令对 pdf 文件执行 Ghostscript 这pdf file变量包含该 pdf 的路径 bbox lt system paste C gs gs8 64 bin gswin32c exe sDEVICE bbox dNOPAUS
  • 如何让脚本执行结束后自动删除?

    是否可以制作一个Python脚本 在Windows中执行结束时删除 py文件 自删除 这种方式使您的程序不依赖于操作系统 from os import remove from sys import argv remove argv 0 奖励
  • 如何更改选项卡控件的名称

    我在 C WinForms 应用程序中使用选项卡控件 我想更改选项卡的标题 默认情况下它们是 tabPage1 tabPage2 等 一种无需代码即可实现的懒惰方法 选择选项卡控件 Go to properties use F4 to do
  • Windows7上python3.5无法安装BeautifulSoup4

    我已经从下载了 beautifulsoup4 4 5 3 tar gzhttps www crummy com software BeautifulSoup bs4 download 4 5 https www crummy com sof
  • 如何在 C++ 中急于提交分配的内存?

    总体情况 带宽 CPU 使用率和 GPU 使用率都极其密集的应用程序需要每秒从一个 GPU 向另一个 GPU 传输约 10 15GB 的数据 它使用 DX11 API 来访问 GPU 因此上传到 GPU 只能在每次上传都需要映射的缓冲区中进
  • 检测计算机何时解锁 Windows

    我用过这个优秀的方法 https stackoverflow com questions 20733441 lock windows workstation using python 20733443锁定 Windows 计算机 那部分工作
  • 从命令行运行 R 代码 (Windows)

    我在名为 analysis r 的文件中有一些 R 代码 我希望能够从命令行 CMD 运行该文件中的代码 而无需通过 R 终端 并且我还希望能够传递参数并在我的代码中使用这些参数 例如就像下面的伪代码 C gt execute r scri
  • 在 Cygwin 软件包列表中找不到 Openssl

    这里说的是https github com joyent node wiki Building node js on Cygwin Windows https github com joyent node wiki Building nod
  • 自定义波特率,redux

    我遇到的问题详述如下自定义波特率 https stackoverflow com questions 7714060 custom baud rate SetCommState 波特率 921600 失败 但波特率 115200 成功 尽管
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 在哪里可以获得 PHP 5.3+ 的 runkit DLL 扩展?

    这是一个简单的问题 我在哪里可以获得 PHP 5 3 版本的 runkit 扩展 它的手册 http php net manual en book runkit php http php net manual en book runkit
  • 将 CrashDumps 转储到应用程序运行所在的同一文件夹中

    我编写了一个应用程序 我希望对其进行一定程度的自动调试 我想使用 Windows 错误报告将故障转储输出到应用程序运行所在的同一文件夹中 我的想法是 我可以让我的应用程序在它自己的文件夹中查找任何 dmp 文件 然后根据需要上传它们进行分析

随机推荐

  • 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