案例分析-程序的机器级表示

news2024/10/12 18:19:38

案例一:关于编译优化

请自写一段if- else简单分支程序,分别尝试对它进行不带优化、-O1优化和-O2优化,比较它们的机器级表达,并讨论优劣。

图一为不带优化、图二为O1优化、图三为O2优化、图四为原始C代码。
(1)
①不带优化
不带优化的代码很直接的对应了C代码的逻辑。首先设置栈帧,然后调用__isoc99_scanf函数两次来读取输入。然后使用cmp和jle指令来比较x和y的值,并根据结果执行减法操作。最后,它检查栈的完整性,返回结果。
优点是易于理解和调试,因为它直接反映了C代码的结构,而且非常容易理解,都是一些基础的操作。但是缺点是性能不是最优的,因为它包含了一些不必要的栈操作和检查,而这些操作可以使用一些更高效的指令来替代。
②O1优化
在O1优化级别下,编译器进行一些基本的优化了。比如,减少了栈帧的大小,并尝试重用栈上的空间来存储变量。此外,它还使用了一些更高效的指令来执行相同的操作,比如在这个例子中,编译器使用了lea指令来加载有效地址,这通常比直接使用mov指令更快;它还使用了cmovg指令来实现条件移动,这可以避免使用分支指令,从而提高性能。
③O2优化
在O2优化级别下,编译器会进行更强烈的优化。可能会重新排序指令,删除不必要的操作,并尝试将代码内联到调用者中。
(2)优劣讨论
不带优化:
优点: 便于理解和调试,直接反映了C代码的结构。
缺点: 性能可能不是最优的,包含很多不必要的栈操作和检查。
O1优化:
优点: 在保持代码结构相对清晰的同时提高了性能。使用了一些更高效的指令和技巧来减少不必要的操作。
缺点: 虽然比不带优化的代码更高效,但可能还没有达到最优性能。
O2优化:
优点: 通常能提供最优的性能。编译器会进行更强烈的优化,删除不必要的操作,并尝试将代码内联到调用者中。
缺点: 代码可能变得难以理解和调试,因为编译器会对原始C代码进行大量的转换和重排。

案例二:条件表达式的机器级表示

C中有多种方式实现分支,下面是用2种不同的方式实现分支的程序,这两种方式在C层面上是等价的。

方式一:用if-else实现

方式二:用条件表达式实现

请在Ubuntu环境下进行编译及反汇编,分析并回答:

1)  两种方式的机器级表达是否一致?(贴图展现)

2)  方式二(条件表达式实现分支)存在什么风险?有什么代价?

从提供的反汇编代码来看,两种方式的机器级表达在大体上是一致的(左图为if else,右图为三目运算符)。它们都包含了以下步骤:
将局部变量x和y的值加载到寄存器中、使用cmp指令比较x和y的值、根据比较结果使用条件跳转指令(jle)来执行不同的减法操作、将结果存储到寄存器或栈中,并准备返回。
方式二使用条件表达式来实现分支,这种方式在C语言层面上的语法确实很简洁,然而,在底层实现上,它并没有本质上不同于if-else语句,方式二在机器级表达上同样会生成条件跳转和减法操作等指令序列。
在风险方面,使用条件表达式实现分支本身并没有引入新的风险,因为它在语义上与if-else语句是等价的。但是我们可以发现,过度使用条件表达式可能会使代码难以阅读和维护,尤其是在复杂的逻辑表达式中,比如当条件冗长时,一条语句可能就占了几十个字长。此外,如果条件表达式的条件部分计算一些复杂的操作(如函数调用),那么这些操作可能会在每次条件判断时都被执行,导致性能大大降低。
在代价方面,使用条件表达式与if-else语句在性能上通常没有显著差别,因为编译器会将其转换为类似的机器代码,这一点我们由objdump反汇编代码也能看出。然而,如果编译器无法对条件表达式进行有效的优化,或者条件表达式的条件部分较为复杂,那么可能会产生稍微多一些的指令,也可能会稍微降低一些执行速度。

案例三:循环的机器级表示

在C语言中,我们可以用for、while、do-while和goto四种不同的方式实现循环程序,请自己设定一种循环情形,用以上四种方式分别写出C代码,并比较它们的机器级表达(均不带编译优化)是否一样?

在不带编译优化的情况下,在x86-64指令集架构,gcc 13.2编译器环境下,我设计了一个循环打印1~10的整数的C代码。根据汇编代码,我们可以发现,for和while两种方式的汇编代码是完全相同的,而这两种循环与do-while、goto有少许差异。
①for循环的汇编代码包含了初始化计数器、循环体执行、更新计数器和条件判断等步骤,先将计数器初始化为1,并在每次迭代后增加1。条件判断是检查计数器是否小于或等于10。如果是,则继续执行循环体;否则,退出循环。
②while循环的汇编代码与for循环的汇编代码完全相同。这是因为在这个特定例子中,for循环和while循环的逻辑结构是相同的:先检查条件,然后执行循环体,最后更新计数器。编译器在这种情况下选择了类似的实现方式。
③do-while循环的汇编代码在结构上略有不同。它首先执行循环体,然后更新计数器,最后检查条件。这与for和while循环先检查条件后执行循环体的顺序不同。然而,由于这个差异仅在于循环的开始和结束部分,所以整体上三种循环的汇编代码仍然非常相似。
④goto循环的汇编代码在循环条件和跳转指令上与其他三种循环有所不同。它使用了一个无条件跳转指令jmp来重复执行循环体,而不是像其他循环那样使用条件跳转指令jle。此外,goto循环的条件判断是检查计数器是否大于9(即小于或等于10的补码表示),如果是,则跳转到循环体的末尾并更新计数器;否则,退出循环。

案例四:多情形分支-负数的情况

以课堂上讲授的多情形分支Switch.c程序为例,分析以下编译结果:

情形值x为有符号数,为什么编译结果却使用了ja(用于无符号数)指令来判断情形,而不是用于有符号数的jg指令?

附Switch.c代码:

请修改一下switch.c代码,增加一种case为负数的情况(比如-1或-2),进行编译后再观察看看,请贴图说明。(再联想之前问的为何使用ja而非jg)

在负数较小情况下,编译器是会把负数增加到0或者整数,然后再加入跳转表中。举个例子,比如在switch(i)中,原先是case 1 2 3 4 5 6,修改为case -1 -2 3 4 5 6,范围由6变为8。因为有了-1、-2这两个负数的加入,而且因为这两个负数绝对值不是很(负数绝对值过大时会使用jl等跳转语句),所以会先把i先全都+2,补齐为1 0 5 6 7 8,全部转换成了正数(类似于数组下标),然后再与8进行cmp(因为最大值是8。原先是与6进行cmp),这样i就还是正数,可以使用ja,而不是jg。详细对比见下图(x86-64 gcc 13.2编译器处理结果):

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1567247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

x-cmd-pkg | broot 是基于 Rust 开发的一个终端文件管理器

简介 broot 是基于 Rust 开发的一个终端文件管理器,它设计用于帮助用户在终端中更轻松地管理文件和目录,使用树状视图探索文件层次结构、操作文件、启动操作以及定义您自己的快捷方式。 同时它还集成了 ls, tree, find, grep, du, fzf 等工具的常用功能…

IDEA连接SqlServer数据库

目录 下载jar包 下载sqljdbc_12.6压缩包 解压 导入IDEA 新建文件夹 复制粘贴进JDBC文件夹并设为library 编写类及方法 代码 下载jar包 以sqljdbc_12.6为例 下载sqljdbc_12.6压缩包 最新地址:sqljdbc 官方最新地址 解压 解压即用 导入IDEA 新建文件夹 复制…

标题:探索AI绘画:使用深度学习生成艺术

正文: 随着计算机技术的发展,人工智能在各个领域取得了显著的成果。通过训练深度学习模型,AI可以学习大量的艺术作品,从而生成具有独特风格和创意的新作品。 本文将介绍如何使用Python和TensorFlow实现一个简单的AI绘画程序。 二、…

【国信华源2024年首场春季校园招聘面试会举办】

阳春三月,春意盎然,北京国信华源科技有限公司2024年校园招聘活动如期展开。4月2日,成功举办了“国信华源2024年首场春季校园招聘面试会”。 国信华源公司人力资源部热情接待了前来参加面试的同学们,并亲自陪同他们深入探访了企业。…

Docker 哲学 - compose.yaml 指令

compose.yaml 的 image commond working_dir 和 dockerfile的 from cmd workdir 区别在哪里 。为什么 dockerfile制定过了。compose还要再写一个。是处于个性化还是 有不同的意义 如果 dockerfile 的 from 是 node:16 ,compose.yaml 的 images 是 node:18 那么 直接…

使用 Docker 部署 Photopea 在线 PS 工具

1)Photopea 介绍 GitHub:https://github.com/photopea/photopea 官方手册:https://www.photopea.com/learn/ Adobe 出品的「PhotoShop」想必大家都很熟悉啦,但是「PhotoShop」现在对电脑配置要求越来越高,体积越来越大…

00-JAVA基础-反射机制

反射 什么是反射 在Java中,反射(Reflection)是Java语言的一个特性,它允许程序在运行时检查类、接口、字段和方法的信息。通过反射,Java代码能够动态地创建对象、调用方法、改变字段的值等,而无需在编译时…

基础篇3 浅试Python爬虫爬取视频,m3u8标准的切片视频

浅试Python爬取视频 1.页面分析 使用虾米视频在线解析使用方式:https://jx.xmflv.cc/?url目标网站视频链接例如某艺的视频 原视频链接 解析结果: 1.1 F12查看页面结构 我们发现页面内容中什么都没有,video标签中的src路径也不是视频的数据。 1.2 …

linux清理缓存垃圾命令和方法介绍

在Linux系统中,清理缓存和垃圾文件可以通过多种方法完成,这些方法旨在释放磁盘空间、提高系统性能。以下是一些常用的方法,结合了搜索结果中的信息: 1. 使用sync和echo命令清除RAM缓存和交换空间1 清除页面缓存(Page …

不讲概念,讲实操,mysql 分表模糊查询、分页查询 及 merge 表的使用

1.Mysql merge合并表的要求 1.合并的分表必须是 MyISAM 引擎,MyISAN引擎是不支持事务的。2.Merge表只保证合表后数据唯一性,合表前的数据可能会存在重复。3.表的结构必须一致,包括索引、字段类型、引擎和字符集。4.删除 tb_member1 分表正确…

原理图设计的通用规范

原理图各页内容依次为:封面、目录、电源、时钟、CPU、存储器、逻辑、背板(母板)接口等。 原理图上所有的文字方向应该统一,文字的上方应该朝向原理图的上方(正放文字)或左方(侧放文字&#xff…

Whisper对于中文语音识别与转写中文文本优化的实践(Python3.10)

原文:Whisper对于中文语音识别与转写中文文本优化的实践(Python3.10) - 知乎 阿里的FunAsr对Whisper中文领域的转写能力造成了一定的挑战,但实际上,Whisper的使用者完全可以针对中文的语音做一些优化的措施,换句话说,…

【LeetCode热题100】51. N 皇后(回溯)

一.题目要求 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方…

hadoop:案例:将顾客在京东、淘宝、多点三家平台的消费金额汇总,然后先按京东消费额排序,再按淘宝消费额排序

一、原始消费数据buy.txt zhangsan 5676 2765 887 lisi 6754 3234 1232 wangwu 3214 6654 388 lisi 1123 4534 2121 zhangsan 982 3421 5566 zhangsan 1219 36 45二、实现思路:先通过一个MapReduce将顾客的消费金额进行汇总,再通过一个MapReduce来根据金…

RocketMQ是什么?

文章目录 一、RocketMQ是什么?二、RocketMQ 应用场景三、RocketMQ 优缺点1.优点2、缺点 一、RocketMQ是什么? RocketMQ 是一款纯 java、分布式、队列模型的消息中间件,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等。 二、Rocke…

java数据结构与算法刷题-----LeetCode417. 太平洋大西洋水流问题

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 深度优先遍历 深度优先遍历 解题思路:时间复杂度O( …

DIY蓝牙键盘(1) - 理解 键盘报文(免费)

DIY蓝牙键盘(1) - 理解键盘报文 1. 键盘报文体验 一个键盘对于用户的体验是,用户按按键A他能看到字母A会在主机上显示出来。那这是如何实现的? 其实很简单,只要键盘发送下面的两个报文给主机,字母A就能在主机上显示出来。 (1)…

【Qt】Ubuntu20.04.6+Qt5.15.2+QtCreator10.0.1无法输入中文

1、前提条件 1)已经安装了fcitx sudo apt install fcitx sudo apt install fcitx-pinyin sudo apt install fcitx-bin fcitx-table-all sudo apt install fcitx-qt52)系统已经配置fcitx 3)将系统下 /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitx…

CSS3新增的语法(三)【2D,3D,过渡,动画】

CSS3新增的语法(三)【2D,3D,过渡,动画】 10.2D变换10.1. 2D位移10.2. 2D缩放10.3. 2D旋转10.4. 2D扭曲(了解)10.5. 多重变换10.6. 变换原点 11. 3D变换11.1. 开启3D空间11.2. 设置景深11.3. 透视点位置11.4. 3D 位移11…

java数据结构与算法刷题-----LeetCode79. 单词搜索

java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 文章目录 回溯深度优先遍历 回溯深度优先遍历 解题思路:时间复…