Y86指令集(介绍篇)
2014-06-13
Y86的模拟器、汇编器是我们的一项作业。我决定写几篇博客来梳理一些关于它的技术要点。
基本特性
Y86出自《深入理解计算机系统》(CSAPP)第四章。它是一个极为简化的、用于教学的CPU指令集,在特性上与目前PC平台主流的x86相近。
它包括:
- 八个32位的通用寄存器,就像在x86上那样;
- 指令地址寄存器,类似于
EIP
,不过在Y86中我们将它称为PC
; - 地址从0开始的内存;
- 状态:正常运行、地址错误、指令错误、停机;
- 三个Flags,分别对应x86中的ZF、SF、OF,表示结果为零、为负数、溢出;
- 数据移动、计算、堆栈维护等指令(当然,比x86的指令集简单得多)。
但是它:
- 不包含x87(FPU)、MMX、SSE、SSE2、SSE3……SSE233(误)等各种指令集;
- 不区分实模式和保护模式,始终在32位下工作;
- 没有中断,没有系统调用;
- 没有x86风格的调试支持,模拟器中允许运行指定步数停机;
- 没有IO(嗯…你可以猜一下什么东西取代了IO);
- 比x86更宽松、更整齐的二进制格式。
下面来说说Y86中的那些指令——
指令:计算与无条件mov
计算和mov应该说是Y86中最基本的指令了。
Y86的计算指令只允许操作寄存器,有addl
,subl
,andl
,xorl
这四个。
mov在x86中是一组同名的指令,而在Y86中,为了方便汇编器的编写,使用了四个不同的名字:
rrmovl
是寄存器之间的数据移动;irmovl
将立即数移入寄存器;rmmovl
将寄存器的值移到另一个寄存器加偏移表示的内存地址,形如rmmovl rA, D(rB)
;mrmovl
和rmmovl
相对,将内存中的值移到寄存器,mrmovl D(rB), rA
。
指令:条件
Y86中的条件跳转只允许跳转到固定的绝对地址。
类似于x86,Y86的跳转有jmp
,jle
,jl
,je
,jne
,jge
,jg
这七种,jmp
相当于条件永远为真。
条件数据移动指令与跳转指令一一对应,rrmovl
可以看成和jmp
一样的“永真条件”,而六种cmovXX
分别和对应的jXX
使用相同的判断条件。
指令:堆栈与调用
Y86和x86一样,ESP
寄存器表示栈顶。因此有pushl rA
和popl rA
这两条指令用于进出栈。
pushl
先向内存中写数据再移动ESP
,而popl
先移动ESP
再从内存中读数据。……慢着,这顺序区别有什么关系吗?还真有,如果遇到pushl %esp
或者popl %esp
这样的指令,这个顺序将影响结果。
call
即调用,在执行跳转前将PC
压栈。
ret
即返回,弹出PC
。这条指令有一个特殊的地方,它是唯一允许跳转到任意地址的指令,这会给模拟器的实现带来一些麻烦。
之后,我们会继续介绍Y86的模拟器实现。