8086 有一个共同指定的操作码空间ESC
(逃逸到协处理器)。它占据范围d8
为df
。该指令空间中的每条指令后跟一个 modr/m 字节,并且根据 mod 字段,零到两个位移字节。当 8086 遇到ESC
带有两个寄存器操作数的指令时(即 mod = 11),它会执行 nop。当处理器遇到ESC
带有内存操作数的指令时,从内存操作数所指示的地址开始执行一个读周期,结果被丢弃。
使用两条特殊的信号线,协处理器可以区分数据取指和指令取指,允许它与 8086 并行解码指令流。
8087 使用这种机制来挂钩指令流:操作码字节中的三个可用位与 modr/m 字节中 reg 字段的三个位一起形成一个六位操作码。modr/m 字节的 r/m 字段用于指定 FPU 寄存器堆栈上的位置(如果 mod = 11,表示两个寄存器操作数)或内存操作数。一些操作码根据 r/m 字段的内容对各种指令进行编码。在所有这些情况下,一条指令针对内存操作数进行编码,而另外八条指令针对每个可能的寄存器操作数进行编码。
当 8086 在获取指令后立即执行虚拟获取时,8087 会注册并记住地址。对于从内存加载的指令,它会加载内存操作数的附加字并执行其功能。在存储的情况下,它会忽略获取的结果并将其值存储到 8086 指示的地址。
8087 与 8086 异步执行操作。但是,不存在隐式同步。如果在协处理器忙时尝试发出ESC
指令,则该指令将被静默忽略。为了解决这个问题,8087 在执行操作时将其BUSY
引脚(连接到 8086 的TEST
引脚)置位。程序员可以发出wait
指令(9b
, 等待协处理器准备好)等到 8087 完成操作并随后释放该WAIT
行。这通常在每条 8087 指令之前完成,当时的许多汇编程序会自动插入WAIT
前缀。对于高性能代码,也很常见的是手动计算 8087 执行某条指令需要多长时间,并省略上一条wait
浮点指令保证完成的时间。