第3章 程序的机器码表示

什么是机器码?
机器码是对诸如操作数据、管理内存、读写在存储设备上的数据、通过网络通信等底层操作进行编码的字节序列。

什么是汇编码?
汇编码是机器码的文本表示,给出了程序中的各个指令。

什么是X86-64?
X86-64是一种机器语言,用于今天的台式电脑、笔记本电脑、大型数据中心、超级计算机等机器上的大部分处理器上。这种语言有很长的历史,开始于1978年的Intel公司的第一个16位的处理器,然后拓展到32位,最近的不部分都是64位。沿着这条线,为了更好的利用半导体技术、满足市场需要,添加了许多特征。虽然主要是由Intel公司驱动的,但是Intel的竞争对手AMD也作出了重要的贡献。导致现在的X86-64具有独特的功能设计,只有从历史的角度看才有意义。X86-64还具有向后兼容的能力,这种特性是不被现代编译器和操作系统使用的。

32位机器和64位机器
计算机工业最近已从32位机器迁移到了64位机器。32位机器只能利用大约4GB的随机访问内存。随着内存价格不断下降,计算需求和数据量不断增加,突破32位机器能访问的内存限制已变得经济上可行且技术上可期。现在的64位机器可使用多达256TB(2^{48}字节),且很容易拓展到使用16EB(2^{64}字节)。虽然很难想象有那么大内存的机器的样子,但是要记住:在32位机器很常见的20世纪70年代和80年代,4GB的内存似乎也是很大的内存。

计算机执行的是机器码

基于编程语言的规则、目标机器的指令集、操作系统遵守的约定,编译器通过一系列的阶段来生成机器码。比如GCC的C编译器先生成汇编码,后调用汇编器和链接器来从汇编码中生成可执行机器码

在这一章里,我们将仔细地研究机器码汇编码

当使用诸如C语言和Java等高级语言编程时,程序的机器级别详细实现是向程序员屏蔽的。而当使用汇编语言编程时,程序员必须指定用于执行一次计算所需的底层指令。

在多数情况下,在由高级语言提供的更高级的抽象上工作要更有效率和更可靠。由编译器提供的类型检查帮助检测许多编程错误,确保以一致的方式引用和操作数据。现代有优化功能的编译器生成的代码通常跟一个有经验的汇编程序员手写的代码效率一样。用高级语言编写的程序能被编译和在多台不同的机器上执行,而汇编码是高度机器相关的。

为什么要花费时间研究机器码?

  • 即使编译器做了生成汇编码的大部分工作,但能阅读和理解机器码也是程序员的一项重要技能。
  • 使用合适的命令行参数来调用编译器,编译器会生成一个汇编码形式的输出文件。通过阅读汇编码,我们能理解编译器的优化功能和分析潜在的低效率代码。
  • 如我们将在第5章里体会到的那样,寻求最大化关键代码的性能的程序员通常会尝试对源代码的做不同的修改,每编译一次并检查汇编代码来了解程序的运行效率。
  • 程序员学习汇编代码的需求随着时间的推移发生了变化,以前是要求能直接用汇编码编写程序,现在是能阅读和理解编译器生成的代码。

而且,由高级语言提供的抽象有时会隐藏程序的运行时信息。

  • 当使用线程包来写并发程序时,理解不同线程如何共享程序数据和保持数据私有,怎样精确地访问共享数据是非常重要的。这些信息在机器码中是可见的。
  • 程序遭受攻击的的许多方式都涉及程序存储运行时控制信息的细节。许多攻击都利用了系统程序中的弱点来覆盖信息,从而获取了系统的控制权。理解这些漏洞如何出现,以及如何防御攻击需要具备程序的机器码表示的知识。

在这一章里,我们将学习一种特定的汇编语言,了解C程序是如何被编译成这种形式的机器码的。

阅读由编译器生成的汇编码需要具备不同于手工编写汇编码不同的什么技能?

能理解经典编译器在将C结构转换成机器码时都做了哪些事?

相对于用C代码表示的计算,带优化功能的编译器可重排执行顺序、消除不必要的计算、用更快的操作替换较慢的操作、甚至能将递归计算编程迭代计算等。

理解源代码和汇编码之间的关系通常是一个挑战,有点像拼一个跟包装盒上的图片稍微不同的图。这是一个逆向工程,通过研究系统并反向推导系统是如何被创建的。在这里,前述的系统就是一个机器生成的汇编程序。这就简化了逆向工程的任务,因为生成的代码遵循相当规则的模式,且我们可以运行实验,让编译器为不同的程序生成汇编码。

在本章里,我们给出了许多示例,提供了许多练习来说明汇编语言和编译器的不同方面。在这里,掌握细节是理解更深入和更基础的概念的前提。

花时间来研究这些示例、做这些练习、测试你的答案跟参考答案是很重要的

我们的展示是基于X86-64,将集中在被GCC和Linux使用的特征子集上。这就使得我们避免了X86-64的许多复杂性和奥秘版的特征。

我们的展示集中在编译C代码生成的机器码程序的类型上。因此,我们不会去介绍X86-64的许多支持早期微处理器编码的特征。

本章的主要内容
首先,介绍C语言、汇编码、机器码之间的关系。
然后,介绍X86-64的细节

  • 从数据的表示和操作、控制的实现等开始。我们会看到在C语言中诸如ifwhileswitch语句等控制结构是如何实现的。
  • 然后,我们介绍函数的实现,包括程序是如何维护一个运行时栈来支持函数间的数据和控制等信息的传递,以及局部变量的存储等。

接着,考虑诸如数组、结构体、联合体等数据结构在机器级别是如何实现的。有了这些机器级别编程的背景后,我们讨论内存访问越界、系统容易遭受缓冲区溢出攻击等问题。
最后,介绍使用GDB调试器来检查机器码程序的运行时行为,以及展示有关浮点数数据和操作的机器码程序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352