分类 技术向 下的文章

什么是“倒着跑”的程序?

正常的程序都是正着跑的:CPU 里有一个程序计数器(PC),用来记录当前正在执行的指令的地址。执行完 PC 处的指令后,CPU 会接着执行 PC+1 处的指令。

而倒着跑的程序指的是:执行完 PC 处的指令后,程序回过头去执行 PC-1 处的指令。如果你反汇编这个程序,你会看到程序中机器指令的序列也是完全倒过来的,比如程序看起来会先调用函数,后传参。

等等,这样的程序是真实存在的吗?

是的,而且我真的写了一个这样的 x86-64 程序,还把它出成了一道 CTF 逆向题

- 阅读剩余部分 -

是的,这又是一个教你写个编译器的教程。

你可能已经见过无数个教你写编译器的教程了,但它们也许或多或少存在各种问题,导致你看了它们之后,依然觉得无从下手:

  • 教程并非面向“零编译器基础”的人群,理解起来比较费劲。
  • 只教了怎么做一个编译器,但没教为什么这么做,读完之后还是觉得一头雾水。
  • 开始编码之前,需要复杂的环境配置,开局劝退。
  • 上来先做和“编译一个程序”这件事八竿子打不着的东西,跟着教程学一个月才能看到自己的编译器编出一个能跑的程序,反馈周期过长。
  • 最终写出来的只是个解释器,或者不能编译到真实的 ISA(例如输出了某种字节码),或者高度依赖其他框架(例如 LLVM),让人体会不到那种“我真的写出个编译器”的成就感,以及“所有事情都由自己实现”的酣畅感。
  • 实现的编译器只能编译一些过于简单的程序,比如排序算法等等,看起来非常无聊。谁会没事干排序玩啊?
  • 教程及其配套资源非中文,或需要付费,且不开源。

研究生期间,我一直在担任本科编译原理课程的助教。为了让本科生更好地理解编译器工作的原理,在参考多个其他教程之后,我设计了一套全新的,教你从零开始写个编译器的教程:

- 阅读剩余部分 -

SSA, 静态单赋值形式, 是 “单赋值” 的, 所有的量都只会被赋值一次.

在控制流汇聚的时候, 我们可能需要在汇点后的控制流中取得汇点前的多个控制流中更新过后的数据. 此时, 由于其单赋值的特性, 我们没办法简单地表示, 我们拿到的具体是哪一个数据.

为了解决这个问题, Phi 函数应运而生.

- 阅读剩余部分 -

注:本文是高等计算机体系结构课程的作业,因为觉得作业不能白写,而且读书报告似乎被我写成了科普向的文章,所以打算把这些作业发在 blog 上 \_(:з」∠)_

微处理器的结构曾经有过几次重大的革新:流水线和 RISC 概念的诞生,使得处理器的性能和指令吞吐量大幅度提升;多发射、超标量技术的诞生,使得指令级并行性得到了进一步的开发;乱序执行技术的推出,使得处理器的动态调度能力达到了新的顶峰。而在微结构发展的历史中,曾出现过很多让人耳目一新的设计:前有 Cray 设计的向量处理机,后有本文提出的超长指令字架构。

- 阅读剩余部分 -

注:本文是高等计算机体系结构课程的作业,因为觉得作业不能白写,而且读书报告似乎被我写成了科普向的文章,所以打算把这些作业发在 blog 上 \_(:з」∠)_

自流水线的概念被提出起,处理器的性能就进入了一个飞速提升的时代。而随着 RISC、超标量等技术的诞生和发展,指令级并行性的开发越来越被人所重视,指令级并行度本身也在技术的更迭中不断上升。为了提升处理器的性能,进一步挖掘 ILP,人们选择让处理器尽可能同时分析和调度更多的指令。但由于控制转移指令的存在,尤其是条件分支,处理器不得不采用推测执行的方式来跨越基本块的边界,将流水线填得更满——由此,就诞生了分支预测技术。

“分支预测” 技术正如其名,是一种 “预测” 未来的技术。但实际上,它可以做得很简单,例如对所有分支都预测不跳转;也可以做得很复杂,例如结合过往的分支跳转情况,进行各类预测。在本科期间初次了解分支预测技术时,我曾痴迷于此——一度惊讶于简单的计数器居然也可以预知未来,而复杂的多级结构居然可以将预测正确率推上一个常人无法想象的顶峰。

借读书报告的机会,我终于能从历史的角度,学习和认识分支预测器的发展过程。这篇读书报告虽然是针对 TAGE 分支预测器的论文撰写的,但实际上我将课程中提到的所有关于分支预测的文献都大略的看了一遍。本文将结合这些文献,着重探讨 TAGE 分支预测器的技术要点,兼以浅谈分支预测器的普适设计思想。

- 阅读剩余部分 -