处理器不知道它被要求执行的是代码还是数据。它可以同时是一个或两个。 CPU 将尝试执行给定的任何内容。
如果执行失败,它会产生诸如“遇到无效指令”或“指令引用的内存不可访问”或“除以零”或“权限不足”等操作系统将(希望)处理。如果它知道如何解决问题(虚拟内存通常基于此机制),或者让应用程序处理此事件或终止应用程序,它将解决问题。
有不同的反汇编程序。有些是“愚蠢的”反汇编程序,因为他们不会尝试对可执行文件格式做出太多或任何意义,他们只会尝试对给出的任何内容进行反汇编。其他人将反汇编标记为代码的文件部分,他们将从入口点位置开始反汇编(每个可执行文件都有一个应该由 OS/CPU 开始执行的位置)并使用各种启发式方法进行合理的反汇编。
然而,拆卸几乎不可能完美完成。正确反汇编的主要问题是反汇编者不知道一段代码会做什么,不会做什么。
例如,可以编写代码以便计算要跳转或调用的地址。反汇编器将无法计算这样的地址,因为它不执行、模拟或解释代码。因此反汇编程序可能无法确定下一个要从哪个位置进行反汇编。
也有具有可变长度指令的 CPU。这使得代码可以跳转到指令的中间。反汇编器应该如何反汇编那种代码?
另一种令人讨厌的做法是使用代码进行操作。代码可以在执行时即时更改自身。代码还可以生成更多代码。代码也可以存储为数据。你是怎么拆解这一切的?
因此,许多反汇编程序仍然非常愚蠢也就不足为奇了。他们只是无法与编写各种曲折程序的程序员的脑力竞争。
编辑:
此外,由于同样的可变长度指令问题,从稍微不同的位置开始反汇编相同的代码可能会产生不同的指令。
例子:
考虑 x86 处理器在 32 位模式下的这个字节序列:66h,0B8h,90h,90h,90h,90h。
如果你从第一个字节开始反汇编,你会得到:
mov ax,9090h
nop
nop
如果你在下一个字节开始反汇编,你会得到:
mov eax,90909090h
如果你再跳过一个字节,你会得到:
nop
nop
nop
nop