编译和链接【三】

文章目录

  • 编译和链接【三】
    • 前言
    • 系列文章入口
    • 编译过程
      • 词法分析
      • 语法分析
      • 语义分析
      • 生成中间代码
      • 汇编
      • 链接

编译和链接【三】

前言

在我大一的时候, 我使用VC6.0对C语言程序进行编译链接和运行 , 然后我接触了VS, Qt creator等众多IDE, 这些IDE界面友好, 使用方便, 例如我最喜欢的VS,一键编译运行。对于大一的我,不需要了解编译的整个过程就可以运行,这无疑是非常棒的,并且增加了我对编程的兴趣,同时也简化了我后续的软件开发, 我只需要关心业务和功能代码即可。

但是今天, 我不想“逃课了”,欢迎来到我的频道,本系列 将会介绍编译中的一系列细节。

在正式开始之前,我要推荐两本书,一本是《程序员的自我修养》,另一本是《鲸书》,这两本书对编译的整个过程做了非常详细,非常完备的介绍,但是恰恰如此,我想很多时候,很多知识在工作上是用不到的,也许这句话在很多年多的我会反驳,但是站在工作一年的现在,我将会给你介绍,我所了解的编译和链接。

系列文章入口

关注我~持续更新

编译和链接【一】

编译和链接【二】

编译过程

在汇编语言中,通常是以段作为标识,来完成某个功能,例如,你可能会看到这样的代码:

start:# code...goto errHandleerrHandle:# code...

上面的代码片里就是在某种情况下,发生出错的时候,统一的跳转到错误处理函数里,而从C/C++的翻译单元到汇编文件的转换,其实就是把C/C++代码中的函数,代码块转换为汇编代码中的代码段,而C/C++程序里的全局变量,静态变量和常量则转换为汇编中的数据段和只读段

总体来说,编译过程可分为以下6步:

  • 词法分析
  • 语法分析
  • 语义分析
  • 中间代码生成
  • 汇编代码生成
  • 目标代码生成

词法分析

这是编译的第一步,主要用来解析程序里的语句。整个过程利用状态机的思想,将语句从左到右进行扫描,一个字符一个字符地读入,然后解析并标识这些字符,最终会分解为最小记号单元:token,常见的token如下:

  • 关键字:autoconstconstexprconsteval
  • 各种标识符:函数名,变量名等
  • 字面量:字符串等
  • 运算符:+, **-**等
  • 分隔符:;(用于标识语句结束)等

例如你有这样的语句:

sum = a + b / c;

经过扫描处理后,会分解为8个token, “sum”, “=”, “a”, “+”, “b”, “/”, “c”, “;”

在我大一学习C语言的时候,常常会使用中文符号,这个时候就会发生编译错误,其实就是发生在这个阶段。

语法分析

语法分析的核心是构建语法树,也就是根据之前分解的token来解析,看看能否构成语法树,例如上个阶段的语句就能构成:

在这里插入图片描述

在解析构建的过程中, 如果发现不能构建成语法树,那么就会报语法错误:syntax error,例如缺少语句结束符号等。

语义分析

如果说,语法分析仅仅是语法上的校验,那么语义分析则是对各种表达式,语句进行检查,例如:函数传参是否匹配,重载决议等,再或者是使用某个变量,但是未定义的情况;或者除数为零了; break在循环语句或switch语句之外出现了;或者在循环语句之外发现 了continue语句;一般都会报语义上的错误或警告。

生成中间代码

在上个阶段,还是以语法树的形式进行存储,我们需要把其转换为中间代码,这种形式类似于伪代码,常见的有:三地址码,P-代码等。

而你的疑惑可能是,既然有了语法树,为什么要转换为中间代码呢?

答案很简单,中间代码是一维线性序列,编译器可以方便的将中间代码翻译为目标代码,例如,我有以下的程序:

#include <iostream>
#include <string>using namespace std;#define MESSAGE "hello world!"#pragma message("build cpp project")int main()
{int a = 3, b = 4;int c = a + b;return 0;
}

使用gcc的命令:-fdump-tree-gimple

可以生成中间代码,这个时候会在你的当前目录下生成一个后缀为gimple的文件,例如我生成的结果

在这里插入图片描述

以上的代码则被转换为:

main ()
{int D.39926;{int a;int b;int c;a = 3;b = 4;c = a + b;D.39926 = 0;return D.39926;}D.39926 = 0;return D.39926;
}

中间码一般和平台是无关的,如果你想将C程序编译为X86平台下的可执行文件,那么最后一步就是根据X86指令集,将中间代码翻译为X86汇编程序。

如果你想编译成在ARM平台上运行的可执行文件,那么就要参考ARM指令集,根据ATPCS规则分配寄存器,将中间代码翻译成ARM汇编程序。

根据上面的三地址码,我们就可以尝试使用汇编指令实现

section .dataa dd 3b dd 4c dd 0section .textglobal _start_start:; Load the value of 'a' into the EAX registermov eax, [a]; Add the value of 'b' to the EAX registeradd eax, [b]; Store the result in 'c'mov [c], eax; Exit the programmov eax, 1          ; syscall number for sys_exitxor ebx, ebx        ; exit code 0int 0x80            ; call kernel

汇编

这个过程就是利用汇编器来把前阶段生成的汇编文件翻译为目标文件,主要工作是参考对应架构的指令集来完成,同时生成一些其他信息。整个过程使用图表形式进行展现:

在这里插入图片描述

链接

通过编译生成的可重定位的目标文件,都是以零地址为链接起始地址进行链接的,也就是说,编译期在将源文件翻译成可重定位的目标文件的过程中,将代码翻译为二进制指令以后,会从零地址开始把各个指令序列放到代码段中,每个函数的入口也是从零地址开始偏移。

让我们看看目标文件的section信息

在这里插入图片描述

你可以看出,不过是地址还是偏移地址,都是从0开始的,这也符合我在开头所说。

那么,如果大家都想把自己放在零地址,链接器又是怎么将各个目标文件组装在一起的呢?

答案很简单,链接器把各个目标文件组装在一起后,我们需要重新修改各个目标文件中变量和函数的地址,这个过程就是:重定位

而一个疑惑就显然地产生了,链接器是怎么知道哪些函数/变量需要重定位呢?

显然,我们需要打表,也就是把需要重定位的符号专门的收集起来,生成一个重定位表,并且以section的形式保存到每个可重定位目标文件中即可。

当然,一个符号,不管其是否需要重定位,都需要收集起来,这就是:符号表,也以section的形式保存到可重定位目标文件中。

在链接器组装过程中,函数的地址发生了变化,在链接器组装之后,需要重新计算和更新函数的新地址,这个过程就是重定位。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

波导阵列天线学习笔记8 高增益、低轴比的3D打印Ka波段圆极化单脉冲天线阵列

摘要&#xff1a; 本文中&#xff0c; 一种3D打印的16x16圆极化单脉冲天线阵列在Ka波段研究&#xff0c;有着高增益和低轴比的特点。此单脉冲天线阵列有着四个低剖面的左旋圆极化子阵列和一个顺序旋转的和差网络。这四个子阵列正交连接着和差网络的输出&#xff0c;保证了传统2…

高通android WIFI debug

参考高通文档&#xff1a;80-76240-16_REV_AA_Wi-Fi_Debug_Techniques 大纲 一、 WLAN Debug Logs –logcat ■ Logcat log logcat is a command-line tool that dumps the log of system messages, ■ Including stack traces when the device throws an error. ■ Need t…

Pytest自动化测试框架总结

1、pytest简介 pytest是Python的一种单元测试框架&#xff0c;与python自带的unittest测试框架类似&#xff0c;但是比unittest框架使用起来更简洁&#xff0c;效率更高。 执行测试过程中可以将某些测试跳过&#xff0c;或者对某些预期失败的case标记成失败能够支持简单的单元…

交叉编译工具链下载和使用

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…

【SVN基础】

软件&#xff1a;ToritoiseSVN 代码版本回退&#xff1a;回退到上一个版本 问题&#xff1a;SVN版本已经提交了版本1和版本2&#xff0c;现在发现不需要版本2的内容&#xff0c;需要回退到版本1然后继续开发。 如图SVN版本已经提交到了107版本&#xff0c;那么本地仓库也已经…

作业:zuoye

1.闹钟&#xff08;错的&#xff09; #include "widget.h" #include "ui_widget.h" #include <QMessageBox>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 初始化定时器objTimer new QTimer(th…

一种非完全图下的TSP求解算法

序 旅行商问题(Traveling Salesman Problem,简称TSP)是组合优化中的一个经典问题,就是给定一组城市和城市之间的距离,找到一条最短路径使得每个城市只被访问一次后返回到起点。 一些传统的解法都是基于完全图的,我在网上也很少找到非完全图的解法,非完全图应该在实际应…

2025.2.11——一、[极客大挑战 2019]PHP wakeup绕过|备份文件|代码审计

题目来源&#xff1a;BUUCTF [极客大挑战 2019]PHP 目录 一、打开靶机&#xff0c;整理信息 二、解题思路 step 1&#xff1a;目录扫描、爆破 step 2&#xff1a;代码审计 1.index.php 2.class.php 3.flag.php step 3&#xff1a;绕过__wakeup重置 ​编辑 三、小结…

Word成功接入DeepSeek详细步骤

原理 原理是利用Word的VBA宏&#xff0c;写代码接入API。无需下载额外插件。 步骤一、注册硅基流动 硅基流动统一登录 注册这个是为了有一个api调用的api_key&#xff0c;有一些免费的额度可以使用。大概就是这个公司提供token&#xff0c;我们使用这个公司的模型调用deepsee…

STM32_USART通用同步/异步收发器

目录 背景 程序 STM32浮空输入的概念 1.基本概念 2. STM32浮空输入的特点 3. STM32浮空输入的应用场景 STM32推挽输出详解 1. 基本概念 2. 工作原理 3. 应用场景 使能外设时钟 TXE 和 TC的区别 USART_IT_TXE USART_IT_TC 使能串口外设 中断处理函数 背景 单片…

Kafka的消费消息是如何传递的?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka的消费消息是如何传递的&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka的消费消息是如何传递的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Kafka 的消息传递机制是基于 发布-订阅 模型…

活动预告 | Power Hour: Copilot 引领商业应用的未来

课程介绍 智能化时代&#xff0c;商业应用如何实现突破&#xff1f;微软全球副总裁 Charles Lamanna 将为您深度解析&#xff0c;剖析其中关键因素。 在本次线上研讨会中&#xff0c;Charles Lamanna 将分享他在增强商业运营方面的独到见解与实战策略&#xff0c;深度解读商业…

IPD项目管理是什么?

IPD项目管理&#xff0c;即整合项目交付管理&#xff0c;是一种创新的管理方式、强调团队协作、优化设计和施工过程的方法。这种管理模式的核心是整合所有项目参与者的专业技能和知识&#xff0c;从项目初始阶段就开始共同合作&#xff0c;以实现项目目标。它特别强调所有参与者…

支付宝安全发全套解决方案

产品价值 ● 通过支付宝的资金能力&#xff0c;让服务商机构通过信息流驱动资金流&#xff0c;在不碰触客户企业资金的同时&#xff0c;为客户企业完成转账。账目清晰&#xff0c;无合规和资质风险。 ● 为服务商提供全链路的资金流动明细信息&#xff0c;服务商可以将这些信息…

关于FANUC机器人示教器型号的说明

关于FANUC机器人示教器型号的说明 如下图所示&#xff0c; 示教器的型号为&#xff1a;A05B-2255-C102#ESW&#xff0c; 如果需要对示教器进行更换或维修测试&#xff0c;只需保证前面8位的型号保持一致即可&#xff0c; 例如下图中的型号&#xff0c; 只需保证A05B-2255-x…

计算机毕业设计SpringBoot校园二手交易小程序 校园二手交易平台(websocket消息推送+云存储+双端+数据统计)(源码+文档+运行视频+讲解视频)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

11vue3实战-----封装缓存工具

11vue3实战-----封装缓存工具 1.背景2.pinia的持久化思路3.以localStorage为例解决问题4.封装缓存工具 1.背景 在上一章节&#xff0c;实现登录功能时候&#xff0c;当账号密码正确&#xff0c;身份验证成功之后&#xff0c;把用户信息保存起来&#xff0c;是用的pinia。然而p…

2.Excel:滨海市重点中学的物理统考考试情况❗(15)

目录 NO12​ 1.数据透视表​ 2. 3.sum函数 4.sumifs客观/主观平均分​ 5.sumifs得分率​ 6.数字格式修改​ NO3/4/5​ sumifs某一组数据相加&#xff0c;某一范围&#xff0c;某一范围的具体点向下拖拉&#xff0c;锁定列&#xff1b;向左右&#xff0c;锁定行F4&#x…

基于YoloV11和驱动级鼠标模拟实现Ai自瞄

本文将围绕基于 YoloV11 和驱动级鼠标实现 FPS 游戏 AI 自瞄展开阐述。 需要着重强调的是&#xff0c;本文内容仅用于学术研究和技术学习目的。严禁任何个人或组织将文中所提及的技术、方法及思路应用于违法行为&#xff0c;包括但不限于在各类游戏中实施作弊等违规操作。若因违…

期权帮 | 聊一聊股指期货交割是什么意思?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 聊一聊股指期货交割是什么意思&#xff1f; 股指期货交割&#xff0c;就是股指期货合约到期时&#xff0c;咱们得按照合约的规定来结束这笔交易。大多数时候&#xff0c;我们都…