19

在学校,我们用 MIPS 汇编语言编程已经有一段时间了。我有兴趣深入研究 x86 程序集,我听说这有点难(甚至我的 MIPS 教科书也这么说)。

作为一名 MIPS 程序员,在进入 x86 世界之前,我应该了解哪些核心信息?

4

4 回答 4

20

要记住的最重要的事情是:

  • 很少有通用寄存器,而您所拥有的也不是纯 GP——许多指令要求您将某些寄存器用于特定目的。
  • x86 指令是两操作码形式而不是三操作码形式,这会使某些操作更加复杂。也就是说,不是添加 r0, r1, r2 (r0 = r1 + r2),而是添加 eax, ebx (eax += ebx)。
  • 处于保护模式的段(实际上是 DOS 之外的所有 32 位代码)使您的内存寻址方案非常不明显,当您刚开始时,这可能会让您大吃一惊。
  • 您将一直查找由指令设置/清除的标志。学会爱上英特尔手册。
  • 编辑,我忘记了一件事:子寄存器的使用(例如 ah 访问 eax 寄存器的低 16 位的高 8 位)可能会使对寄存器的跟踪操作变得非常困难。小心并自由地发表评论,直到你把事情搞定。

除此之外,x86 非常简单。当您学会滥用诸如“lea”和“test”之类的指令时,您就会学会喜欢它。另外,提示:英特尔将免费向您发送指令集手册的副本,甚至不必支付运费。在他们的网站上查看履行电子邮件并按 SKU 索取书籍。

于 2009-01-17T21:46:56.243 回答
6

与大多数其他架构相比,x86 的可用寄存器集非常有限。这并没有真正使汇编语言更难学习,但有时会使在实践中实现代码变得更加困难。

此外,由于 x86 具有强大的向后兼容性的历史,指令集并不是非常对称(绝对是 RISC 之前的版本),并且可能存在许多规则例外情况和需要注意的极端情况。

于 2009-01-17T21:22:32.610 回答
2

我一直在学习 x86 和 x86_64 自己编写汇编程序。如果您不打算自己编写汇编程序,那么我将讲述的一些内容几乎毫无用处。不过,我自己并不了解 MIPS。

x86 间接寻址是一件复杂的事情。在一条指令中,您可以执行以下操作:

mov reg, [reg+offset]
mov reg, [reg*scale+base register+offset] # in where scale can be 1, 2, 4 or 8.

因此,它们的指令编码很复杂,但是对于以这种方式编码的每条指令来说都是一致的。您可能想从sandpile.org阅读此内容。如果您想了解有关编码的更多信息,可以随时向我询问。另一个指令编码相关的烦人细节是前缀。它们极大地改变了指令的含义。例如,前面的 0x66(如果我没记错的话)和一些指令变为 16 位 GPR 而不是 32 位 GPR。

32 位 GPR(按顺序):eax、ecx、edx、ebx、esp、ebp、esi、edi

64 位 GPR:rax、rcx、rdx、rbx、rsp、rbp、rsi、rdi、r8、r9、r10、r11、r12、r13、r14、r15

注意通用寄存器有多么少,这将迫使大多数软件或多或少地以堆栈机器方式使用它。一个痛苦的细节。rsp 用于堆栈(pop、push 指令),而 rbp 也倾向于保留。x86_64 有更多的寄存器,但人们采用它需要时间,即使每个消费者都有一个能够支持它的处理器。

浮点运算有两种不同的指令集。XMM 是较新的。在 x86_64 中有 16 个 128 位寄存器可用,而在 x86 中只有 8 个。较旧的指令集将寄存器作为堆栈处理。你只是没有交换、咬合或腐烂,所以使用它是令人费解的。

在使用中,x86 趋向于简化为 RISC 机器。其中一些复杂的指令在较新的机器上没有好处,甚至速度更慢。根据您阅读或写作的内容,您将了解大约 30-150 条指令。您也可以完全忽略一些旧指令和 AL/HL -stuff。请记住,这一切都是 1978 年之后的混乱起源,令人惊讶的是,它并没有更糟,从那以后 31 年,距离 IA-32 首次引入还有 24 年。很多事情在那段时间改变了它们的相关性。

直接跳转和调用似乎与 x86 中的下一条指令相关。所以:

    jmp nowhere  # or call, jz, jg whatever...
nowhere:
    nop

最终编码为“JMP imm:0, NOP”。确实执行绝对跳转的寄存器间接 jmp。注意到没有寄存器间接条件跳转也很好,它也困扰着我。

这不是你应该知道的所有可能的事情,而是你的问题让我想到的第一件事。但也许你现在可以和这些相处。

于 2009-01-17T22:25:30.860 回答
1

x86 的指令比 MIPS 更复杂。因此,MIPS 中的常见序列可能只有一条指令(最值得注意的是内存寻址)。缺少大量寄存器当然是一个缺点,但在这两种架构中都有一些约定,几乎将您可以自由使用的数量限制在 4-5 个。在 x86 中更明显。x86 比 MIPS 有更多的寄存器使用例外,你必须记住,但没有什么值得不断抱怨的。

从经验来看,任何一种语言的学习难度都差不多,包括约定。考虑到丰富的在线资源及其受欢迎程度,也许 x86 更容易一些。

x86 的难点在于生成二进制文件,因为它具有可变长度的指令和多种寻址模式。大多数情况下,无论如何您都不需要这样做。

我当然可以推荐你学习比 MIPS 更复杂的指令架构。

而且,这很重要,不要参与 RISC 与 CISC 之间的宗教战争……

于 2009-01-17T21:51:25.330 回答