Datawhale 硅基生物进化论 202602第3次笔记

作业:

从github上下载老师的资料

https://github.com/embedded-idea/AJourneyFrom0and1

1. 准备文件(关键!路径不能错)
  • 在compiler这个文件下:
  • compiler.py:课本里给的编译器源码(核心文件,实现编译逻辑);
  • program.asm:你要编译的汇编源文件(自己写的汇编代码,比如之前提到的main相关指令)。
2. 执行编译器(运行 Python 代码)
  • 打开电脑的 "命令提示符(CMD)" 或 "终端";
  • 先切换到这个文件夹的路径(cd /d "E:\Datawhale 2026\从零入门计算机系统202602\compiler");
  • 输入运行命令:python compiler.py
  • 回车执行,编译器会自动读取同目录的program.asm,编译后生成program.bin(目标机器码文件)。

记事本打开.bin 文件显示乱码 → 正常现象,是文本编辑器解析二进制数据的必然结果。

用 Hex 编辑器或命令行查看十六进制机器码:在文件所在目录执行以下命令(Windows 系统):

复制代码
certutil -dump program.bin

输出文件的十六进制内容如下:

作业完成!

笔记:

编译器的定义、作用与工作流程,通过 C 编译器实例建立感性认知,掌握简易 Python 编译器的实现逻辑,抓住编译器 "高级表示转低级表示" 的核心本质。

一、编译器基础定义与核心作用

  1. 定义 :将人类编写的高级语言源代码 翻译为机器可执行的机器码目标程序的软件工具,不仅完成翻译,还会做错误检查和程序优化。
  2. 核心作用(为何需要编译器)
    • 硬件适配:CPU 仅能识别机器码,高级语言必须经编译器转为指令序列才能运行;
    • 提前检错:在程序运行前发现类型不匹配、变量未定义等语法 / 语义错误;
    • 性能优化:通过循环优化、内联、寄存器分配等让程序运行更快;
    • 跨平台特性:同一份源码可针对不同 CPU / 系统编译出对应的可执行文件 / 库。

二、编译器的形象类比与常见 C 编译器

  1. 类比 :编译器是高级语言(中文)机器语言(英文,0 和 1) 之间的 "翻译官",让计算机理解人类编写的代码;
  2. 常见 C 编译器:GCC(GNU Compiler Collection)、Clang(LLVM 的 C 语言前端)、MSVC(Microsoft Visual C++)。

三、C 语言编译器的翻译全流程

C 编译器将.c 源码转为可执行文件分为4 个核心阶段,最终 Windows 生成.exe 文件,Linux 生成.elf 文件:

  1. 预处理 :处理#include(头文件包含)、#define(宏定义)等预处理指令;
  2. 编译:把 C 语言源代码翻译为汇编语言;
  3. 汇编:把汇编语言进一步翻译为机器码;
  4. 链接:将多个目标文件、库函数组合,生成最终的可执行文件。

四、C 代码编译为汇编语言的实操解析

int main(){int a=9;int b=19;return a+b;}为例

以 GCC 编译器、x86 架构 64 位处理器为环境,核心分为 3 步:

1. 词法 / 语义分析 + 中间表示(IR)

编译器将代码转为抽象语法树,生成中间表示,明确代码执行逻辑:

  • 分配变量 a,赋值 9;分配变量 b,赋值 19;
  • 执行 a+b 运算,返回运算结果。

2. 生成汇编语言(简化版,带核心注释)

asm

复制代码
main:
push    rbp         ; 保存旧的栈帧指针
mov     rbp,rsp     ; 设置新的栈帧
mov     DWORD PTR [rbp-4],9  ; 给int a赋值9,存储在栈中
mov     DWORD PTR [rbp-8],19 ; 给int b赋值19,存储在栈中
mov     eax,DWORD PTR [rbp-4] ; 把a的值加载到返回值寄存器eax
add     eax,DWORD PTR [rbp-8] ; 把b的值加到eax,完成a+b
pop     rbp         ; 恢复旧的栈帧
ret                 ; 返回eax中的结果(a+b),作为程序退出码

3. 机器运行时的核心细节

  • rbp/rsp:栈帧管理寄存器,负责保存 / 设置栈指针,处理函数调用;
  • eax:约定俗成的返回值寄存器,用于存储函数的返回结果;
  • 局部变量 a、b:存储在栈中,对应 rbp 的偏移量位置;
  • 真正的运算:由add指令执行,最终通过ret指令将结果返回操作系统。

五、简易 Python 编译器的实现(核心:不到 200 行代码,覆盖编译器最小闭环)

1. 整体结构

分为入口函数核心函数两部分,实现 "读源文件→预处理→译机器码→写目标文件" 的最小闭环:

表格

函数部分 核心职责
入口函数 调用核心编译函数,捕捉语法错误并提示,编译结束后输出compiling completed
核心函数compile_program() 编译器的核心,承担所有实质性编译工作

2. 核心函数compile_program()的执行步骤

  1. 读取源文件:打开同目录下的program.asm汇编源文件,逐行读取并去除注释、多余空白;
  2. 构造指令对象:为每条有效汇编指令构造Code类对象,拆解操作码(OPcode)操作数(寄存器、立即数等);
  3. 翻译机器码:调用compile_code()方法,将汇编指令转为二进制机器码;
  4. 写入目标文件:将机器码按顺序写入program.bin文件,生成可在虚拟机 / 自制 CPU 上运行的可执行代码。

3. 运行与扩展说明

  • 运行条件:机器安装 Python 环境,直接执行编译器脚本compiler.py
  • 文件要求:汇编源文件必须命名为program.asm,且与编译器脚本在同一目录;
  • 扩展方向:可自行修改代码,实现动态指定源文件名、增加更多编译功能等。

六、总结

  1. 编译器的本质:高级表示(源代码 / 汇编)向低级表示(机器码)的转化工具,伴随检错、优化、链接等附加功能;
  2. 编译的核心逻辑:无论工业级还是简易编译器,都遵循 "读取源文件→预处理→翻译→生成目标文件" 的核心流程;
  3. 简易编译器的价值:覆盖编译器的最小闭环,是初学者入门编译原理的最佳实操范例,理解其逻辑即可抓住编译器的核心思想。
  4. 编译器是一款运行在电脑上的翻译软件,专门把程序员写的、人能看懂的高级语言代码,翻译成 CPU 能执行的机器码,同时还会检查代码错误、优化程序性能,它和 CPU 一个是软件、一个是硬件,没有从属关系
相关推荐
sakiko_37 分钟前
UIKit学习笔记2-组件嵌套、滚动视图等
笔记·学习·objective-c·swift·uikit
Alice-YUE2 小时前
【JS高频八股】什么是闭包?
开发语言·javascript·笔记·学习
宵时待雨2 小时前
linux笔记归纳3:linux开发工具
linux·运维·笔记
摇滚侠3 小时前
Java 零基础全套视频教程,面向对象(高级),笔记 105-120
java·开发语言·笔记
tq10864 小时前
程序行为的效应构成:约束、规则与延迟固化的统一视角
笔记
Alice-YUE4 小时前
前端图片优化完全指南:从格式到加载的全面提速方案
前端·笔记·学习
Stella Blog4 小时前
狂神Java基础学习笔记Day05
java·笔记·学习
枷锁—sha4 小时前
【CTFshow-pwn系列】03_栈溢出【pwn 073】详解:静态编译下的自动化 ROP 链构建
网络·汇编·笔记·安全·网络安全·自动化
你数过天上的星星吗4 小时前
Python学习笔记二(函数、类与对象)
笔记·python·学习
Titan20245 小时前
C++11学习笔记
c++·笔记·学习