Bob Playground


Welcome to Bob‘s blog.


实现 Y86 处理器 —— 指令集体系结构

指令被编码为由一个或多个字节序列组成的二进制格式。

一个处理器支持的指令和指令的字节级编码称为它的 指令集体系结构(Instruction-Set Architecture, ISA)。

定义一个指令集体系结构,包括:

  • 定义各种状态元素
  • 指令集和它们的编码
  • 一组编程规范
  • 异常事件处理

程序员可见状态

汇编语言可以读取或修改的处理器状态。

程序员可见状态

CPU 硬件实现并不一定存在这些组件,可以理解为这是 CPU 底层硬件开放给汇编语言的接口。

Y86 指令

Y86 指令集

指令格式

每条指令需要 1 ~ 6 个字节不等。

  • 第 1 个字节:表明指令的类型

    高 4 位:指令代码(code)部分 + 低 4 位:功能代码(function)部分

    当一组指令共用一个指令代码时,功能代码部分才有用。

  • 第 2 个字节:指令用到的寄存器地址 rA 和 rB

    8 个程序寄存器分别对应 0 ~ 7 的寄存器标识符(register ID)。所以,可用 4 位来表示这些寄存器。

    不需要访问任何寄存器时,就用 0xF 来表示。

  • 第 3 ~ 5 共 4 个字节:常数字(constant word)

Y86 指令集基本上是 IA32 的子集。它只包括四字节整数运算,寻址方式比较少,操作也比较少。

好处是方便我们学习理解 CPU 的实现机制。

指令详解

Y86 指令集的功能码

MOV 数据传送指令

共 4 个,包括 irmovl rrmovl mrmovlrmmmovl

首字母表示来源类型,第二个字母表示了目的类型。

字母 类型
i 立即数
r 寄存器
m 存储器

存储器引用方式为基址+偏移量形式(Imm(E)),上图中的常数字 D 就是偏移量。

OP 整数操作

共 4 个,包括 addl subl andlxorl

如上图所示,只对寄存器数据进行操作。

这些指令会设置条件码 ZF、SF 和 OF(零、符号和溢出)。

JXX 跳转指令

共 7 个,包括 jmp jle jl je jne jgejg

根据条件码来选择分支。

CMOV 条件传送指令

共 6 个,包括 cmovle cmovl cmove cmovne cmogecmovg

他们与 rrmovl 一样,都是在两个寄存器之间传送数据,但是只有条件码匹配时,才会执行。

CALL 和 RET

call 指令将返回地址入栈,然后跳转到目的地址。ret 指令从这样的过程调用中返回。

PUSH 和 POP

pushlpopl 分别实现了入栈和出栈。

HALT

停止指令的运行,并将状态码设置为 HLT。

另外,

简单起见,跳转指令和 call 指令使用绝对地址,而不像 IA32 那样使用相对 PC 的相对寻址方式。

同 IA32 一样,所有整数采取小端法编码。所以,反汇编后,这些字节会以相反的顺序出现。

指令集的一个重要性质就是字节编码必须有唯一的解释。

Y86 每条指令的第一个字节有唯一的代码和功能组合,可以决定所有其他附加字节的长度和含义。

Y86 异常

状态码 Stat 描述了程序执行的总体状态。

Y86 状态码

对于 Y86,遇到非 AOK 的状态码时,只是简单地让处理器停止执行指令。在更完整的设计中,处理器通常会调用一个 异常处理程序(exception handler)

一些 Y86 指令的详情

两个特别的指令组合需要注意:

pushl %esp

popl %esp

在下一篇中将会得到答案。