《逆向工程权威指南》—第1章1.1节指令集架构

简介:

本节书摘来自异步社区《逆向工程权威指南》一书中的第1章1.1节指令集架构,作者【乌克兰】Dennis Yurichev(丹尼斯),更多章节内容可以访问云栖社区“异步社区”公众号查看。

第一部分 指令讲解
逆向工程权威指南
在最初接触C/C++时,我就对程序编译后的汇编指令十分着迷。按照从易到难的顺序,我循序渐进地研究了C/C++语言编译器生成汇编指令的模式。经过日积月累的努力,现在我不仅可以直接阅读x86程序的汇编代码,而且能够在脑海里将其还原成原始的C/C++语句。我相信这是学习逆向工程的有效方法。为了能够帮助他人进行相关研究,我把个人经验整理成册,以待与读者分享。

本书包含大量x86/x64和ARM框架的范例。如果读者熟悉其中某一种框架,可以跳过相关的篇幅。


0afa9bbcb89c93b25ee148f4b8d72e4c5b5c9f05

第1章 CPU简介
逆向工程权威指南
CPU是执行程序机器码的硬件单元。简要地说,其相关概念主要有以下几项。

指令码:CPU受理的底层命令。典型的底层命令有:将数据在寄存器间转移、操作内存、计算运算等指令。每类CPU都有自己的指令集架构(Instruction Set Architecture,ISA)。

机器码:发送给CPU的程序代码。一条指令通常被封装为若干字节。

汇编语言:为了让程序员少长白头发而创造出来的、易读易记的代码,它有很多类似宏的扩展功能。

CPU寄存器:每种CPU都有其固定的通用寄存器(GPR)。x86 CPU里一般有8个GPR,x64里往往有16个GPR,而ARM里则通常有16个GPR。您可以认为CPU寄存器是一种存储单元,它能够无差别地存储所有类型的临时变量。假如您使用一种高级的编程语言,且仅会使用到8个32位变量,那么光CPU自带的寄存器就能完成不少任务了!

那么,机器码和编程语言(PL)的区别在哪里?CPU可不像人类那样,能够理解C/C++、Java、Python这类较为贴近人类语言的高级编程语言。CPU更适合接近硬件底层的具体指令。在不久的将来,或许会出现直接执行高级编程语言的CPU,不过那种尚未问世的科幻CPU必定比现在的CPU复杂。人脑和计算机各有所长,如果人类直接使用贴近硬件底层的汇编语言编写程序,其难度也很高——因为那样很容易出现大量的人为失误。可见,我们需要用一种程序把高级的编程语言转换为CPU能受理的底层汇编语言,而这种程序就是人们常说的编译器/Compiler。

1.1 指令集架构
在x86的指令集架构(ISA)里,各opcode(汇编指令对应的机器码)的长度不尽相同。出于兼容性的考虑,后来问世的64位CPU指令集架构也没有大刀阔斧地摒弃原有指令集架构。很多面向早期16位8086 CPU的指令,不仅被x86的指令集继承,而且被当前最新的CPU指令集继续沿用。

ARM属于RISC[1] CPU,它的指令集在设计之初就力图保持各opcode的长度一致。在过去,这一特性的确表现出了自身的优越性。最初的时候,所有ARM指令的机器码都被封装在4个字节里[2]。人们把这种运行模式叫作“ARM模式”。

不久,他们就发现这种模式并不划算。在实际的应用程序中,绝大多数的CPU指令[3]很少用满那4个字节。所以他们又推出了一种把每条指令封装在2个字节的“Thumb”模式的指令集架构。人们把采用这种指令集编码的指令叫作“Thumb模式”指令。然而Thumb指令集并不能够封装所有的ARM指令,它本身存在指令上的局限。当然,在同一个程序里可以同时存在ARM模式和Thumb模式这两种指令。

之后,ARM的缔造者们决定扩充Thumb指令集。他们自ARM v7平台开始推出了Thumb-2指令集。Thumb-2指令基本都可封装在2个字节的机器码之中,2个字节封装不下的指令则由4字节封装。现在,多数人依然错误地认为“Thumb-2指令集是ARM指令集和Thumb指令集的复合体”。实际上,它是一种充分利用处理器性能、足以与ARM模式媲美的独立的运行模式。在扩展了Thumb模式的指令集之后,Thumb-2现在与ARM模式不相上下。由于Xcode编译器默认采用Thumb-2指令集编译,所以现在主流的iPod/iPhone/iPad应用程序都采用了Thumb-2指令集。

64位的ARM处理器接踵而至。这种CPU的指令集架构再次使用固定长度的4字节opcode,所以不再支持Thumb模式的指令。相应地,64位ARM工作于自己的指令集。受到指令集架构的影响,ARM指令集分为3类:ARM模式指令集、Thumb模式指令集(包括Thumb-2)和ARM64的指令集。虽然这些指令集之间有着千丝万缕的联系,需要强调的是:不同的指令集分别属于不同的指令集架构;一个指令集绝非另一个指令集的变种。相应地,本书会以3种指令集、重复演示同一程序的指令片段,充分介绍ARM应用程序的特点。

除了ARM 处理器之外,还有许多处理器都采用了精简指令集。这些处理器多数都使用了固定长度的32位opcode。例如MIPS、PowerPC和Alpha AXP处理器就是如此。

[1] Reduced instruction computing /精简指令集。

[2] 这种固定长度的指令集,特别便于计算前后指令的地址。有关特性将在13.2.2节进行介绍。

[3] 即MOV/PUSH/CALL/Jcc等指令。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

相关文章
|
存储 并行计算 安全
我们自己的芯片指令集架构——龙芯架构简介
我们自己的芯片指令集架构——龙芯架构简介
2864 6
|
芯片
软件体系结构 - 精简指令集架构 (RISC)
【4月更文挑战第17天】软件体系结构 - 精简指令集架构 (RISC)
259 1
|
缓存 编译器
软件体系结构 - 指令集架构
软件体系结构 - 指令集架构
327 0
|
存储
嵌入式微处理器的系统架构中指令系统
嵌入式微处理器的系统架构中指令系统
217 0
|
算法 编译器
【计算机架构】响应时间和吞吐量 | 相对性能 | 计算 CPU 时间 | 指令技术与 CPI | T=CC/CR, CC=IC*CPI
【计算机架构】响应时间和吞吐量 | 相对性能 | 计算 CPU 时间 | 指令技术与 CPI | T=CC/CR, CC=IC*CPI
1868 1
|
存储 并行计算 编译器
【计算机架构】程序指令计数 | 功耗计算 | 电力功耗 | 安德尔定律(Amdahl‘s Law)
【计算机架构】程序指令计数 | 功耗计算 | 电力功耗 | 安德尔定律(Amdahl‘s Law)
427 1
|
存储 人工智能 编译器
【AI系统】CPU 指令集架构
本文介绍了指令集架构(ISA)的基本概念,探讨了CISC与RISC两种主要的指令集架构设计思路,分析了它们的优缺点及应用场景。文章还简述了ISA的历史发展,包括x86、ARM、MIPS、Alpha和RISC-V等常见架构的特点。最后,文章讨论了CPU的并行处理架构,如SISD、SIMD、MISD、MIMD和SIMT,并概述了这些架构在服务器、PC及嵌入式领域的应用情况。
1109 5
|
存储 设计模式 编译器
软件体系结构 - 复杂指令集架构 (CISC)
【4月更文挑战第18天】软件体系结构 - 复杂指令集架构 (CISC)
661 6
|
存储 编译器 数据处理
CPU架构和指令集
不同的CPU架构通常使用不同的指令集。每种CPU架构都有其自己的一组特定的机器指令,这些指令用于执行计算机程序。不同的CPU架构之间的指令集是不兼容的,这意味着编写的程序通常需要根据目标CPU的架构进行编译或汇编,以确保它们能够在该CPU上正确运行。 一些常见的CPU架构包括:
|
安全 Java
架构系列——面试必问:volatile的可见性、防止指令重排序以及不能保证原子性的解决方式
架构系列——面试必问:volatile的可见性、防止指令重排序以及不能保证原子性的解决方式