• C语言编译执行]


    介绍
     
     
      现在C语言跨的领域非常之多,如游戏、嵌入式、智能电器等。为什么不直接用汇编或机器语言直接写呢?原因是汇编和机器语言受到计算机体系结构的影响。直接用某种体系结构的汇编或机器指令写出来的程序只能在这种体系结构的计算机上运行
     
      C语言的好处是各种体系结构的计算机都有各自的C编译器,可以把C程序编译成各种不同体系结构的机器指令,这意味着用C语言写的程序只需稍加修改甚至不用修改就可以在各种不同的计算机上编译运行
     

      
    hello,world
     
      我们从简单hello,world开始——有人说了,又来了,这个“hello,world”,好多博友都写这种东西烦不烦?呵呵,那我写的也许跟他们说的不一样呢?或者理解的跟别人有不一样的地方。
     
      先写个程序我们看看。
      
    源程序(或者源文件):是程序员通过文本编辑器创建并保存的文本文件。
    源程序实际就是由0和1组成的位序列,这些位8个一组,成为字节,每个字节通过ASCII字符集(大部分是)对应一个文本字符。
                                     下面是上面程序对应的16进制数字表示

                                      在终端输入man ascii看看ascii表

    操作步骤:

                 

                 查看16进制格式

                 回复到文本格式

                                     我们看看对应的二进制是什么样的?——这个也是在磁盘中的存储状态。

     
    总结:
      系统中所有的信息——包括磁盘文件、存储器中的程序,存储器中存放的用户数据以及网络上传送的数据,都是由一串比特表示的。
     
    思考:
      同样的一套字节序列可能在不同的上下文中表示一个整数、浮点数、字符串或者机器指令。——这取决于数据对象的上下文。
     
    我们该做什么?
      做为程序员,我们需要了解数字的机器表示方式,因为它们与常见的整数和实数是不同的。
     
    使用参考:
     

     
    翻译
     
      
     
      源程序是能够被人读懂的,为了能在系统上运行,我们需要把C语句通过其他程序转化为一系列的低级机器语言指令。然后这些指令按照一种称为“可执行目标程序“的格式打包好,并以二进制磁盘文件的形式存放起来。
     
      在Linux系统上,从源文件到目标文件(可执行目标程序文件)的转化是由编译器驱动程序完成的。如下图:

    编译系统

      我们用GCC工具观察每个阶段。(GCCGNU Compiler CollectionGNU编译器套装
     
    预处理阶段

                                     查看main.i的部分源码

    总结:预处理器(cpp)根据以字符#开头的命令,修改原始C程序,结果得到了另一个C程序(还是C程序),通常以i做为文件扩展名。

     编译阶段

     

                                     查看main.s的源码

    总结:将C语言文本文件翻译成汇编语言文本文件。——汇编语言是非常有用的,因为它为不同高级语言的不同编译器提供了通用的输出语言。

     汇编阶段
     

                                     打开源代码,注意此时为二进制磁盘文件,还有注意操作步骤

                                     此时为乱码,需要进行:%!xxd操作

                                     查看指令

    总结:汇编器(as)将main.s翻译成机器语言指令,把这些指令打包成为一种“可重定位目标程序“的格式,并将结果保存到main.o文件中,main.o是二进制文件,它的字节编码是机器语言指令而不是字符(所以用文本编译器看会出现乱码)。

     链接阶段
     

                                     按照汇编阶段操作,查看部分指令码

    总结:程序中调用了printf函数,它是C标准库的一个函数,printf函数存在于一个名为printf.o的单独的预编译目标文件中。连接器(ld)负责把printf.o的预编译目标文件进行并入,结果就得到a.out文件。

    NOTE:a.out是可执行的目标文件,而main.o是可重定位目标程序文件。——可执行目标文件加载到系统存储器后,由系统负责执行。而可重定位目标程序文件是提供给链接器使用,执行并入操作。

     
    总结
     
      这一篇主要是学习gcc编译器的编译过程,对整个过程有所熟悉。如果有好的知识点,望大家赐教。
     
      要知后事如何,且听下回分解。
    介绍
     
      上一篇a.out(hello,world程序)执行之后发生了什么?这次通过系统硬件和操作做粗略的描述,这样对我们也是有一些帮助的。
     
      如果中间若有误,请不吝赐教。
     
     从键盘上读取a.out命令
     
      当我们打开我们的终端的时候,shell程序会执行它的指令,等待我们的输入。
      当我们在键盘上输入"a.out",敲回车时,shell就知道我们结束了命令的输入。然后shell的指令就会逐一读取目标文件a.out的代码和数据到寄存器,再把代码和数据拷贝到主存储器。
                                     流程图如下

                                     那么在硬件中是如何奔跑的呢?
     

    科普普及:

    1、主存用来存放指令和指令处理的数据。

    2、处理器(CPU的简称)是解释(或执行)存储在主存中指令的引擎。在任何一个时间点上,CPU中的PC(程序计数器)都指向主存中的某条机器语言指令。

     3、有一种DMA(直接存储器存取)技术,数据可以不通过处理器而直接从磁盘到达主存储器。

    从存储器写输出串到显示器
     
     1、 一旦a.out目标文件中的代码和数据被加载到了主存储器,CPU就开始执行main.c程序的主程序中机器语言指令。
     2、 这些指令将"hello,world\n"串中的字节从主存储器中拷贝到寄存器文件。
     3、 再从寄存器中文件拷贝到显示设备,最终显示在屏幕上。
     
    流程图:
      

                                      那么这些在硬件中是如何奔跑的呢?
     
     
     

    总结
     
    从两个角度分析上面的问题:
      机器指令:最初是在磁盘上——》(程序加载时)拷贝到主存——》(处理器运行指令时)从主存拷贝到处理器。
      数据串:最初是在磁盘上——》拷贝到主存——》显示设备。
     
     
    推荐
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    分类: C Language
    标签: C Language
  • 相关阅读:
    09、Vue.js 3 —— 事件处理
    03、Vue.js 3 —— 模板语法
    vagrant 的介绍与使用
    Asp.Net Core 中的Swagger中间件
    chkconfig和systemd服务管理工具 init.d
    02、Vue.js 3 —— app应用 与 vm组件实例
    01、vue.js 3 笔记(只是本人笔记,大家请自行到官网看文档)
    Linux中的 打包、解压缩 命令(无废话)
    07、Vue.js 3 —— 条件渲染
    0x05、设计模式原则 —— 开闭原则
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2560748.html
Copyright © 2020-2023  润新知