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

案例一:关于编译优化

请自写一段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编译器处理结果):

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker实战教程 第1章 Linux快速入门

2-1 Linux介绍 为什么要学Linux 三个不得不学习 课程需要:Docker开发最好在Linux环境下。 开发需要:作为一个后端程序员,是必须要掌握Linux的,这是找工作的基础门槛。 运维需要:在服务器端,主流的大型服…

JVM中常见垃圾收集器介绍

常见垃圾收集器 垃圾收集器介绍垃圾收集器使用命令及默认值串行垃圾收集器并行垃圾收集器CMS(并发)垃圾收集器G1收集器(Garbage-First Collector)面试题:为何新生代和老年代采取的算法不一样? 垃圾收集器介绍 GC算法…

ArrayList与线性表详解

1.线性表 线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表有:顺序表、链表、队列…… 线性表在逻辑上是线性结构,也就是说是连续的一条直线。但是在物理结构上不一定是连续的&#xff…

VGA显示器驱动设计与验证

1.原理 场同步信号的单位是像素点 场同步信号的单位是一行 60的含义是每秒钟刷新60帧图像 全0表示黑色 2.1 CLK_gen.v module CLK_gen(input wire sys_clk ,input wire sys_rst_n ,output wire CLK_out ,output wire locked );parameter STATE1b0; reg [1:0] cnt; r…

E5071C是德科技E5071C网络分析仪

181/2461/8938产品概述: E5071C ENA 矢量网络分析仪,9 kHz 至 20 GHz,配有增强型 TDR 测量选件。E5071C 网络分析仪具有较高的射频性能和较快的速度,并具有宽频率范围和全面的功能。它是制造和研发工程师们测试频率范围在 20 GHz…

uniapp自定义卡片轮播图

效果图 1、封装组件 <template><view><!-- 自定义卡片轮播 --><swiper class"swiperBox" :previous-margin"swiper.margin" :next-marginswiper.margin :circular"true"change"swiperChange"><swiper-ite…

Windows11安装MySql-8.0.36安装详细教程(保姆级教程)

之前一直用的mysql5.7&#xff0c;最近导入一个项目一直报错&#xff0c;经查阅发现数据库mysql版本太老&#xff0c;今天特地重头下载安装配置一下&#xff0c;做个记录供大家参考。 下载安装包&#xff1a; 下载地址&#xff1a;https://dev.mysql.com/downloads/ 进入后选…

SpringBoot(48)-使用 SkyWalking 进行分布式链路追踪

Spring Boot&#xff08;48&#xff09;- 使用 SkyWalking 进行分布式链路追踪 介绍 在分布式系统中&#xff0c;了解各个服务之间的调用关系和性能表现是非常重要的。SkyWalking 是一款开源的分布式系统监控与分析平台&#xff0c;能够帮助我们实现分布式系统的链路追踪、性…

Xshell Mobaxterm等终端工具连接不上服务器,显示 SSH服务器拒绝密码。请再试一次。解决办法

问题解决办法&#xff1a; &#xff08;1&#xff09;需要查看配置SSH密钥时&#xff0c;输入的password密码和当前users_name cd /home/: 查看当前系统下的用户名 注意上图中的登录名是服务器端linux下自己设置的user_name用户名&#xff1a; 所以需要将fl改为&#xff1a…

python 利用xpath 爬取一周天气

需求&#xff1a; 爬取 中国天气网指定城市一周的天气&#xff0c;以天津为例 实现&#xff1a; 1&#xff0c;先找到一周的数据位置。 divs html.xpath("//div[classhanml]") 2&#xff0c;再遍历每天。 trs div.xpath("./div/div[2]/table//tr[position…

院内感染的相关因素分析(Boruta联合SHAP分析2)R

院内感染的相关因素分析&#xff08;Boruta联合SHAP分析2&#xff09;R 和鲸社区一键运行代码 院内感染是指住院患者在医疗机构内发生的感染&#xff0c;是医院管理中常见且严重的问题。院内感染不仅会延长患者住院时间&#xff0c;增加医疗费用&#xff0c;还会严重威胁患者生…

概率论经典题目-二维随机变量及分布--由概率密度求分布函数和概率

解答&#xff1a; 由概率密度函数求解分布函数的公式可知&#xff1a; 辅助图形加以确定积分上下限

【JavaWeb】Day32.MySQL概述

什么是数据库 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 像我们日常访问的电商网站京东&#xff0c;企业内部的管理系统OA、ERP、CRM这类的系统&#xff0c;以及大家每天都会刷的头条、抖音类的app&#xff0c;那这些大家所…

Django路由分发的三种方式以及命名空间namespce——附带源码解析

目录 1. 前言 2. include常规路由分发 3. include源码解析 4. 路由分发的第二种写法 5. 路由分发的第三种写法 6. 小结 7. 有关namespace 8. 最后 1. 前言 本篇文章主要是讲解路由分发的三种方式。当然&#xff0c;你可能在想&#xff0c;一般做路由分发只需要一个incl…

云计算存在的安全隐患

目录 一、概述 二、ENISA云安全漏洞分析 三、云计算相关系统漏洞 3.1 概述 3.2 漏洞分析 3.2.1 Hypervisor漏洞 3.2.1.1 CVE-2018-16882 3.2.1.2 CVE-2017-17563 3.2.1.3 CVE-2010-1225 3.2.2 虚拟机漏洞 3.2.2.1 CVE-2019-14835 3.2.2.2 CVE-2019-5514 3.2.2.3 CV…

css 属性值计算过程

1.css 属性值计算过程 某个元素从所有CSS属性没有值&#xff0c;到所有CSS属性都有值的过程1.确定声明值 2.层叠 3.继承 4.使用默认值 1.确定声明值 样式表总共有两类&#xff1a;作者样式表&#xff08;自己写的样式&#xff09;和浏览器样式表 html <h1 class"text&…

前视声呐目标识别定位(三)-部署至机器人

前视声呐目标识别定位&#xff08;一&#xff09;-基础知识 前视声呐目标识别定位&#xff08;二&#xff09;-目标识别定位模块 开发了多波束前视声呐目标识别定位模块后&#xff0c;自然期待能将声呐部署至AUV&#xff0c;实现AUV对目标的抵近观测。原本规划着定位模块不…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果 一、简单介绍 二、简单视频放大抖动效果实现原理 三、简单视频放大…

面试经典150题【131-140】

文章目录 面试经典150题【131-140】123.买卖股票的最佳时机III188.买卖股票的最佳时机IV二分查找的板子&#xff1a;35.搜索插入位置74.搜索二维矩阵162.寻找峰值33.搜索旋转排序数组34.在排序数组中查找元素的第一个和最后一个位置153.寻找旋转排序数组中的最小值4.寻找两个正…

练习 18 Web [RoarCTF 2019]Easy Calc

表达式注入&#xff0c;被屏蔽字符的处理方式 一开始先看一下前端的源码 有一个calc.php&#xff0c;肯定需要打开 这是calc中的代码 <?php error_reporting(0); if(!isset($_GET[num])){show_source(__FILE__); }else{$str $_GET[num];$blacklist [ , \t, \r, \n,\,…