The Kollected Kode Vicious

Kode Vicious - @kode_vicious

  下载本文的PDF版本 PDF

Kode Vicious

赞美反汇编器

从硬件的底层细节中可以学到很多东西。

 

亲爱的 KV,

我读过足够多的你的专栏,明白你经常强调的一个主题是源代码是供人阅读的,包括未来的自己,以及代码如何被解释器(如 Python)或编译器处理,不如使代码对下一个读者清晰易懂重要。你似乎在说,我们的工具会理解我们的意思,我们应该把解释器或编译器当作一个黑盒子,它神奇地将我们的源代码转化为运行代码。我觉得你忽略了理解软件的一个重要部分,那就是编译后的代码在机器上执行时会发生什么——毕竟,没有计算机直接执行 C、C++ 或 Rust;它们运行的是编译后的二进制文件。当你遇到一个错误,仅仅因为编译器、链接器、汇编器或工具链的其他部分犯了一个错误而只在二进制文件中出现时,这肯定会不时发生。那该怎么办呢?

后端反汇编

 

亲爱的反汇编,

的确,在过去的 50 年里,软件行业内部有许多人和许多运动,他们将开发者和开发工作进一步从机器代码和汇编语言中转移开——而且并非没有充分的理由。在计算机技术短暂的历史中,高级语言的抽象化使得软件和服务的爆炸式增长成为可能,而非程序员每天都认为这是理所当然的。我们这些经常在技术底层工作的人都知道,这些抽象化以及开发者远离机器的趋势是有代价的。

在软件系统中,有许多问题如果不很好地理解我们所使用的机器的底层细节——有些人可能会说是最低层细节——就无法正确理解,当我试图解释这些事情,却得到在该行业工作多年的那些人的茫然凝视时,我感到震惊和愤怒。这种态度可以用我在高中时听到的一句话来概括,当时我正在学习我的第一门汇编语言,那甚至在当时也是一台古老的机器 DEC-10。“你永远不需要使用这个,因为将来所有语言都将是像 Fortran 和 Cobol 这样的高级语言,”这是辅导我们计算机实验室的数学老师们的口头禅。

关于这句话有趣的是,它在两个不同的方面都是错误的。首先,他们选择的语言虽然今天仍在使用,但远非软件开发中的主流语言,这意味着它们并不是这些老师认为的全部和最终目标。第二个谬论是,我在第一次接触汇编和机器代码时学到的东西在我的职业生涯中将毫无用处,但事实并非如此。

虽然我手工编写的最后一段汇编代码(并最终出现在商业产品中)是在 30 年前编写的,但我通过直接与硬件交互——甚至没有 C 语言(即带有 for 循环的汇编语言)的缓冲——所学到的教训至今仍历历在目,并使我能够追踪到难以解决的错误,以及重大的性能问题。过去我曾写过关于理解算法以及这些解决问题的表达方式如何与良好的性能相关联的文章(“了解你的算法”。Kode Vicious。acmqueue 16(6),2019;https://queue.org.cn/detail.cfm?id=3310152),但另一方面是理解运行你的算法的机器实际上是如何工作的。理解计算机系统的底层区域需要什么?KV 的建议分为三个部分:从小处着手。从小处着手。从小处着手。

从处理器和计算机硬件的小端入手。现代笔记本电脑、台式机或服务器系统是一个极其复杂的设备,在很大程度上是通过特性堆积而成,这些特性会让任何刚接触计算机领域的人完全分心。你想要从一个小系统开始,特性很少,指令集也很小,这样你就可以希望一次性将几乎所有细节都塞进你的脑海中。对称多处理、多级缓存、指令的推测执行、长流水线以及所有其他为了在摩尔定律末期提高性能而添加的硬件创新,稍后再学习它们很重要。很少有人一开始就通过坐下来演奏莫扎特或 Fats Waller 来学习钢琴,所以你不应该试图在第一天就攀登超标量处理器的顶峰。

2021 年开始的一个好地方是小型、廉价的嵌入式处理器,而我绝对不是指 Raspberry Pi 或任何类似的设备。当前的 Pi 基于复杂的 ARMv8 设计,它会让你头晕目眩,就像《驱魔人》中的琳达·布莱尔一样。不要从那里开始。一个更好的起点是流行的 Atmel AVR 芯片,它可以在 Arduino 和业余爱好者及嵌入式系统设计师使用的其他板卡上找到。这些处理器是 8 位的——是的,你没看错,8 位——系统,很像 20 世纪 80 年代早期的微型计算机,它们具有小内存、慢处理速度、少量寄存器,最重要的是,一套小巧且易于记忆的汇编操作(操作码)。

这些约束实际上帮助你学习机器,而不会受到许多无关的干扰。这种架构的另一个优点是,指令需要一个或两个时钟周期,具体取决于它们是内部操作还是 I/O 操作。指令具有较小且已知的周期时间,这使得更容易思考你正在查看的代码的性能。以这种方式获得性能方面的经验是能够理解更大、更复杂架构的性能的关键。KV 怎么强调都不过分,你想要从一种小型且易于理解的汇编语言开始。去看看英特尔、ARM 或其他大型处理器的任何数据手册,你就会明白我的意思。AVR 指令集在一页纸上就足够了。

阅读小程序。我曾向各个级别(从高到低)的语言开发者提出过这个建议,但是当你试图学习机器的最低层级时,这甚至更加重要。所有 C 程序员学习的规范的“Hello world”程序,当它被静态链接时,会生成一个包含数百万条指令的二进制文件。Brooks Davis 在 2016 年 BSDCan 技术会议上做了一个精彩的演讲,描述了执行它时会发生什么(https://www.bsdcan.org/2016/schedule/events/676.en.html)。

大多数 Arduino 入门编程教程中的示例,那些闪烁 LED 的示例,与我建议的示例大小相当。稍后你可以开发一个代码编辑器,它会演变成邮件阅读器和 Web 浏览器,这似乎是所有软件项目随时间推移的进程,但现在只需打开和关闭灯即可。有两种方法可以检查这些小程序。第一种是查看为这些嵌入式设备构建 C 或更高级别代码的各种编译器的输出,例如 Arduino IDE,或基于 LLVM 和 GNU 的交叉编译器。你可以通过使用 objdump 程序转储代码来查看代码,或者如果你有理解 AVR 指令集的调试器,则可以在调试器中查看代码。调试器是更有趣的环境,因为你不仅可以阅读代码,还可以执行代码、停止代码、检查寄存器和内存等。来自 LLVM 的 LLDB 和来自 GNU 的 GDB 都具有汇编模式,因此你甚至可以在更高级别的语言和汇编器之间切换。

编写少量底层代码。我 30 年前编写的那段汇编代码只有几页长,部分原因是它所做的事情很简单(从微型计算机上的并行端口拉取音频数据),而且因为它使用的是功能强大的 CISC(复杂指令集计算机)汇编语言(Motorola 68K)。CISC 汇编语言比机器代码更接近 C,并且通常具有代表你完成大量工作的操作码。AVR 可以被认为是 RISC(精简指令集计算机)处理器系列中的一员,其中每条指令都非常简单,复杂的运算必须由这些指令构建而成。今天仍然编写的大部分原始汇编代码都遵循这种少量指令的模型。

当你刚开始时,你希望能够尽可能地将整个程序记在脑海中。一旦你熟悉了你的第一个简单的汇编语言和你正在使用的机器架构,你完全有可能查看一两页的汇编代码,不仅知道它应该做什么,还知道机器将为你逐步做什么。当你查看高级语言时,你应该能够理解你打算让它做什么,但通常你不知道你的意图将如何转化为行动——汇编和机器代码是行动发生的地方。

培养这些技能将使你远远超越在业余爱好者板卡上闪烁 LED 的程度。能够将这些相同的技能应用于更大型、更复杂的机器,使得找到各种各样的海森堡 bug(“Kode Vicious Bugs Out.” Kode Vicious。acmqueue 4(3),2006;https://queue.org.cn/detail.cfm?id=1127862)、优化系统以提高功耗和性能,以及理解诸如 ROP(面向返回的编程)和缓冲区溢出等底层安全攻击的后果成为可能。如果没有这些技能,你将被降级到软件的云雾缭绕的上层,这很好,直到工具或你的硬件或软件之神让你失望。

KV

 

Kode Vicious,凡人称之为 George V. Neville-Neil,从事网络和操作系统代码的编写,以此为乐并以此营利。他还教授各种与编程相关的课程。他的兴趣领域是代码探险、操作系统和重写你的糟糕代码(好吧,也许不是最后一个)。他获得了马萨诸塞州波士顿东北大学的计算机科学学士学位,并且是 、Usenix 协会和 IEEE 的成员。Neville-Neil 与 Marshall Kirk McKusick 和 Robert N. M. Watson 合著了《FreeBSD 操作系统设计与实现》(第二版)。他是一位狂热的自行车爱好者和旅行者,目前居住在纽约市。

版权 © 2021 归所有者/作者所有。出版权已授权给 。

acmqueue

最初发表于 Queue 第 19 卷,第 2 期
数字图书馆中评论本文





更多相关文章

Catherine Hayes, David Malone - 质疑评估非加密哈希函数的标准
虽然加密和非加密哈希函数无处不在,但在它们的设计方式上似乎存在差距。存在许多由各种安全需求驱动的加密哈希标准,但在非加密方面,存在一定程度的民间传说,尽管哈希函数历史悠久,但尚未得到充分探索。虽然针对真实世界数据集的均匀分布很有意义,但在面对具有特定模式的数据集时,这可能是一个挑战。


Nicole Forsgren, Eirini Kalliamvakou, Abi Noda, Michaela Greiler, Brian Houck, Margaret-Anne Storey - DevEx 实践
随着领导者们在财政紧缩和人工智能等变革性技术的背景下寻求优化软件交付,DevEx(开发者体验)在许多软件组织中越来越受到关注。技术领导者们凭直觉接受,良好的开发者体验能够实现更有效的软件交付和开发者幸福感。然而,在许多组织中,旨在改进 DevEx 的拟议倡议和投资难以获得支持,因为业务利益相关者质疑改进的价值主张。


João Varajão, António Trigo, Miguel Almeida - 低代码开发效率
本文旨在通过展示使用基于代码、低代码和极端低代码技术进行的实验室实验结果来研究生产力差异,从而为该主题提供新的见解。低代码技术已清楚地显示出更高的生产力水平,为低代码在短期/中期内主导软件开发主流提供了强有力的论据。本文报告了程序和协议、结果、局限性以及未来研究的机会。


Ivar Jacobson, Alistair Cockburn - 用例至关重要
虽然软件行业是一个快节奏且令人兴奋的世界,其中不断开发新的工具、技术和技巧来服务于商业和社会,但它也很健忘。在它急于快速前进的运动中,它容易受到时尚潮流的摆布,并且可能会忘记或忽略某些它面临的永恒问题的成熟解决方案。用例,最初于 1986 年引入,并在后来普及,就是这些成熟的解决方案之一。





© 保留所有权利。

© . All rights reserved.