从零学习开发一个RISC-V操作系统(二)丨GCC编译器和ELF格式
本篇文章的内容
- 一、GCC(GUN Compiler Collection)
- 1.1 GCC的命令格式
- 1.2 GCC的主要执行步骤
- 1.3 GCC涉及的文件类型
- 二、ELF简介
- 2.1 ELF文件格式图
- 2.2 ELF文件处理的相关工具
- 2.3 练习
本系列是博主参考B站课程学习开发一个RISC-V的操作系统的学习笔记,计划从RISC-V的底层汇编指令学起,结合C语言,在Ubuntu 20.04上开发一个简易的操作系统。一个目的是通过实践操作学习和了解什么是操作系统,第二个目的是为之后学习RISC-V的集成电路设计打下一定基础。本系列持续不定期更新,分享出来和大家一同交流进步。
博主是微电子科学与工程专业的学生,对软件和操作系统难免有理解不到位的地方。如有谬误敬请不吝告知,不胜感激。
参考课程及文章:
【Bilibili】[完结] 循序渐进,学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春
一、GCC(GUN Compiler Collection)
GCC是一个由GNU(一个自由软件基金会组织)开发的,遵循GPL许可证发行的编译器套件,是一个编译器的集合。支持 C、C++、Objective-C、Fortran、Ada 和 Go 语言等多种语言前端,已被移植到多种计算机体系架构上,如 x86、ARM、RISC-V 等。在之后的课程中使用的也是GCC作为编译工具。GCC 的初衷是为 GNU 操作系统专门编写一款编译器,现已被大多数 “Unix-like”操作系统(如 Linux、BSD、MacOS 等)采纳为标准的编译器。
1.1 GCC的命令格式
- GCC
操作选项文件名
| 常用操作选项 | 含义 |
|---|---|
| -E | 只做预处理(将包含的宏语言头文件转化为C语言文件) |
| -c | 只编译(生成机器指令)不链接(与库文件相连),生成目标文件.o |
| -S | 生成汇编代码 |
-o file | 将输出的文件生成到由file指定文件名的文件中 |
| -g | 在输出的文件中加入支持调试的信息 |
| -v | 显示输出详细的命令执行过程信息 |
1.2 GCC的主要执行步骤

- 编译
编译(使用cc1程序,这里针对 C 语言,不同的语言有自己的编译器):编译器完成 “预处理” 和 “编译”,“预处理” 指处理源文件中以 “#” 开头的预处理指令,譬如 #include、#define 等;“编译” 则针对预处理的结果进行一系列的词法分析、语法分析、语义分析,优化后生成汇编指令,存放在 .o 为后缀的目标文件中。
- 汇编
汇编(使用as程序):汇编器将汇编语言代码转换为机器(CPU)可以执行的指令。
- 链接
链接(使用ld程序):链接器将汇编器生成的目标文件和一些标准库(譬如 libc)的.o文件组合,形成最终可执行的应用程序。

1.3 GCC涉及的文件类型
.c:C 源文件.cc/.cxx/.cpp:C++ 源文件.i:经过预处理的 C 源文件.s/.S:汇编语言源文件(.S文件中还包含宏指令,.s`文件中是纯汇编指令).h:头(header)文件.o:目标(object)文件.a/.so:编译后的静态库(archive)文件和共享库(shared object)文件a.out:可执行文件,常见于Unix系统
二、ELF简介
ELF(Executable Linkable Format)是一种 Unix-like系统上的二进制文件格式标准。ELF文件格式对于底层的操作系统开发非常重要,当程序需要在底层进行优化,调试,排错等操作时,ELF文件可以更好地帮助程序员完成任务。ELF 标准中定义的采用 ELF 格式的文件分为以下4类:

2.1 ELF文件格式图

ELF格式是在程序编译链接过程中生成的文件采用的通用格式。如果直接用文本编辑器或二进制编辑器打开该文件,无法直接看出文件中包含的信息,因为该文件是用二进制书写的。但是其中每一个字节都有其特定的含义,这些字节的排布遵从ELF文件格式。ELF文件中最主要的部分包括ELF文件头(ELF Header)、程序头表(Program Header Table)和节头表(Section Header Table)。
ELF文件头(ELF Header)中包含了该文件的一些基本信息,例如该文件运行在哪种体系架构上,运行的版本号等。
ELF文件的主体部分是多个程序节(Section)。如上图所示,.text中一般存放指令(程序的具体操作),.init中一般存放一些初始化操作,.data中存放程序要操作的数据,例如在程序中定义的全局变量等。
在程序加载到内存前,一般都要对各个节进行对齐操作。例如,当程序按4KB进行分节时,如果.test节中的内容本身很少,且不加任何操作,它就会按4KB的大小独占一部分区域。为了节省内存空间,我们对各个节的内容按属性进行归并,例如.text和.init都存放了一些程序运行的指令,所以我们可以对齐进行归并,形成了程序段(Segment)。一个程序段可以由多个程序节构成。
ELF程序头表(Program Header Table)从运行角度描述了程序的内容,它是程序运行视图的体现。程序头表中包含了该文件中哪几个节要归并成一个段,每一个段占用的大小,入口地址等信息。其中包含的信息只有在运行时才会用到。
ELF节头表(Section Header Table)中存放的该文件中包含的节的信息,包括节的名称,节的入口地址,节的大小等。节头表从链接的角度描述了程序的内容,它是程序链接视图的体现。其中的信息只有链接时才会用到。
2.2 ELF文件处理的相关工具
对程序员而言,手动查看和调试ELF文件的过程是十分繁琐的,GNU为程序员提供了相关的处理工具软件,存放在Binutils工具包中。该工具包中的小程序如下:
- ar:归档文件,将多个文件打包成一个大文件。
- as:被 gcc 调用,输入汇编文件,输出目标文件供链接器 ld 连接。
- ld:GNU 链接器。被 gcc 调用,它把目标文件和各种库文件结合在一起,重定位数据,并链接符号引用。
- objcopy:执行文件格式转换。
- objdump:显示 ELF 文件的信息。
- readelf:显示更多 ELF 格式文件的信息(包括DWARF 调试信息)。
- …
2.3 练习
使用gcc编译代码并使用Binutlis工具对生成的目标文件和可执行文件(ELF格式)进行分析,具体要求如下:
- 编写一个简单的打印“Hello world!”的程序源文件
hello.c- 对源文件进行本地编译,生成针对支持x86_64指令集架构处理器的目标文件
hello.o- 查看
hello.o的文件的ELF文件头信息- 查看
hello.o的节头表- 对
hello.o进行反汇编,并查看hello.c的程序源码和机器指令的对应关系
首先,在Vim编辑器中编写一个简单的hello.c程序:

如果我们需要hello.o文件,说明只需要编译,不需要链接,所以在终端中输入如下代码:
$ gcc -c hello.c -o hello.o
查看hello.o文件中ELF文件头信息(-h就表示查看文件头header):
$ readelf -h hello.o

查看hello.o的节头表(-SW表示显示节头表,并展宽表示):
$ readelf -SW hello.o

要对文件进行反汇编,首先要重新编译程序,并使用gdb使其携带调试信息,之后使用objdump对程序hello.o进行反汇编。可以看到每一条C语句对应的汇编指令,可以利用该工具对程序进行调试和优化。
$ rm hello.o
$ gcc -g -c hello.c
$ objdump -S hello.o

原创笔记,码字不易,欢迎点赞,收藏~ 如有谬误敬请在评论区不吝告知,感激不尽!博主将持续更新有关嵌入式开发、机器学习方面的学习笔记。
相关文章:
从零学习开发一个RISC-V操作系统(二)丨GCC编译器和ELF格式
本篇文章的内容 一、GCC(GUN Compiler Collection)1.1 GCC的命令格式1.2 GCC的主要执行步骤1.3 GCC涉及的文件类型 二、ELF简介2.1 ELF文件格式图2.2 ELF文件处理的相关工具2.3 练习 本系列是博主参考B站课程学习开发一个RISC-V的操作系统的学习笔记&…...
论文阅读_大语言模型_Llama2
英文名称: Llama 2: Open Foundation and Fine-Tuned Chat Models 中文名称: Llama 2:开源的基础模型和微调的聊天模型 文章: http://arxiv.org/abs/2307.09288 代码: https://github.com/facebookresearch/llama 作者: Hugo Touvron 日期: 2023-07-19 引用次数: 11…...
当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用及论文写作、拓展分析
生态系统服务是人类从自然界中获得的直接或间接惠益,可分为供给服务、文化服务、调节服务和支持服务4类,对提升人类福祉具有重大意义,且被视为连接社会与生态系统的桥梁。自从启动千年生态系统评估项目(Millennium Ecosystem Asse…...
k8s Limits 限制内存
Limits 限制内存 在 Kubernetes (K8s) 中,可以使用 Limits(资源限制)来限制 Pod(容器)使用的内存数量。此处的 Limits 表示 Pod 在 K8s 集群中可用的最大内存量。一旦 Pod 内存使用超过这个限制,可能会触发…...
单片机第三季-第三课:STM32开发板原理图、配置、浮点运算单元
目录 1,开发板原理图 2,浮点运算单元(FPU) 1,开发板原理图 课程视频比较早,介绍了三款开发板。观看视频时用的开发板说和51单片机共板的STM32核心板,将51单片机从底座拆下来后,安…...
观察者模式 发布-订阅模式(设计模式与开发实践 P8)
文章目录 观察者模式运用实现 观察者模式 定义:他用来定义对象之间一种一对多的依赖关系,当一个对象状态发生改变时,所有依赖他的对象都会得到通知 运用 如果我们使用过 DOM 上的事件函数,那就接触过观察者模式 document.body…...
【日常业务开发】Java实现异步编程
【日常业务开发】Java实现异步编程 Java实现异步编程什么是异步异步的八种实现方式异步编程线程异步Future异步CompletableFuture实现异步Spring的Async异步Spring ApplicationEvent事件实现异步消息队列ThreadUtil异步工具类Guava异步 CompletableFuture异步编排工具类创建异步…...
学习笔记|模数转换器|ADC原理|STC32G单片机视频开发教程(冲哥)|第十七集:ADC采集
文章目录 1.模数转换器(ADC)是什么?手册说明: 2.STC32G单片机ADC使用原理19.1.1 ADC控制寄存器(ADC_CONTR)19.1.2 ADC配置寄存器(ADCCFG)19.1.4ADC时序控制寄存器(ADCTIM)19.3 ADC相…...
OpenCV实现“蓝线挑战“特效
原理 算法原理可以分为三个流程: 1、将视频(图像)从(顶->底)或(左->右)逐行(列)扫描图像。 2、将扫描完成的行(列)像素重新生成定格图像…...
容器管理工具 Docker生态架构及部署
目录 一、Docker生态架构 1.1 Docker Containers Are Everywhere 1.2 生态架构 1.2.1 Docker Host 1.2.2 Docker daemon 1.2.3 Registry 1.2.4 Docker client 1.2.5 Image 1.2.6 Container 1.2.7 Docker Dashboard 1.3 Docker版本 二、Docker部署 2.1 使用YUM源部署…...
js判断数据类型的方法
简单数据类型用:typeof, // 可以直接typeof空格接数据的方式,也可以typeof(数据)的方式使用 console.log(typeof ""); //string(检验字符串没问题) console.log(typeof 1); //number(检验数字没问题) console.log(typ…...
达梦数据库随系统开机自动启动脚本
写一个脚本,实现在服务器开机后自动启动达梦数据库的功能。 1. 在/etc/init.d/目录下,编写脚本,并将脚本命名为startdm.sh。脚本内容实现如下: #!/bin/bash #chkconfig:2345 80 90 #decription:启动达梦# 切换到 dmdba 用户 su …...
Python开发利器之VS Code
Python官方提供了一个Python集成开发环境(IDE): IDLE (Integrated Development and Learning Environment)。 它提供了一个图形用户界面,可以让开发者编写、调试和执行Python程序。IDLE包含Python解释器、代码编辑器、调试器和文件…...
【Axure视频教程】输入框控制滑动评分条
今天教大家在Axure里如何制作输入框控制滑动评分条的原型模板,可以通过鼠标左右拖动滑块,也可以点击条形让滑块移动到指定位置,标签和输入框里会返回具体的分值,分值由滑块所在的位置动态计算而成;也可以在输入框里输入…...
【学习笔记】[AGC064C] Erase and Divide Game
有点难😅,看到比自己低一级的选手场切这道题就更绷不住了😇 考虑 从低到高位 建立 trie \text{trie} trie 树,但是因为是对反串建立的,所以编号连续的点在 trie \text{trie} trie 树上的位置是分散的😅 …...
算法通关村-----数组中元素出现次数问题
数组中出现次数超过一半的数字 问题描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。详见剑指offer39 问题分析 最直接的方式就是使用hashMap,遍历给定数组,…...
Qt-键盘消息的传递-键盘消息的获取-C++
文章目录 1.概述2.焦点3.强制获取键盘消息4.键盘常用组合方法5.总结 1.概述 QKeyEvent 类用来描述一个键盘事件。当键盘按键被按下或者被释放时,键盘事件便会被发送给拥有键盘输人焦点的部件。 QKeyEvent 的 key() 函数可以获取具体的按键,对于 Qt 中给…...
数据结构与算法(五)--链表概念以及向链表添加元素
一、前言 今天我们学习另一种非常重要的线性数据结构–链表,之前我们已经学习了三种线性数据结构,分别是动态数组,栈和队列。其中队列我们额外学习了队列的另一种实现方式–循环队列。其实我们自己实现过前三个数据结构就知道,它…...
计算机视觉与深度学习-图像分割-视觉识别任务02-目标检测-【北邮鲁鹏】
目录标题 参考目标检测定义深度学习对目标检测的作用单目标检测多任务框架多任务损失预训练模型姿态估计 多目标检测问题滑动窗口(Sliding Window)滑动窗口缺点 AdaBoost(Adaptive Boosting)参考 区域建议 selective search 思想慢…...
Flink——Flink检查点(checkpoint)、保存点(savepoint)的区别与联系
Flink checkpoint Checkpoint是Flink实现容错机制最核心的功能,能够根据配置周期性地基于Stream中各个Operator的状态来生成Snapshot,从而将这些状态数据定期持久化存储下来,从而将这些状态数据定期持久化存储下来,当Flink程序一…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
