程序的执行原理(上)

news2025/1/19 12:59:14

文章目录

  • hello world
  • 程序源文件的本质是0和1
  • hello world文件的ASCII表示
  • 程序被其他程序翻译成不同的格式
    • 预处理阶段
    • 编译阶段
    • 汇编阶段
    • 链接阶段
  • 为什么需要了解编译系统的工作原理?
    • 优化程序性能
    • 理解链接时出现的错误
    • 避免安全漏洞
  • 运行程序
  • 参考

hello world

在这里插入图片描述

程序源文件的本质是0和1

hello程序的生命周期是从一个源程序(或者说源文件)开始的,即程序员通过编辑器创建并保存的文本文件,文件名是 hello.c。源程序实际上就是一个由值0和1组成的位(又称为比特)序列,8个位被组织成一组,称为字节。每个字节表示程序中的某些文本字符。

hello world文件的ASCII表示

大部分的现代计算机系统都使用 ASCII标准来表示文本字符,这种方式实际上就是用一个唯一的单字节大小的整数值来表示每个字符。
在这里插入图片描述

hello.c 程序是以字节序列的方式储存在文件中的。

每个字节都有一个整数值,对应于某些字符。

例如,第一个字节的整数值是 35,它对应的就是字符“# ”。第二个字节的整数值为 105,它对应的字符是“i,依此类推。
每个文本行都是以一个看不见的换行符“\n’来结束的,它所对应的整数值为 10。

像 hello.c 这样只由ASCII 字符构成的文件称为文本文件,所有其他文件都称为二进制文件。

hello.c 的表示方法说明了一个基本思想:

系统中所有的信息一一包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的数据,都是由一串bit表示的。区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。

比如,在不同的上下文中,一个同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令。

作为程序员,我们需要了解数字的机器表示方式,因为它们与实际的整数和实数是不同的。它们是对真值的有限近似值,有时候会有意想不到的行为表现。

程序被其他程序翻译成不同的格式

hello程序的生命周期是从一个高级 C语言程序开始的,因为这种形式能够被人读懂。

然而,为了在系统上运行 hello.c 程序,每条 C语句都必须被其他程序转化为一系列的低级机器语言指令。

这些指令按照一种称为可执行目标程序的格式打好包,并以二进制磁盘文件的形式存放起来。

目标程序也称为可执行目标文件。

在 Unix 系统上,从源文件到目标文件的转化是由编译器驱动程序完成的:

linux> gcc -o hello hello.c

在这里,GCC 编译器驱动程序读取源程序文件 hello.c,并把它翻译成一个可执行目标文件 hello。

这个翻译过程可分为四个阶段完成。
执行这四个阶段的程序(预处理器、编译器、汇编器和链接器)一起构成了编译系统(compilation system)。

在这里插入图片描述

预处理阶段

预处理器(cpp)根据以字符#开头的命令,修改原始的 C 程序。比如hello.c中第 1行的#include <stdio.h> 命令告诉预处理器读取系统头文件stdio.h 的内容,并把它直接插入程序文本中。结果就得到了另一个 C程序,通常是以.i 作为文件扩展名。

编译阶段

编译器(cc1)将文本文件 hello.i 翻译成文本文件 hello.s,它包含一个汇编语言程序。该程序包含函数 main的定义,如下:

main:
subq	$8%rsp
movl	$.LCO,%edi
call	puts
movl	$0%eax
addq	$8%rsp
ret

定义中 2~7行的每条语句都以一种文本格式描述了一条低级机器语言指令.

汇编语言是非常有用的,因为它为不同高级语言的不同编译器提供了通用的输出语言。

汇编阶段

接下来,汇编器(as)将 hello.s 翻译成机器语言指令,把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式,并将结果保存在目标文件 hello.o中。

hello.o文件是一个二进制文件,它包含的 17 个字节是函数 main的指令编码。

如果我们在文本编辑器中打开 hello.o文件,将看到一堆乱码。

链接阶段

请注意,hello程序调用了 printf 函数,它是每个C编译器都提供的标准C库中的一个函数。

printf 函数存在于一个名为 printf.o的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的 hello.o程序中。链接器(ld)就负责处理这种合并。

结果就得到 hello 文件,它是一个可执行目标文件(或者简称为可执行文件),可以被加载到内存中,由系统执行。

为什么需要了解编译系统的工作原理?

对于像 hello.c 这样简单的程序,我们可以依靠编译系统生成正确有效的机器代码。
但是,有一些重要的原因促使程序员必须知道编译系统是如何工作的。

优化程序性能

现代编译器都是成熟的工具,通常可以生成很好的代码。作为程序员,我们无须为了写出高效代码而去了解编译器的内部工作。但是,为了在 C程序中做出好的编码选择,我们确实需要了解一些机器代码以及编译器将不同的 C语句转化为机器代码的方式。

比如,一个 switch 语句是否总是比一系列的 if-else 语句高效得多?

一个函数调用的开销有多?

while循环比 for循环更有效吗?

指针引用比数组索引更有效吗?

为什么将循环求和的结果放到一个本地变量中,会比将其放到一个通过引用传递过来的参数中,运行起来快很多呢?

为什么我们只是简单地重新排列一下算术表达式中的括号就能让函数运行得更快?

理解链接时出现的错误

根据我们的经验,一些最令人困扰的程序错误往往都与链接器操作有关,尤其是当你试图构建大型的软件系统时。

比如,链接器报告说它无法解析一个引用,这是什么意思?

静态变量和全局变量的区别是什么?

如果你在不同的 C文件中定义了名字相同的两个全局变量会发生什么?

静态库和动态库的区别是什么?

我们在命令行上排列库的顺序有什么影响?

最严重的是,为什么有些链接错误直到运行时才会出现?

避免安全漏洞

多年来,缓冲区溢出错误是造成大多数网络和 Internet 服务器上安全漏洞的主要原因。

存在这些错误是因为很少有程序员能够理解需要限制从不受信任的源接收数据的数量和格式。

学习安全编程的第一步就是理解数据和控制信息存储在程序栈上的方式会引起的后果。

运行程序

处理器读并解释储存在内存中的指令。

此刻,hello.c 源程序已经被编译系统翻译成了可执行目标文件 hello,并被存放在磁盘上。要想在 Unix 系统上运行该可执行文件,我们将它的文件名输人到称为 shell 的应用程序中:

linux>  ./hello
hello,world
linux>

shell是一个命令行解释器,它输出一个提示符,等待输人一个命令行,然后执行这个命令。

如果该命令行的第一个单词不是一个内置的 shell 命令,那么 shell 就会假设这是一个可执行文件的名字,它将加载并运行这个文件。

所以在此例中,shell 将加载并运行hello程序,然后等待程序终止。hello 程序在屏幕上输出它的消息,然后终止。

shell随后输出一个提示符,等待下一个输入的命令行。

参考

《深入理解计算机系统》

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

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

相关文章

基于ZLMediaKit的GB28181视频平台demo

GB28181 主要内容 国标的20位id是按照标准来定的&#xff0c;前8位是地域信息&#xff0c;9-10位是行业信息&#xff0c;11-13是设备类型、14是网络标识、后6位为序号 约定以SIP协议作为会话通道的使用标准&#xff0c;以RTP作为语言和视频的载体。联网系统在进行音视频传输及…

AQS和ReentrantLock还能这样理解?

1.公平锁和非公平锁 1.1含义 公平锁:在竞争环境下&#xff0c;先到临界区的线程比后到的线程一定更快地获取得到锁。非公平锁:先到临界区的线程未必比后到的线程更快地获取得到锁。 1.2如何自我实现 公平锁实现&#xff1a;可以把竞争的线程放在一个先进先出的队列上。只要…

webpack plugin

1、基本写法及使用 这里用到 emit 钩子 及make 钩子&#xff0c;前者是串行后者是并行 /*** 1.webpack加载webpack.config.js中所有配置&#xff0c;此时就会new TestPlugin()&#xff0c;执行插件的constructor2.webpack创建compiler对象3.遍历所有plugins中插件&#xff0…

404 - File or directory not found.

iis部署的时候容易出现以下错误&#xff0c;造成的主要原因可能是IIS没有安装好某个组件或插件: 04-找不到文件或目录。 您要查找的资源可能已被删除、名称已更改或暂时不可用。 如果遇到该问题&#xff0c;安装iis的时候记得安装以下

AIGC ChatGPT4总结SQL优化细节操作

数据库SQL优化是一个复杂的过程,它通常涉及到许多不同的技术和方法。以下是一些常用的SQL优化策略: 1. **索引使用**:索引可以极大地加速查询速度。但是,索引并不总是有好处的,因为它们需要额外的空间来存储,并且在插入和更新数据时可能会减慢速度。因此,选择正确的字段…

【C++】类和对象——构造函数和析构函数

今天要学习两个特殊的函数&#xff0c;分别是构造函数和析构函数&#xff0c;它们究竟有什么用呢&#xff1f; 比如说&#xff0c;我们先写一个简单的日期的类 class Date { public:void Init() {_year 1;_month 1;_day 1;}void Print() {cout << _year << &qu…

字符串和内存函数(2)

文章目录 2.13 memcpy2.14 memmove2.15 memcmp2.16 memset 2.13 memcpy void* memcpy(void* destination, const void* source, size_t num); 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到 ‘\0’ 的时候并不会停下来。如果so…

企业计算机服务器中了locked勒索病毒怎么办,勒索病毒解密恢复

计算机网络为企业的生产生活提供了极大帮助&#xff0c;让企业逐步走向数字化办公&#xff0c;但随之而来的网络安全威胁也不断增多&#xff0c;网络勒索病毒病毒攻击企业计算机的事件频发&#xff0c;并且攻击加密手段也在不断提升。近期&#xff0c;云天数据恢复中心再次接到…

接口测试 —— requests 的基本了解

● requests介绍及安装 ● requests原理及源码介绍 ● 使用requests发送请求 ● 使用requests处理响应 ● get请求参数 ● 发送post请求参数 ● 请求header设置 ● cookie的处理 ● https证书的处理 ● 文件上传、下载 requests介绍 ● requests是python第三方的HTTP…

python -opencv 中值滤波 ,均值滤波,高斯滤波实战

python -opencv 中值滤波 &#xff0c;均值滤波&#xff0c;高斯滤波实战 cv2.blur-均值滤波 cv2.medianBlur-中值滤波 cv2.GaussianBlur-高斯滤波 直接看代码吧&#xff0c;代码很简单&#xff1a; import copy import math import matplotlib.pyplot as plt import matp…

第二十章 多线程

20.2创建线程 20.2.1继承Thread类 Thread类是Java.lang包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建议Thread实例。 public class ThreadTest extedns Thread{} run方法格式&#xff1a; public void run(){} 20.1让线…

论设备管理的发展趋势及对策

作者&#xff1a;韩平 设备是企业生产要素的一个重要组成部分&#xff0c;是企业进行生产活动的物质硬件基础&#xff0c;也是决定企业生产效能的重要因素之一。 设备管理又称设备工程&#xff0c;是根据企业生产经营目标&#xff0c;为了提高设备效能&#xff0c;在调查研究…

主播产品话术

以电子产品为例 一、产品特点 1.高效性能:这款产品采用了最先进的技术&#xff0c;确保高效运行&#xff0c;让你的工作更加流畅。 2.便捷操作:设计简洁&#xff0c;操作方便&#xff0c;即使是不熟悉电子产品的人也能轻松上手。 3.时尚外观:多种颜色可选&#xff0c;满足你…

2023年09月 Scratch(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 点击绿旗,运行程序后,舞台上的图形是?( ) A:画笔粗细为4的三角形 B:画笔粗细为5的六边形 C:画笔粗细为4的六角形 D:画笔粗细为5的三角形 答案:D 第2题 如下图所示,从所给…

零编程基础Python的全面学习指南

文章目录 前言什么是编程&#xff1f;Python代码对应的机器码准备开始Windows变量类型整型字符串型布尔类型字符串连接和整数相加if 语句捕获用户输入导入MacWindows游戏时间&#xff01;小结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Pyt…

Postman API Enterprise 10.18.1 Crack

适合您企业的 Postman API 平台 掌控您的 API 环境。构建更好的 API。加快产品开发。 无论您处于 API 之旅的哪个阶段&#xff0c;Postman 都会为您提供帮助 想让您团队的 API 更容易被发现吗&#xff1f;希望减少开发和质量检查之间的滞后时间&#xff1f;想要更快地让新开发…

csdn最新最全pytest系列——pytest-xdist插件之多进程运行测试用例|| pytest-parallel插件之多线程运行测试用例

pytest之多进程运行测试用例(pytest-xdist) 前言 平常我们功能测试用例非常多时&#xff0c;比如有1千条用例&#xff0c;假设每个用例执行需要1分钟&#xff0c;如果单个测试人员执行需要1000分钟才能跑完当项目非常紧急时&#xff0c;会需要协调多个测试资源来把任务分成两部…

还不知道指针和引用的区别,一篇文章教会你

1、引用的概念 1.引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名 2.编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间 比如:孙悟空&#xff0c;可以叫他孙悟空&#xff0c;也可以叫齐天大圣。本质他们就是一个人 2、引用的定…

CentOS 7 使用Fmt库

安装 fmt Git下载地址&#xff1a;https://github.com/fmtlib/fmt 步骤1&#xff1a;首先&#xff0c;你需要下载fmt的源代码。你可以从https://github.com/fmtlib/fmt或者源代码官方网站下载。并上传至/usr/local/source_code/ ​ 步骤2&#xff1a;下载完成后&#xff…

LINUX入门篇【8】----计算机组成原理以及OS知识的总结

前言&#xff1a; 从而本篇文章开始&#xff0c;我们将进入LINUX的进程篇&#xff0c;但学习进程之前&#xff0c;我们首先需要重新认识我们的计算机&#xff0c;并且正确认识到控制进程的OS&#xff0c;即操作系统是怎样在计算机运行的过程中起到作用的。下面就让我们一同去了…