1、第9章 数学协处理器 第9章 数学协处理器 9.1 概述概述 9.2 协处理器的逻辑结构协处理器的逻辑结构 9.3 协处理器指令系统及应用协处理器指令系统及应用 第9章 数学协处理器 9.1 概概 述述 9.1.1 数学协处理器的作用数学协处理器的作用 表表 9.1 相容的处理器和协处理器相容的处理器和协处理器 第9章 数学协处理器 9.1.2 接口及性能接口及性能 处理器与协处理器以级联方式工作,处理器执行取指令、译码、计算存储器操作数的地址等操作,而协处理器执行对浮点数的算术及比较操作。此外,协处理器还提供了许多三角函数及超越函数,供程序员作为简单的单条指令使用。计算机系统中的许多设备,诸
2、如视频显示控制器和中断控制器,必须用非直观的I/O指令编程。没有特定设备的编程信息,就对这些设备编写程序或试图理解现成的目标码是近乎不可能的。由于处理器和协处理器共享一个严格定义的硬件接口,因此,无需特殊的设置和复杂的数据传送。实际上,协处理器指令可以简单地作为处理器基本指令集的扩展。第9章 数学协处理器 协处理器指令集被设计用来补充正常处理器指令的编码形式。例如,操作数可以位于存储器中或位于协处理器寄存器中。协处理器对存储器的寻址使用与CPU同样的操作数寻址方式。此特性可以将浮点操作以一个相对简单的方式集成于应用程序中。基本的(8087兼容的)协处理器指令集提供全范围的加载和存储指令,这些指
3、令在协处理器的数值寄存器与系统存储器之间转移实数、整数及BCD数等数据操作数。算术指令提供的是基本四则运算:加、减、乘、除。更加高级复杂的指令用于实现平方、比例、求余、取模、取整及绝对值等函数,还提供了超越函数,包括正切、对数及指数等。第9章 数学协处理器 9.1.3 应用应用 创建协处理器的一个目标,就是使应用程序员能掌握易于数值编程的能力。协处理器操作及浮点指令集的设计,尽可能地使人们从易读形式的算法到汇编代码直截了当,减少错误发生的机会。这样的话,大部分使用协处理器的程序便是通常的科学及商业应用程序。要求协处理器具有高精度及快速的处理能力的应用包括:商业数据处理、科学数据的归纳,图形处理
4、及财务操作。嵌入式应用还可在实时编程中充分利用协处理器,包括过程及机器控制、航海、机器人和数据获取。第9章 数学协处理器 9.1.4 数据类型数据类型 协处理器的数据格式已经在第一章中介绍了,它可以支持7种数据类型。需要强调的是,虽然每一种数据格式都可能用在协处理器加载和存储数据时,然而从内部来看,所有数据操作数都要转换成80位临时实数格式。协处理器内部将临时实数格式用于所有的计算,从存储器中读取的所有数据类型将自动转换成临时实数格式,程序员对此毫无感觉。这样,协处理器芯片内部的结构有所简化,而又不会增加程序设计的负担。由于临时实数格式的精度超出其它格式很多,一方面使得运算精度提高;另一方面计
5、算的最终结果引入的错误,也将可能发生在短实数和长实数的范围之外,即上溢和下溢的条件在计算期间极少发生,而更易发生于把结果写入到范围有限的短实数或长实数内存操作数中去时。第9章 数学协处理器 9.2 协处理器的逻辑结构协处理器的逻辑结构 9.2.1 协处理器的内部结构协处理器的内部结构 像处理器一样,协处理器是一个复杂的微电路的阵列,被设计用来实现复杂的功能。处理器与协处理器之间相互补充,并且按先后顺序工作。处理器取指令、译码,并且计算存储器操作数的地址,而协处理器同时处理那些特殊编码的浮点指令(所有协处理器指令的机器码的高5位都是“1 1 0 1 1”),称为逃逸(ESC)指令。尽管它的运行似
6、乎很复杂,但作为结果,协处理器在结构上却是比处理器更为简单的器件。第9章 数学协处理器 图 9.1 协处理器内部结构 280标志字寄存器栈内部总线接口微码指令单元操作数指数寄存器操作数队列指数ALUNEU指令数据缓冲区控制字状态字常量(ROM)67位操作数尾数寄存器操作数ALU可编程左/右桶形移位器控制逻辑状态地址数据1668数值执行单元(NEU)控制单元(CU)第9章 数学协处理器 1.控制部件控制部件 控制部件的责任之一便是同步协处理器与处理器之间的操作。当两个处理器必须交换信息,访问彼此运行的结果或指令译码时,同步是必要的。例如,协处理器的指令经常混在应用程序目标码的普通处理器指令中,只
7、有处理器执行取指令,然而协处理器控制部件是硬连接到处理器的状态线上,并且能够像与处理器并行取指一样来读指令。如果处理器/协处理器要成对正确运行的话,协处理器就必须读取和译码与主处理器相同的指令。因此,协处理器必须模拟它的宿主处理器的取指和译码特性。例如,协处理器必须保留一个与处理器在大小上一致的预取指令队列,需要时,协处理器要识别它的相伴处理器的复位情况,并且自动匹配队列的长度,然后,协处理器监控指令队列以便从队列中移去指令,并且与处理器同时译码。第9章 数学协处理器 处理器与协处理器都能译码一类特殊的指令,我们称为浮点或ESC指令,即协处理器指令的范围。对于所有的应用,处理器不执行这些指令而
8、由协处理器的控制部件对它们译码。然而,处理器对ESC指令的译码是为了区分它是否访问存储器,如果ESC指令访问存储器,那么处理器将计算存储器操作数的有效地址,并初始化一个读存储器总线周期。处理器将忽略作为读周期的结果而放在总线上的数据,而由协处理读取。如果ESC指令不包含存储器的访问,那么处理器立刻开始译码和执行下一条指令。第9章 数学协处理器 协处理器控制部件最后负责执行总线操作的细节,即使由处理器计算有效地址,这些操作仍是协处理器需要的。如果正在访问内存,那么协处理器保存操作数的有效地址。如果指定了寄存器操作数,那么操作数的值要被保存。例如,由于大小和对准的原因,如果操作数要求多于一个总线周
9、期去访问,那么协处理器控制部件就要控制系统总线,并传送操作数的余下部分。如果要写入存储器一个操作数,那么,处理器计算有效地址并初始化一个读总线周期,协处理器控制部件保存有效地址,但不管总线上的数据;然后,协处理器控制单元变成局部总线主控,并按要求初始化写周期,来向存储器传送操作数,无需NEU参加的ESC指令,由控制部件独立于NEU来执行。第9章 数学协处理器 2.数值执行部件数值执行部件 协处理器的第二个主要的处理部件称为数值执行部件(NEU)。NEU才是协处理器中实际上的浮点处理器,并执行所有对协处理器寄存器中数据的访问和处理操作。NEU可以运行算术、逻辑及超越函数等的操作,还能提供少数的数
10、学常数,这样的常数存于片上的ROM中。NEU的数值寄存器有80位宽,刚好与80位临时实数数据类型相配。在内部,数据按两条途径处理:64位尾数总线和16位符号/指数总线。在寄存器栈外,另有4位附加到尾数总线上,则总共68位。出于执行特殊数学功能的需要而引入NEU内部特殊的硬件,包括有专用指数和尾数加法器及一个可编程左/右桶形移位器。第9章 数学协处理器 ESC指令译码后,被送入微指令顺序发生器(协处理器内部的小计算机),然后按次序使片上硬件单元按每条指令的要求执行具体任务。当ESC指令开始执行,NEU使它的BUSY信号激活。NEU的BUSY状态在协处理器的控制字中报告,而且还要驱动可由处理器监控
11、的外部管脚。此信号用来连接处理器的WAIT指令,以便使协处理器与处理器重新同步。第9章 数学协处理器 3.同步同步 在两种情况下,必须在协处理器与处理器之间建立同步。第一种情况,如果NEU还没有完成前一条指令的执行,那么,要求NEU参与的ESC指令的执行肯定不能启动。除少数控制和报告协处理器状态的指令外,大多数ESC指令都使用NEU。第二种要求协处理器与处理器同步的情况是,当处理器指令访问一存储器位置时,而此位置中的内容恰为前一条协处理器指令的操作数。此情况下,处理器必须与协处理器同步以保证协处理器指令的执行完成,否则处理器可能在协处理器读取之前改变其值,或者在协处理器写入之前读取了其值。第9
12、章 数学协处理器 处理器WAIT指令(等同于FWAIT指令)是出于建立同步的目的而提供的。如果遇到一条WAIT指令,处理器便会监视TEST线,它与协处理器的BUSY信号直接相连。只要TEST被激活,WAIT指令就使处理器停止执行。TEST线一变成无效,处理器就继续执行下一条指令。只有8087协处理器要求在所有数值ESC指令之前显式编码WAIT指令。在任何ESC指令启动执行之前,程序员必须保证8087已经完成所有前面ESC指令的活动。由于典型的浮点指令的执行时间在数百个时钟的数量级上,因此,处理器很可能在协处理器完成ESC指令处理之前很长时间,就已完成对其的处理。80286及以后的处理器自动在执
13、行一条协处理器指令前测试它们的TEST线,而且无需显式对WAIT编码。第9章 数学协处理器 许多协处理器的指令执行时间都特别长。为防止WAIT指令在整个ESC指令执行期间延迟了中断处理,处理器在其等待TEST线时,每5个时钟周期间隔处理器被中断一次。当TEST线无效时,挂起的中断将被忽略,而处理器立即执行下一条指令。无论何时发生一个非屏蔽的浮点异常,协处理器将发出错误条件信息给处理器。如果处理器和协处理器并行操作,处理器可能已经将异常处理程序要修正和重新启动ESC指令所需的数据修改。如果想正确处理异常,便需要在ESC指令之后编码WAIT和FWAIT指令,此编码还允许处理器应答任何挂起的浮点异常
14、。第9章 数学协处理器 9.2.2 寄存器寄存器 1.寄存器与标记字寄存器与标记字 图 9.2 协处理器寄存器栈 797864 630R0R1R2R3R4R5R6R71位符号15位指数64位指尾数寄存器号第9章 数学协处理器 在状态字中的ST字段是一个指针,它总是指向当前栈顶寄存器。入栈操作把ST减1后再把数值装入新的栈顶寄存器,出栈操作是先取出当前栈顶寄存器中的值,然后ST加1。不同于传统栈设计成只有栈顶寄存器对程序员可见(为访问栈中更深的寄存器,其上面的操作数必须被删除),在协处理器的寄存器栈中,通过ST指针,寄存器栈中的每个独立单元都可以按隐式或显式寻址,此灵活性使设计数值程序更容易,而
15、且使编程效率提高。当80X87指令对寄存器栈中的数据进行操作时,若不明确指出是哪一个寄存器,则总是栈顶元素被引用,即隐式寻址为栈顶元素ST,或等价的ST(0);若指令中显式寻址寄存器,则必须以栈顶指针ST为依据,用ST(i)表示被寻址的寄存器,ST(i)表示栈中从ST算起的第i个寄存器(0i7)。例如,若ST=011B(R3寄存器是栈顶),那么指令FADDST,ST(2)就表示R3寄存器和R5寄存器的内容相加。第9章 数学协处理器 图 9.3 协处理器栈机器实现10101234567STST10122ST12322ST123159ST123159ST123159STST=4以空栈开始压入101
16、压入22加压入159弹出弹出标为空栈项用阴影显示第9章 数学协处理器 图 9.4 标记字格式 TAG(7)TAG(6)TAG(5)TAG(4)TAG(3)TAG(2)TAG(1)TAG(0)标记值:“00”寄存器内容为有效值 “01”寄存器内容为零 “10”寄存器内容为特殊值(NaN,不正常或不支持)“11”寄存器为空150第9章 数学协处理器 2.状态字状态字 状态字是协处理器中的一个16位寄存器,其值报告协处理器的状态。状态字中的域如图9.5所示。它可以被80X87指令装入内存,再由CPU指令对各位进行检测。图 9.5 协处理器状态字 BC3STC2C1C0IRSFPEUEOEZEDEIE
17、1587650忙栈顶指针条件码异常标志,=1时表明相应的异常已发生栈失效(只用于80387以后)中断请求第9章 数学协处理器 B“忙”位,对于8087和80287,忙位反映了协处理器BUSY信号的状态。数学协处理器闲时,忙位便清零,NEU在执行一条ESC指令时,忙位被置1。如果协处理器发生异常,忙位也会被置1。这就允许异常条件在试图执行另一指令之前被处理。对80387及以后的协处理器,忙位并不再反映协处理器的BUSY信号状态,但却置成与IR值(中断请求位)相同的值以保持与8087和80287的兼容性。第9章 数学协处理器 ST 占用3位。表示8个椎栈单元中的哪一个现在是栈顶。ST数值数值 含含
18、 义义 0 0 0 单元0是堆栈顶 0 0 1 单元1是堆栈顶 1 1 1 单元7是堆栈顶 第9章 数学协处理器 C3C0 占用4位。条件码标志,NEU更新这些标志的值来反映算术操作的状态。测试及比较功能也使用这些标志报告它们的操作结果。IR中断请求位。当某事故标志位为“1”而控制字中相应事故屏蔽位为“0”时,则中断请求位为“1”。SF 栈失效标志。只为80387及以后的协处理器定义的,并且发生在栈上溢时(试图向一个非空的寄存器中加载内容)或下溢时(试图从空栈中弹出一个操作数来)。PE 精度异常标志。如果结果必须四舍五入以便能够用浮点格式表示时,该标志位置1。第9章 数学协处理器 UE 下溢异
19、常标志。当计算的结果大小,不用非正常的方法就不能以指定的目的操作数的浮点格式存储时,该标志置1。OE 溢出异常标志。只要计算的结果超出指定目的操作数的浮点格式所能表示的数域时,该标志置1。ZE 被零除异常标志。表示除法操作是否被零除和被除数是否为非零数字。DE 非正常操作数异常标志。用于表示指令是否企图操作一个非正常的操作数。IE 非法操作异常标志。表示是否完成了几种非常操作中的一种操作。例如求一个负数的平方根。第9章 数学协处理器 3.控制字控制字 图 9.6 协处理器控制字 ICRCPCIEMPMUMOMZMDMIM控制域中断使能屏蔽0=中断使能1=中断禁止异常屏蔽位=1 屏蔽异常150第
20、9章 数学协处理器 控制字的低8位(位0到位7)用于控制协处理器的错误异常的屏蔽。低6位分别表示着6种可能的由协处理器探测的数值错误异常。每一屏蔽位的位置与相应状态寄存器的报告标志的位置相同。如果屏蔽位被置1(屏蔽了异常),那么,协处理器将使用它的片上屏蔽响应在内部处理异常。如果屏蔽位清零(未屏蔽异常),那么协处理器将发生一个中断请求调用一个外部处理程序,此称之为未屏蔽响应。只有8087,未屏蔽异常的行为还取决于控制字位7的值,即中断屏蔽使能位(IEM)域。未屏蔽的中断将置位状态寄存器的中断请求位,但如果IEM位置1的话,也不产生中断。此位在以后的协处理器中未定义并忽略。第9章 数学协处理器
21、精度控制域(PC)的设置控制着NEU的内部精度。正常情况下,PC=11B,NEU使用64位尾数进行所有的内部计算。然而,精度控制域的不同设置,可以用于将精度减至53或24位尾数位,如表9.2所示。表表9.2 PC域及精度方式域及精度方式 第9章 数学协处理器 表表9.3 RC域及舍入方式域及舍入方式 第9章 数学协处理器 4.异常指针异常指针 通常,在6种可能的错误异常中,除了非常操作异常之外,对其它5种错误异常,80X87都可以使用其片上的屏蔽响应“合理”地进行处理,不一定需要向CPU申请中断。当发生某种错误异常而相应的屏蔽位为零时,则引起状态字中中断申请位IR置1,向CPU发出中断请求,请
22、求引出用户自行编写的错误异常处理程序来进行处置。异常指针就是供用户编写错误异常处理程序时使用的,它可以提供异常发生时的指令、地址、操作码、操作数地址等信息。如果发生异常,处理程序可以把异常指针的内容拷贝到内存中进行异常分析。异常指针的格式见图9.7所示。第9章 数学协处理器 图 9.7 异常指针格式 第9章 数学协处理器 图图 9.8 16位实方式异常指针内存格式位实方式异常指针内存格式 第9章 数学协处理器 9.2.3 协处理器的初始化协处理器的初始化 表表9.4 协处理器的复位状态协处理器的复位状态 第9章 数学协处理器 续表 第9章 数学协处理器 9.3 协处理器指令系统及应用协处理器指
23、令系统及应用 9.3.1 指令句法指令句法 大多数指令(包括那些用于控制协处理器的)都有一个或两个参量作为输入,并且产生一到两个结果作为输出。输入可以从寄存器栈或是存储器中获取,但是当输入是从寄存器栈中取得,那么NPX的操作是非常有效的。有些指令操作隐式要求浮点栈顶元素(ST),既可以是单独的也可能是与另一操作数的组合。其他指令允许或要求程序员指定操作数。同处理器指令一样,指令的参数指定(隐式的和显式的)一个源操作数和一个目的操作数。源操作数提供一个操作的输入而目的操作数接收结果,目的操作数也可提供另一个输入。例如,处理器指令ADD AX,CX实现的功能是AX=AX+CX。在此情况下,CX寄存
24、器是源而AX寄存器是目的。AX和CX都提供输入而AX接收操作的结果。第9章 数学协处理器 浮点指令句法并不那么直截了当。相同的基本助记符具有不同的解释,这取决于是使用了传统栈还是常规的指令操作数方式。使用传统栈形式时,均采用隐式寻址,若有两个操作数,通常指的就是栈顶单元(作为源操作数)和栈顶的下一个单元ST(1)(作为目的操作数);若仅使用一个操作数,则指的就是栈顶单元。常规指令形式采用显式寻址。第9章 数学协处理器 句法上的差别由汇编器和调试器来决定指令形式。例如,FMUL指令可写成无操作数、只有一个操作数,或是一个源和一个目的操作数。如下面所示,每一条指令执行的操作不同:FMUL;ST(1
25、)=ST(1)*ST,FPOP FMUL ST(1);ST(1)=ST(1)*ST FMUL ST,ST(1);ST=ST*ST(1)无显式操作数的指令FMUL的编码,等同于全部指定操作数的指令FMULP ST(1),ST。汇编器根据指令的形式来确定指令的操作码变量。第9章 数学协处理器 9.3.2 指令简介指令简介 1.数据传送数据传送 表表9.5 NPX数据传送类指令数据传送类指令 第9章 数学协处理器 2.算术运算算术运算 表表9.6 NPX算术指令算术指令 第9章 数学协处理器 表表9.6 NPX算术指令算术指令 第9章 数学协处理器 表表9.7 基本算术指令形式基本算术指令形式 第9
26、章 数学协处理器 3.比较运算比较运算 表表9.8 NPX比较指令比较指令 第9章 数学协处理器 表表9.9 比较指令所置的条件码比较指令所置的条件码 第9章 数学协处理器 4.常数加载常数加载 表表9.10 NPX加载常数指令加载常数指令 第9章 数学协处理器 5.超越指令超越指令 表表9.11 NPX超越指令超越指令 第9章 数学协处理器 表表9.12 用于导出高级函数的恒等式用于导出高级函数的恒等式 第9章 数学协处理器 续表 第9章 数学协处理器 6.协处理器控制指令协处理器控制指令 表表9.13 NPX控制指令控制指令 第9章 数学协处理器 续表续表 第9章 数学协处理器 9.3.3
27、 协处理器指令应用举例协处理器指令应用举例 例例9.1 数据求和。程序功能:将存储器中的十个数(1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0)相加,结果放入存储器指定单元之中。程序清单:STACK SEGMENT PARA STACK STACK DW 200H DUP(0)STACK ENDS DATA SEGMENT PARA PUBLIC DATA ARRAY DD 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 ;10个原始数据放在数组ARRAY中。第9章 数学协处理器 N DW 10D ;数据长度。DSUM DD?
28、;求和结果单元。DATA ENDS CODE SEGMENT PARA PUBLIC CODE CACULATE PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACK,ES:NOTHING MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV CX,N FINIT ;初始化协处理器。FLDZ ;加载+0.0到栈顶寄存器ST中,作为累加初值。第9章 数学协处理器 START:MOV SI,CX ;计算当前加数的地址偏移量。DEC SI SHL SI,1 ;SI=SI*4,因为原始数据是双字长度。SHL SI,1 FADD A
29、RRAYSI ;将当前加数加到ST,ST中是每步累加结果。LOOP START FST DSUM ;将求和结果从ST存入存储器指定单元DSUM中。CACULATE ENDP CODE ENDS END CACULATE 第9章 数学协处理器 例例9.2 求一组数的平均值和均方差。程序功能:计算n个数的平均值A和均方差D,即 A=(V1+V2+Vn)/N D=(V1-A)2+(V2-A)2+(Vn-A)2/N1/2程序清单:STACK SEGMENT PARA STACK STACK DW 200H DUP(0)STACK ENDS DATA SEGMENT PARA PUBLIC DATA 第
30、9章 数学协处理器 AVERAGE DD?;平均值存储单元。STANDARD-DEV DD?;均方差存储单元。VECTOR-SIZE DW 9 ;数据长度。VECTOR DD 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 ;9个原始数据放在向量VECTOR中。DATA ENDS CODE SEGMENT PARA PUBLIC CODE AVEDEV PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACK,ES:NOTHING 第9章 数学协处理器 MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MO
31、V CX,VECTOR-SIZE FINIT ;初始化协处理器。FLDZ ;加载+0.0到栈顶寄存器ST中,作为累加初值。START:MOV SI,CX ;计算当前分量的地址偏移量。DEC SI SHL SI,1 ;SI=SI*4,因为原始数据是双字长度。SHL SI,1 FLD VECTORSI ;将当前分量压入ST,ST(1)中是每步累加结果。第9章 数学协处理器 FADDP ST(1),ST ;累加,将当前分量弹出,累加结果在ST中。LOOP START ;循环9次,累加结果在ST中。FIDIV VECTOR-SIZE ;ST/N,求平均值,结果放入ST。FLDZ ;加载+0.0到ST中
32、,作为每一分量与平均值差值的 ;平方和的累加初值,ST(1)中是平均值。MOV CX,VECTOR-SIZE MAIN:MOV SI,CX DEC SI SHL SI,1 SHL SI,1 FLD VECTORSI ;将当前分量压入ST,ST(1)中是平方和累加值,;ST(2)中是平均值。第9章 数学协处理器 FSUB ST,ST(2);求当前分量与平均值的差值,结果在ST中。FLD ST(0);将上一步求得的差值再压入在ST中。FMULP ST(1),ST ;求差值的平方并弹出差值。FADDP ST(1),ST ;累加差值的平方并弹出差值的平方。LOOP MAIN ;循环9次,求得差值的平方
33、和在ST中,;ST(1)中是平均值。FIDIV VECTOR-SIZE ;求差值的平方的平均值。FSQRT ;求均方差,结果在ST中。FSTP STANDARD-DEV;将均方差从ST弹出到存储器指定单元。;STANDARD-DEV中。FST AVERAGE ;将平均值从ST弹出到存储器 ;指定单元AVERAGE中。AVEDEV ENDP CODE ENDS END AVEDEV 第9章 数学协处理器 例例9.3 求自然对数和常用对数。程序功能:对栈顶内容求以e为底的对数和以10为底的对数。NATURAL LOG(ST)求自然对数 LN PROC FAR FLDLN2 FXCH FYL2X R
34、ET LN ENDP;COMMON LOG(ST)求常用对数 LOG10 PROC FAR FLDLG2 FXCH FYL2X RET LOG10 ENDP 第9章 数学协处理器 说明:(1)程序的算法利用了对数换底公式lognX=logn2*log2X;(2)从本例可以看出,协处理器的常数指令和超越指令给数值计算程序的编写带来了许多方便。第9章 数学协处理器 例例9.4 求函数10X,eX,YX。程序功能:分别求以10、e、Y为底,X为指数的幂。STACK SEGMENT PARA STACK STACK DW 200H DUP(0)STACK ENDSDATA SEGMENT PARA P
35、UBLIC DATA STATUS-WORD DD?;NPX状态字存储单元。CONTROL-WORD DD?;NPX控制字存储单元。CONTROL-WORD-TEMP DD?;NPX新控制字暂存单元。HALF DD 0.5 第9章 数学协处理器 DATA ENDS CODE SEGMENT PARA PUBLIC CODE;2 TO THE Z(ST),计算2Z的子程序,Z在栈顶寄存器ST中。TOW2THEZ PROC NEAR PUSH AX FSTCW CONTROL-WORD;将NPX控制字存入存储器中。FSTCW CONTROL-WORD-TEMP FWAIT ;将NPX控制字中的RC
36、域设置为01B;向下舍入。AND CONTROL-WORD-TEMP,0F3FFH OR CONTROL-WORD-TEMP,00400H FLDCW CONTROL-WORD-TEMP 第9章 数学协处理器 FLD ST(0);将Z在栈顶再复制一份。FRNDINT ;将Z舍入至整数Z1ST,ST(1)=Z。FLDCW CONTROL-WORD ;恢复原NPX控制字。FSUB ST(1),ST ;ST(1)=Z2=(Z-Z1)。FXCH ;ST=Z2,ST(1)=Z1。FLD HALF ;将0.5压入ST。FXCH ;ST=Z2,ST(1)=0.5。;缩减Z2至00.5之间:ST=Z2时,C1
37、=0;ST=(Z2-0.5)时,C1=1。FPREM FSTSW ;将NPX控制字存入存储器中,准备检测条件码C1位。FWAIT FSTP ST(1);ST=缩减后的Z2,ST(1)=Z1。第9章 数学协处理器 ;计算ST=(2ST-1)+1;F2XM1 FLD1 FADDP ST(1),ST ;检测条件码C1位 TEST BYTE PTR STATUS-WORD+1,00000010B JZ WAS-Z2 ;C1=0说明ST=2Z2,则不需乘20.5。;否则,说明ST=2(Z2-0.5),需再乘20.5,即ST=ST20.5。FLD1 FADD ST,ST(0)FSQRT FMULP ST(
38、1),ST 第9章 数学协处理器 WAS-Z2:FSCALE ;ST=ST2ST(1),ST(1)=Z1。FSTP ST(1);保存结果,并弹栈。POP AX RET TWO2THEZ ENDP;EXP(X)(ST)EXP PROC NEAR FLDL2E ;装入log2e。FMULP ST(1),ST CALL TWO2THEZ RET EXP ENDP;10 TO THE X(ST)TEN2THEX PROC NEAR 第9章 数学协处理器 FLDL2T ;装入log210。FMULP ST(1),ST CALL TWO2THEZ RET TEN2THEX ENDP;Y TO THE X(
39、ST(1),ST);ASSUMES Y IS POSITIVE IN ST ;假设Y在栈顶寄存器ST中。;ASSUMES X IS POSITIVE IN ST(1);X在ST(1)中。Y2THEXPROC NEAR FYL2X ;计算X*log2Y。CALL TWO2THEZ RET Y2THEX ENDP CODE ENDS 第9章 数学协处理器 说明:(1)本例共包含4个NEAR过程,分别用来计算2X,10X,eX,YX。算法的依据是公式YX=2(X*log2Y)。(2)程序的关键部分在于计算2Z,即过程TWO2THEZ。程序先求出小于Z的最大整数Z1,再计算Z2=Z-Z1。如果Z20.
40、5,则运算2(Z2-0.5)20.5;如果Z20.5,则直接计算2Z2。最后将结果乘上2Z1。第9章 数学协处理器 (3)此程序利用指令F2XM1对0X0.5的变量进行运算,而利用指令FSCAL对整数进行运算。注意,对80287XL及以后的协处理器,指令F2XM1将参数允许的范围增大到-1X1,则对Z的小数部分的处理要简单得多:可以采取任何一种舍入方式进行整数和小数部分的分离,然后直接对它们作用指令F2XM1和FSCAL。第9章 数学协处理器 例例9.5 实数运算实例:正弦波的绘制。程序功能:计算一个0至90度之间的整数角度的正弦,并在图形方式下画出一个完整的正弦波。说明:本程序使用了宏库MA
41、CRO.LIB,其中涉及到的两个宏SETSCREEN和WRITEDOT的清单如程序列表所示。第9章 数学协处理器 PAGE 60,132 TITLE SINE IF1 INCLUDE MACRO.LIB ENDIF STACK SEGMENT PARA STACK STACK DW 64H STACK END DATA SEGMENT PARA PUBLIC DATA ANGEL DW 0;角度单元,起始值为0。TEMP DW?;中间存储单元。CONST DD 180.0 ;角度与弧度相互转换的常数。第9章 数学协处理器 MULTIP DW 100 ;将正弦值放大100倍,以便画图。POS D
42、W 0 ;画图时横坐标值0360,初值为0。INDEP DB 0 ;画图时纵坐标值。SINE DQ 91 DUP(?);正弦值存储区。DATA ENDS CODE SEGMENT PARA PUBLIC CODE SINEWAVE PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACK,ES:NOTHING MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV SI,0;SI是在存储区SINE中的变址。第9章 数学协处理器 AGAIN:MOV AX,ANGEL CMP AX,45 ;45是边界条件。JG FIXIT ;如果大
43、于,转移。JMP CONT ;如果不大于,继续。FIXIT:NEG AX ADD AX,90 ;90-AX,结果在AX中。CONT:MOV TEMP,AX ;把结果保存在TEMP中。FINIT ;初始化协处理器。;将角度转化成弧度单位,ANGEL*PI/180.0 FLDPI ;把PI放在堆栈顶。FLD CONST ;把常数装入堆栈。FDIV ;PI/180.0。FLD TEMP ;装入调整的整数角度。第9章 数学协处理器 FMUL ;(PI/180.0)角度。FPTAN ;求上述乘积的部分正切,ST=X,ST(1)=Y。FWAIT ;同步化。MOV AX,ANGEL ;检查角度大小。CMP
44、AX,45 JG COSINY;如果大于45,用CONSIN=X/斜边。JMP SININ ;如果等于或小于,用SINE=Y/斜边。COSIN:FXCH ST(1);用CONSIN要交换堆栈,用SINE无堆栈交换。SININ:;求斜边,斜边=(X2+Y2)1/2 FMUL ST(0),ST ;FXCH ST(1);ST=X或Y,ST(1)=Y2或X2。FLD ST(0);FMUL ST(0),ST 第9章 数学协处理器 FADD ST(0),ST(2)FSQRT ;求得斜边,ST=斜边,ST(1)=X或Y。FDIVP ST(1),ST ;求得正弦值。FIMUL MULTIP ;放大100倍。F
45、STP SINESI ;结果弹入存储器。FWAIT ;同步化。ADD SI,02 ;指向下一个SINE单元。ADD ANGEL,1 ;角度增加。CMP ANGEL,90 ;进行0到90。JLE AGAIN ;如果没到91,重复进行。;在高分辨率图形屏幕上画出计算的各点。SETSCREEN ;设置图形屏幕。MOV SI,0 ;找到表的起点。MOV AX,POS ;把角度值送AX。CMP AX,180 ;是否大于180?第9章 数学协处理器 JLE NEWQUAD ;如果小于,角度在1或2象限。SUB AX,180 ;如果大于,调整角度(角度-180)。NEWQUAD:CMP AX,90 ;是否大
46、于90?JLE SECQUAD ;如果小于,转SECQUAD。NEG AX ;大于90,调整角度(180-角度)。ADD AX,180 SECQUAD:ADD SI,AX ;SI得到偏移量和。SHL SI,1 ;确定为字变址(2)。MOV AL,BYTE PTR SINESI;得到数值并放在AL中。CMP POS,180 ;角度是否大于180?JLE SMALDIS NEG AL ;如果角度大于180,得到值的负数。第9章 数学协处理器 SMALDIS:ADD AL,100 ;数值加100,调整屏幕位移量,使纵坐标值非负。MOV INDEP,AL WRITEDOT ;画点宏调用。ADD POS,1 ;得到下一个的角度。CMP POS,360 ;完成360否?JLE AGAIN ;如未完成,再次执行。SINWAVE ENDP CODE ENDS END SINWAVE SETSCREEN MACRO ;设置高分辨率屏幕。MOV AX,0006H ;200640点黑白。第9章 数学协处理器 INT 10H ENDM WRITEDOT MACRO ;画点宏调用。MOV AX,1201H MOV CX,POS ADD CX,140 ;显示取中。MOV DH,00 MOV DL,INDEP INT 10H ENDM