第一篇笔记的主题是讨论Hello World程序的生命周期,程序是最简单的hello world程序,使用高级C语言编写。

先介绍整个生命周期中涉及到的几个部分以及相应的概念,然后总结整个生命周期,最后是几个零散的知识点。

程序

#include<stdio.h>
int main(){
printf("Hello World!\n");
system("pause");
return 0;
}

编译系统

基于以下的几个疑问,我们有必要了解编译器如何工作:

  1. 优化程序性能 : 例如 一个switch语句是否比一串if-else语句高效?一个函数调用的开销有多大?while循环和for循环,哪个更有效?
  2. 理解链接时出现的错误 :链接器报告它无法解析一个引用,这是什么意思?静态变量和全局变量的区别是什么?
  3. 避免安全漏洞 :缓冲区溢出错误如何产生?

下面针对Hello World程序,介绍一下编译系统如何工作。

  • 预处理阶段:预处理器(cpp)根据以字符#开头的命令,修改源程序;#include<stdio.h>告诉预处理器读取系统头文件stdio.h的内容,并把它直接插入到源程序中,生成的文件以.i为扩展名。
  • 编译阶段  :编译器(ccl)将.i文件翻译成.s文件,这是一个汇编语言程序。汇编语言为不同高级语言的不同编译器提供了通用的输出语言。
  • 汇编阶段  :汇编器(as)将.s文件翻译成机器语言指令,并打包成可重定位目标程序,也就是.o文件。.o文件是二进制文件,它的字节编码是机器语言指令而不是字符。
  • 链接阶段  :链接器(ld)。printf函数是一个C标准函数,单独存在于一个预编译好的printf.o目标文件中,链接器将其合并到hello.o文件中,生成可执行文件,然后载入内存,等待运行程序。

此时,hello.c源程序已被编译系统翻译成了可执行目标文件hello,存放于磁盘上。需要运行时,用命令解释器(外壳(shell))运行。

计算机的几个相关硬件

  • 总线     :贯穿整个系统的一组电子管道,负责携带信息并在各个部件之间传递信息。传送定长的字节块(字),每个字的字节数(字长)因系统而异。
  • I/O设备:负责系统与外部进行信息交互。上图示例有四个I/O设备:鼠标键盘(用户输入)、显示器(用户输出)和磁盘(存储程序和数据)。每个I/O设备通过一个控制器或适配器与I/O总线相连,负责在两者之间传递信息。
  • 主存    :一个临时存储设备,在处理器运行程序时负责存放程序和程序处理的数据。
  • CPU   :负责解释(或执行)主存中的指令。处理器的核心是一个字长的存储设备(或寄存器),称为程序计数器(PC,注:PC区分“个人计算机”)。任何时刻,PC都指向主存中某条机器语言指令,即PC中存放该指令的地址。从系统通电开始,到系统断电为止,处理器就一直在执行PC指向的指令。执行完之后更新PC,在指向下一条指令,值得一提的是这里的下一条指令并非物理意义上的下一条,也即不一定与上一条指令相邻。这样的简单操作并不多,且围绕着主存、寄存器文件和算数/逻辑单元(ALU)进行,寄存器文件是一个小的存储设备,由一些1字长的寄存器组成,每个寄存器都有唯一的名字;ALU负责计算新的数据和地址。

CPU执行的操作

  • 加载:把一个字节或者字从主存复制到寄存器,并覆盖寄存器原来的值。
  • 存储:把一个字节或者字从寄存器复制到主存的某个位置,病覆盖掉主存该位置原来的值。
  • 操作:把两个寄存器的内容复制到ALU,ALU对这两个内容做算术运算,将结果存放到一个寄存器中,并覆盖掉原来的值。
  • 跳转:从指令本身中抽取一个字,复制到PC中,并覆盖掉PC中原来的值。

现在总结一下运行hello程序的整个过程:

  • 开始时我们先通过键盘鼠标等用户输入设备将高级语言源程序写入电脑,这些程序代码存储在磁盘上。
  • 然后编译系统将高级语言程序代码经过预编译、编译、汇编和链接等操作将C语言代码翻译成机器语言指令,存放在磁盘上。
  • shell等待我们输入一个指令,当我们从键盘输入字符串“./hello”后,shell将字符串逐一读入寄存器,然后存储到存储器。现在主存放着“hello”命令。如下图所示:

  • 当我们输入回车时,shell知道命令输入结束。然后执行一系列操作加载可执行的hello文件,将hello目标文件中的代码和数据从磁盘复制(操作)到主存,利用直接存储器存取(DMA)技术(后续讨论),数据可以从磁盘直接到达主存。现在主存放有运行程序的命令和运行程序所需的机器语言代码。如下图所示:

  • hello的代码和数据加载到主存后,处理器开始执行hello程序的main程序中的机器语言指令,这些指令将结果字符串“Hello World\n”以字节的形式从主存复制到寄存器,然后再复制到显示设备,最后我们在屏幕上看到”Hello World“。过程如下图所示:

以上就是hello world程序整个软硬件配合从输入到输出的整个过程。下面罗列几点上面用到的知识点。

  • 源程序实际上就是一个由值0和1组成的位序列。8个位组成一个字节,每个字节表示程序中的某个文本字符。hello.c程序以字节序列的方式在文件中进行存储。
  • 大部分的现代系统使用ASCII标准来表示文本字符,这种方式实际上使用一个字节表示一个字符。
  • 像hello.c这样只由ASCII字符构成的文件称为文本文件,其他的所有文件均称为二进制文件。

    以此类推:系统中所有的信息都是由一串位表示的,事实上的确如此。区分这些数据的唯一方式是读取这些数据时的上下文。
  • 从上面的过程可以看出,系统很多的时间花费在了信息转移传递的过程:hello程序的机器指令最初是在磁盘上的,当程序加载时,它们被复制到主存;当处理器运行程序时,它们又被复制到处理器。
  • 计算机系统是由硬件和系统软件组成的,他们共同工作来运行应用程序。

最后附上源程序的ASCII码图

深入理解计算机系统(1)--hello world程序的生命周期的更多相关文章

  1. 教你理解微信小程序的生命周期和运行原理

    转自:http://blog.csdn.net/tsr106/article/details/53052879  写微信小程序,他的生命周期不能不知道,不知道小程序就会出现各种bug而无法解决.小助君 ...

  2. 理解微信小程序的生命周期和运行原理

    写微信小程序,他的生命周期不能不知道,不知道小程序就会出现各种bug而无法解决.小助君公众号带你学习小程序的生命周期和运行原理. 小程序由两大线程组成:负责界面的线程(view thread)和服务线 ...

  3. asp.net MVC 应用程序的生命周期

    下面这篇文章总结了 asp.net MVC 框架程序的生命周期.觉得写得不错,故转载一下. 转载自:http://www.cnblogs.com/yplong/p/5582576.html       ...

  4. 浅析 - iOS应用程序的生命周期

    1.应用程序的状态 状态如下: Not running  未运行  程序没启动 Inactive          未激活        程序在前台运行,不过没有接收到事件.在没有事件处理情况下程序通 ...

  5. iOS 应用程序的生命周期

    iOS 应用程序的生命周期(网络资源总结) http://blog.csdn.net/totogo2010/article/details/8048652 http://www.cocoachina. ...

  6. ASP.NET 应用程序(Application)生命周期概述

    原文:ASP.NET 应用程序(Application)生命周期概述 引用MSDN:ASP.NET 应用程序生命周期概述 本 主题概述应用程序生命周期,列出重要的生命周期事件,并描述如何编写适合应用程 ...

  7. [转]iOS 应用程序的生命周期

    OS的应用程序的生命周期,还有程序是运行在前台还是后台,应用程序各个状态的变换,这些对于开发者来说都是很重要的. iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的.在后台时,程序会受到 ...

  8. [转] 微信小程序之生命周期

    本篇文章介绍小程序的生命周期,由于小程序分为应用和页面两个部分,所以小程序的生命周期就涉及到三个部分,分别是: 应用的生命周期 页面的生命周期 应用的生命周期对页面生命周期的影响 一.应用的生命周期 ...

  9. 小程序的生命周期 launchApp

    https://developers.weixin.qq.com/miniprogram/dev/api/launchApp.html?search-key=生命周期 launchApp(OBJECT ...

随机推荐

  1. ACM-ICPC(11/8)

    URAL 1005 给定一些石头的重量,要求分成两个部分最相近.二进制暴力枚举. #include <bits/stdc++.h> using namespace std; ]; int ...

  2. UOJ 35 后缀数组

    后缀数组裸题,求排名第1~n的后缀,想相邻后缀的最长公共前缀. 集训队模板就是硬lO(∩_∩)O哈哈~ #include <cstdio> #include <cmath> # ...

  3. iOS 代码混淆--pch实现

    之前实现代码的混淆一般是使用sh脚本,不过也是需要把一写需要混淆的方法写到一个文件中(除非是使用特定的命名规范统一混淆), 现在发现,实现代码的混淆pch 文件就可以轻松完成! 1,在新建的工程中 创 ...

  4. 如何从GitHub获取源代码

    如何从GitHub获取源代码 github是当前流行的开源项目托管网站,里面有成千上万的项目值得学习和借鉴,可以把项目源代码下载到本地研究.本文介绍如何获取github的源代码. 方法1 - 克隆(C ...

  5. 【洛谷P1288】取数游戏II

    取数游戏II 题目链接 显然,由于一定有一个0,我们可以求出从初始点到0的链的长度 若有一条链长为奇数,则先手可以每次取完一条边上所有的数, 后手只能取另一条边的数,先手必胜: 反之若没有奇数链,后手 ...

  6. JavaEE权限管理系统的搭建(四)--------使用拦截器实现登录认证和apache shiro密码加密

    RBAC 基于角色的权限访问控制(Role-Based Access Control)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限.这就极大地简化了权限的管理.在一个 ...

  7. 【XP-IE8】XP系统的IE8无法正常访问图片,按钮无反应,不执行JS脚本代码

    环境: Windows XP ,自带的是IE6,另外安装的 IE8 . 状况: 使用IE8浏览内网网站,点击登录按钮,没有反应.滚动图片新闻不显示.但使用Chrome浏览器,一切正常,说明是IE8某处 ...

  8. ASP.NET mvc 验证码 (转)

    ASP.net 验证码(C#) MVC http://blog.163.com/xu_shuhao/blog/static/5257748720101022697309/ 网站添加验证码,主要为防止机 ...

  9. Redis分布式锁的正确实现方式(Java版)

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  10. Knowledge Point 20180305 数据在计算机中的表示

    计算机发明的初衷就是用于帮助我们加工和处理数据,虽然时至今天计算机看起来无所不能,但它根本上还是在做数据的加工和处理,数据的机器层次表示将直接影响到计算机的结构和性能. 在计算机中,采用数字化方式来表 ...