assembly 什么是8086 ESC指令操作码

x0fgdtte  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(220)

这是一个很有历史意义的问题,如果我要实现汇编程序的8086兼容性,什么操作数对ESC指令有效?
ESC opcode, source
从8086程序员手册中我知道,opcode是一个立即数,范围是0到63,而source是一个寄存器或内存。但是哪些寄存器可以被编码?reg8reg16都可以,还是只有reg16?如果source是内存,操作数大小(mem8mem16)有关系吗?
基本上,从指令编码的Angular 来看,上述两种情况并不重要(例如,esc 0x01, chesc 0x01, bp会产生相同的结果),但汇编器可能有强制限制
最后,但并非最不重要的一点是,我在哪里可以找到ESC操作码的描述?

ymdaylpp

ymdaylpp1#

8086有一个操作码空间,统称为ESC(转义到协处理器)。它占用d8df的范围。此指令空间中的每条指令后面都跟一个modr/m字节,并且根据mod-field的不同,还跟0到2个位移字节。当8086遇到带有两个寄存器操作数的ESC指令时,当处理器遇到具有存储器操作数的ESC指令时,从由存储器操作数指示的地址执行读取周期,并且丢弃结果。
使用两条特殊的信号线,协处理器可以区分数据获取和指令获取,允许它与8086并行地解码指令流。
8087使用此机制来挂钩到指令流:操作码字节中的三个可用位与modr/m字节中reg字段的三个位一起构成一个六位操作码。modr/m字节的r/m字段用于指定FPU寄存器堆栈上的位置(如果mod = 11,则表示两个寄存器操作数)或一个存储器操作数。某些操作码根据r/m字段的内容对各种指令进行编码。在所有这些情况下,一个指令被编码用于存储器操作数,而八个其它指令被编码用于每个可能的寄存器操作数。
当8086在取指令后立即执行虚拟取指令时,8087寄存器会记住该地址.当指令从存储器装入时,它装入存储器操作数得附加字,并执行其功能.当执行存储操作时,它忽略取指令得结果,并将其值存储到8086所指示得地址.
8087执行与8086异步的操作。但是,不存在隐式同步。如果在协处理器忙碌时试图发出ESC指令,则该指令将被忽略。要解决此问题,8087Assert它的BUSY引脚(连接到8086的TEST引脚)。程序员可以发出wait指令(9b,等待协处理器就绪),直到8087结束操作并因此释放WAIT行。这通常在每个单独的8087指令之前完成,并且当今的许多汇编器将自动插入WAIT前缀。对于高性能代码,还普遍地改为手动计算8087对于某个指令将花费多长时间,并且当保证已经完成前一个浮点指令时省略X1 M12 N1 X。

xv8emn3q

xv8emn3q2#

80 x86的操作码--就像8080和8085的前身一样--最好用八进制而不是十六进制来理解。它被理解为每个字节8位,2+3+3位,所以第一个八进制数字的范围是0-3,而其他两个数字的范围是0-7。
浮点转义具有八进制形式33 c xrm D,对于Escape #c,具有名义寄存器#r和操作数模式(x,m),其中D是类型int8_t的一个字节,对于x = 1;- 对于x = 2或对于(x,m)=(0,6),类型uint16_t的2个字节;否则为0字节。
对于x = 3,m名义上是第二寄存器:寄存器#m,而对于x = 0、1或2(除(x,m)=(0,6)),m名义上表示索引寄存器的组合(BX+SI,BX+DI,BP+SI,BP+DI,SI,DI,BP,BX),对于m =(0,1,2,3,4,5,6,7),当x = 3时,该指标不适用(因为m表示寄存器,而不是存储器地址),并且是0或(x,m)=(0,6)。如果D是0字节,则位移是Disp = 0,如果D是1字节,则位移是Disp =(int16_t)D;如果D是2个字节,则Disp = D。
不受支持的操作码会触发CPU中的异常,如中断6 -从80186开始。
我不清楚33 c操作码的握手过程,也不清楚中断6的情况。这是一个硬件问题,它涉及到对数据总线的同步访问。为此,8086中有WAIT操作码(233),以允许CPU延迟。连接到8086的8087将在8086恢复之前完成它的任务。
但是对于017操作码和8086中的其它操作码漏洞,异常中断6被触发。
无论谁为CPU编写裸机程序(根据定义:固件)负责为中断6(以及所有其它中断和异常)写异常处理程序。返回地址指向无效操作的 start,并且这样做是为了给固件给予一个钩子以实现其自己的操作码集的扩展。
在80 x86语言中,没有任何东西可以让固件程序员直接访问(x,m,D)或r的“寄存器”,所以它们必须在固件的异常处理程序中显式解释。(x,m,D)在硬件级驱动数据总线,使得部分解释任务被传递给硬件工程师,解释“r”的任务,但是,我认为仍然需要在固件中处理。
顺便说一下,当人们使用十六进制作为操作码时,在其他地方,对八进制格式的理解会在转换中丢失,包括操作码中间的八进制数字对操作进行编码的情况。
这里丢失的是在不同地方出现的相同编码,例如,操作码0 pq分别表示p =(0,1,2,3,4,5,6,7)的操作(add,or,adc,sbb,和,sub,xor,cmp);具有不同的寻址模式q =(0,1,2,3,4,5);情况q =(0,1,2,3)采用额外的xrm D字节,q = 4采用额外的1字节uint_8值,并且q = 5采用额外的2字节uint_16值。
在c =(0,1,2,3)的情况下,在操作码20 c xpm D中出现的“p”是相同的。因此,这些操作码没有寄存器#r,因为xrm中的r被替换为运算符p。(相反,它们占用了额外的数字字节:这些是由(x,m,D)表示的寄存器或存储器之间的“p”个操作和附加到该操作的额外的1或2个字节的数字数据。
当我在USENET上提出八进制遗留8086的问题时,这促使了NASM(Netwide Assembler)的创建,这就是为什么它在内部使用--现在仍然使用--八进制作为操作码。

相关问题