微机原理答疑题库.doc 25页

  • 272.50 KB
  • 2022-04-22 11:46:31 发布

微机原理答疑题库.doc

  • 25页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'《微机原理》答疑题库1.计算21*12-117/9的源程序.2.答:MOVAL,21;将21取出来MOVBL,17;将17取出来MULBL;计算21*17MOVCX,AX;将结果暂存起来(得结果1)MOVAX,117;将117取出来MOVBL,13;将13取出来DIVBL;计算117/13(得结果2)SUBCX,AX;将结果1-结果2,得到最终结果HLT2.采用总线结构有什么优点?答:采用总线结构后,计算机的主要功能部件就都"挂在"总线上,系统的各种信息都通过总线传输。相对于一些各部件"随机"连线的电子产品,这种方式有很突出的优点:结构简化:统一的总线连接,使系统的结构清晰、简化。设计简化:在确定了总线的标准后,各功能部件都可以以此标准为依据,分别进行设计。同时,凡符合此标准的部件也都可以直接连接起来。这种设计方式叫"面向总线的设计方法",它大大减小了设计的工作量。扩充容易:采用总线结构的计算机,如果需要在系统中扩充新的功能部件,相对较为容易,一般只需要将符合该总线标准的部件直接接入即可(当然需考虑驱动能力的问题)。对此,我们在给PC机安装新的板卡时应有体会3.总线的分类. 答:按总线所处的位置不同,总线可分为四级:片内总线:又称芯片内部总线,位于芯片内部,由它实现芯片内部各功能单元电路之间的相互连接。片总线:又称元件级总线或局部总线,是微计算机主板或单板微计算机上,以μP芯片为核心,芯片与芯片间的连接总线。内总线:又称微计算机总线或板级总线,一般又称微机系统总线。它用来实现微计算机系统中插件板与插件板间的连接。外总线:又称通信总线。它用于系统之间的连接,完成系统与系统间的通信(如微计算机系统与微计算机系统之间,微计算机系统和仪器或其它电子设备之间)。按总线上所传输的信息类型的不同,总线又可分为三种:数据总线(DataBus或DB):数据总线是传输数据或代码的一组通信线,其条数与处理器字长相等。地址总线(AddressBus或AB):地址总线是传送地址信息的一组通信线,是微处理器用来寻址存储器单元(或I/O接口)用的总线。控制总线(ControlBus或CB):控制总线是用来传送各种控制信号的,这些信号是微处理器和其它芯片间相互提供状态信息,或进行相互控制的。4.指令执行的全过程。答:取指令1过程   (1)CPU将PC的内容00H送至地址缓冲寄存器AR;   (2)当PC内容送入AR后,PC内容自动加1,变为01H;   (3)AR将00H地址信号通过地址总线送至存储器,经地址译码器译码,选中00H单元;   (4)CPU经控制总线发出"读"命令到存储器;   (5)所选中的00H单元的内容3EH读到数据总线DB上;   (6)读出的内容经数据总线送至CPU数据缓冲寄存器DR;   (7)因是取指令阶段,读出的必为操作码,故DR将它送至指令寄存器IR,经指令译码器ID译码后,发出执行这条指令所需要的各种控制命令。   指令经泽码后,判定是一条取操作数送累加器A的指令,而操作数放在第二字节,因而,执行第一条指令,必须是取出第二字节中的操作数。 执行指令1的过程   (1)CPU把PC的内容01H送至AR;   (2)当PC内容送至AR后,PC内容自动加1,变为02H;   (3)AR将地址信号01H通过地址总线送到存储器,经地址译码后选中01H单元;   (4)CPU经控制总线发出"读"命令到存储器;   (5)所选中的01H单元内容15H读到数据总线DB上;   (6)通过DB总线,把读出的操作数15H送到DR;   (7)因已知读出的是操作数,且指令要求选的累加器A,放由DR通过内部数据总线进入A中。至此,第一条指令执行完毕,接着进入第二条指令的取指阶段。请注意上面步骤中,PC内容自动加1这个操作,它并不是由某条指令控制的,它是由处理器内固定逻辑决定的,正是这一操作,决定了处理器能按顺序执行整个程序。5.求十进制56D的二进制表示及二进制数10110110B的十进制表示(结尾的字符D表示十进制数,字符B表示二进制数,字符H表示十六进制数)解:56=1*2^5+1*2^4+1*2^3所以56D用一字节字符二进制数表示即为00111000B10110110B=1*2^7+1*2^5+1*2^4+1*2^2+1*2^1=182D6.求–75D的二进制和16进制单字节补码及双字节补码表示解:+75D二进制补码=01001011B将01001011各位取反,得10110100B,末位加1得10110101B所以-75D单字节补码=10110101B=0B5H其双字节补码可由将单字节补码的最高位扩展到高字节得到.即-75D双字节补码=1111111110110101B=0FFB5H(注意,对于16进制数,若第一个数字是字母A—F,则应在前面加上0)7.求补码0A5H的真值。解:0A5H=10100101B各位取反,得01011010B末位加1得01011011B=91D所以,0A5H的真值为十进制的-91(注意,正数与负数是互补的关系)8.求12.5D的定点数表示解:要想求定点数表示,首先应确定定点数的格式。假设我们用两字节表示整数部分,两字节表示小数部分,即用四字节表示该定点数。分别求出整数部分和小数部分的二进制表示:12=0000000000001010B0.5=0.1000000000000000B所以,12.5D的四字节定点数表示为00000000000010101000000000000000B或000C8000H9.求12.5D的三字节浮点数表示解:要想求浮点数表示,首先应确定浮点数的格式。这里我们使用一种常用的三字节浮点数格式:第一字节为阶码,其中,最高位为数值的符号,次高位为阶的符号;第二、三字节为尾数,尾数必须大于等于0.5。另外,阶码和尾数用原码表示。根据以上格式规定,可得如下求法:12.5=0.78125*16=0.78125*2^4所以:尾数=0.78125阶=4将尾数转化为二进制,得0.78125=0.1100100000000000B所以,原数的三字节浮点数表示为:000010001100100000000000B或:04C800H 10.8086内部的地址产生器是如何产生实际地址的?答:由于指令指针和通用寄存器都是16位,8086为了产生20位的地址(此地址称为实际地址或物理地址PA(PhysicAddress),采用地址产生器这一个部件。在地址产生器中,先将段寄存器中存放的段地址(16位)左移四位,然后再与偏移地址或逻辑地址(16位)的内容相加,就得到20位的实际地址。8086CPU实际输出的用于对存储器寻址的地址就是这种20位的实际地址。 也就是说,我们有公式:PA=段地址*16+偏移地址11.如何给8086复位呢?答:在此引脚加上一个高电平脉冲,脉冲宽度大于等于4个时钟脉冲宽,而在初次接通电源时不能小于50us宽,就会强制8086进行复位操作。当此复位脉冲回到低电平后,8086就进入正常工作模式。12.8088和8086的比较 答:准十六位的8088CPU是继8086之后推出的,被畅销全球的IBM-PC机选作CPU,它与8086CPU具有类似的体系结构。两者的执行部件EU完全相同,其指令系统,寻址能力及程序设计方法都相同,所以两种CPU完全兼容。这两种CPU的主要区别,归纳起来有以下几方面: 1.外部数据总线位数的差别:8086CPU的外部数据总线有16位,在一个总线周期内可输入/输出一个字(16位数据),使系统处理数据和对中断响应的速度得以加快;而8088CPU的外部数据总线为8位,在一个总线周期内只能输入/输出一个字节(8位数据)。也正因为如此,8088被称为准16位处理器。2.指令队列容量的差别:8086CPU的指令队列可容纳6个字节,且在每个总线周期中从存储器中取出2个字节的指令代码填入指令队列,这可提高取指操作和其它操作的并行率,从而提高系统工作速度;而8088CPU的指令队列只能容纳4个字节,且在每个总线周期中只能取一个字节的指令代码,从而增长了总线取指令的时间,在一定条件下可能影响取指令操作和其它操作的并行率。3.引脚特性的差别:两种CPU的引脚功能是相同的,但有以下几点不同:(1)AD15~AD0的定义不同:在8086中都定义为地址/数据复用总线;而在8088中,由于只需用8条数据总线,因此,对应予8086的AD15~AD8这8条引脚,只作地址线使用。(2)34号引脚的定义不同:在8086中定义为BHE信号;而在8088中定义为SS0,它与DT/R,IO/M一起用作最小方式下的周期状态信号。(3)28号引脚的相位不同:在8086中为M/IO;而在8088中被倒相,改为IO/M,以便与8080/8085系统的总线结构兼容。13.8284A有两种不同的连接方法。 答:一种方法是用外接脉冲发生器作振荡源,这时,只要将脉冲发生器的输出端和8284A的EFI端相连即可,此时,必须将F/C接为高电平。此时,时钟输出实际上是外接的脉冲发生器产生的。输入到8284A中的目的是提高驱动能力及给其他信号(例如RDY,RES)提供同步作用。  另一种方法更为常用,是利用一块晶体作为振荡元件,使用片内的振荡器产生时钟输出,这时,需将晶体振荡器连在8284A的X1和X2两端上,且须将F/C接地。  不管用哪种方法,8284A输出的时钟CLK的频率均为振荡源频率的三分之一,而芯片上PCLK引脚输出的脉冲又是CLK的二分频。振荡源频率经8284A驱动后,由OSC端输出,可供系统使用。14.最小方式下,8086的24~31脚的控制线功能及含义。答: (1)M/IO(Memory/InputandOutput,输出,三态)存储器/输入输出控制信号:用于区分是访问存储器还是访问IO,被接至存储器芯片或接口芯片的片选端。若为高电平,表示CPU和存储器之间进行数据传输;若为低电平,表示CPU和输入/输出设备之间进行数据传输。当DMA时,此线被置为浮空。 (2)WR(WRite,输出,低电平有效,三态)写控制信号是CPU用来表示在进行对存储器或是对I/O进行写操作。在任何写周期,WR只在T2,T3和Tw有效,在DMA时,此线被置为浮空。 (3)HOLD(HOLDRequest,输入,高电平有效)总线保持请求信号 是系统中的其它总线主控部件向CPU发出的请求占用总线的控制信号。这里总线主控部件指的是能像CPU一样,能通过地址总线发出地址信号,通过控制总线发出控制信号,通过数据总线对存储器或I/O端口进行访问的部件。这样的一种操作也叫占用总线。 当8086收到一个有效的HOLD信号后,它在当前的总线周期执行完后,会同时使具有三态功能的地址/数据总线和控制总线处于浮空,从而使这些信号线与8086处于隔离的状态。这也叫8086出让总线。8086此时发出HLDA信号,以通知发出HOLD信号的总线主控部件。总线请求部件收到HLDA后,获得总线控制权,从这时间开始,HOLD和HLDA都保持高电平。当请求部件完成对总线的占用后,将把HOLD信号变为低电平(无效),CPU收到无效信号后,也将HLDA变为低电平,这时,CPU又恢复了对地址/数据总线和控制总线的占有权。在CPU出让总线期间,由于它不能通过总线读取存储器中的指令,因此,它只能执行其片内指令队列中的指令代码,若这些指令代码执行完毕,或因需要执行某种总线周期而不能继续执行下去,CPU就处于暂停状态。 (4)HLDA(HOLDAcknowledge,输出,高电平有效)总线保持应答信号是与HOLD配合使用的联络信号。在HLDA有效期间,所有三态输出的CPU三总线引脚都应处于浮空,从而让出总线。 (5)INTA(INterruptAcknowledge,输出,低电平有效)中断响应信号是在中断响应周期中由CPU对外设中断请求作出的响应。对8086,INTA信号实际上是位于连续两个总线周期中的两个负脉冲(见图2-24),在每个总线周期的T2,T3和Tw状态下,INTA端为低电平。第一个负脉冲通知外设的接口,它发出的中断请求已经得到允许;第二个负脉冲期间,由外设接口往数据总线上放中断类型码,使CPU得到有关该中断请求的详尽信息。 (6)ALE(AddressLatchEnable,输出,高电平有效),地址锁存允许信是CPU在每个总线周期的T1状态发出的,作为地址锁存器(例如8282/8283)的地址锁存信号。 (7)DT/R(DataTransmit/Receive,输出三态)数据收发控制信号是在系统使用类似8286/8287的数据缓冲器作为数据总线收发器时,控制其数据传送方向的。如果DT/R为高电子,则进行数据发送。否则,进行数据接收。在DMA下,DT/R被置为浮空。 (8)DEN(DataEnable,输出低电平有效,三态)数据允许信号是8086提供给类似8286/8287的数据缓冲器的选通信号,接至其OE端,用于打开缓冲器的输出三态门。在每个访问存储器或访问I/O周期,或者中断响应周期均有效。在DMA下,被置为浮空。需要指出的是,在最小方式下,8086和8088的34号引脚定义不同:对8086来说,此引脚定义为BHE/S7,由于S7未被赋予固定定义,故此引脚只用来提供高位字节数据总线允许信号,作存储器高位库的选择信号(见图2-28)。34号引脚只在总线周期的T1状态输出,因此也需要进行锁存。锁存时BHE和高四位地址(A19~A16)一起由第3片8282/8283进行锁存。对8088来说,外部数据总线只用低8位,因而不需要BHE,34号引脚被定义为SS0,SS0和M/IO及DT/R组合起来,决定了当前总线周期的操作,具体对应关系如表2.6所示。对于有些只配备64K内存的小系统,只需用到16位地址线,若这时的CPU又采用8088,不存在BHE信号,因此,在最小方式系统的配备中就只需2片8282/8283作锁存器了。15.最大方式下,24~31脚的控制线功能含义。 答:(1)S2,S1,S0(BusCycleStatus,输出,三态)总线周期状态信号是表示CPU总线周期的操作类型的。8288总线控制器依据这三个状态信号产生访问存储器和I/O端口的控制命令。表2-7示出S2~S0对应的总线周期类型及8288产生的控制命令。表中的无源状态是表示一个总线操作周期结束,而另一个新的总线周期还未开始的状态。 (2)QS1、QS0(InstructicnQueueStatus,输出)指令队列状态信号这两个信号组合起来提供前一个时钟周期(即总线周期的前一个状态)中指令队列的状态,以便于外部对8086BIU中的指令队列的动作跟踪。QS1、QS0组合与队列状态的对应关系见表2-8。              (3)RQ/GT1、RQ/GT0(Request/Grant,双向)总线请求输入/总线请求允许输出信号这两个双向信号是在最大方式时裁决总线使用权的信号。其功能类似于最小方式下的HOLD与HLDA两信号,即它们也是用于请求8086处理器暂时出让总线控制权的申请信号及8086同意出让控制权的响应信号。只不过是现在申请与响应信号复用一个引脚,先作为申请、后作为响应,两者的有效形式都是低电平脉冲信号。注意,现在,CPU脱离此状态,重新获得总线控制权的条件是:总线请求设备通过同一个引脚再送来一个低电平脉冲。    在CPU出让总线期间,由于它不能通过总线读取存储器中的指令,因此,它只能执行其片内指令队列中的指令代码,若这些指令代码执行完毕,或因需要执行某种总线周期而不能继续执行下去,CPU就处于暂停状态。    两个引脚功能相同,但当两者同时有请求时,RQ/GT0有更高优先权,即优先输出允许信号。最大方式下的总线请求/允许/释放时序见图2-26。 (4)LOCK(Lock,输出,三态)总线封锁信号此信号线为低电平时,表示CPU要独占总线使用权。LOCK信号是由指令前缀LOCK产生的,带LOCK前缀的指令在执行期间,将输出有效的LOCK信号,它表示此时不允许系统中其他的总线主控设备申请占用总线。在LOCK前缀后面的一条指令执行完后,便撤消了LOCK信号。此信号是为避免多个处理器使用共有资源时产生冲突而设置的。此外,在8086的2个中断响应脉冲之间,LOCK信号也自动有效,以防其他的总线主控部件在中断响应过程中占有总线,而使一个完整的中断响应过程被间断。另外,必须注意,有些指令执行需要多个总线周期,而总线请求可以在当前总线周期结束后就获得响应,因此,某些指令的完整执行可能被打断,由此可能会造成共有资源使用的冲突。这是,我们就有必要使用LOCK信号及LOCK指令前缀。16.Tw状态的含义。答:当系统中所用的存储器或外设的工作速度较慢,不能在基本总线周期规定的四个状态完成读操作时,它们将通过8284A时钟产生器给CPU送一个READY=0信号。CPU在T3的前沿(下降沿)采样READY。当采到的READY=0时(表示"未就绪"),就会在T3和T4之间插入等待状态Tw。在Tw内,CPU所有信号都延续T3内的状态,实际上就是增加对存储器或外设的访问时间。Tw可以为1个或多个。以后,CPU在每个Tw的前沿(下降沿)去采样READY,直采到的READY=1(表示"已就绪")时,就在本Tw完结时,脱离Tw而进入T4状态。在最后一个Tw,数据已出现在数据总线上,所以,Tw等待状态的作用是,延长CPU读写内存(或I/O口)的时间,以便速度较慢的内存(或I/O口)芯片能在规定的总线周期的时间内,完成数据的存取,以实现与CPU的正确接口。17.从10000H开始的内存单元存放有"A”到"G”的ASCII码,请画出存储示意图。解:"A”到"G”的ASCII码分别是41H到47H,是一字节数据,它们按顺序存放于10000H开始的7个单元。如下图所示:地址内容10000H41H10001H42H10002H43H10003H44H10004H45H10005H46H10006H47H  18.有三个字数据,分别是1268H,0A132H,3630H,分别存储在20000H与21001H开始的单元,并连续存放,请画出存储示意图。解:对于字数据,8086遵循高字节存放于高地址,低字节存放于低地址的原则。掌握了这一点,本例即可完成。                 地址内容20000H68H20001H12H20002H32H20003H0A1H20004H30H20005H36H显然,以上存放方式为规则存放。地址内容21001H68H21002H12H21003H32H21004H0A1H21005H30H21006H36H显然,以上存放方式为非规则存放。19.有两个双字数据,第一个是56131274H,第二个是个双字指针,其段地址是3562H,偏移地址是1330H,存储在1F000H开始的单元,并连续存放,请画出存储示意图。解:对于双字数据,8086遵循高字存放于高地址,低字存放于低地址的原则。另外,对于段地址加偏移地址的指针,8086系统中是在低地址处存储偏移地址,在高地址处存储段地址,因此有:地址内容1F000H74H1F001H12H1F002H13H1F003H56H1F004H30H1F005H13H1F006H62H1F007H35H20.设某单元段地址为1234H,偏移地址为5678H,其物理地址为多少?另位于1000H段的17523H单元的偏移地址是多少?解:将段地址*16+偏移地址即得其物理地址。故第一问的答案是:物理地址是1234H*16+5678H=12340H+5678H=179B8H第二问的偏移地址是:17523H-10000H=7523H21.存储器分段的含义。答:8086使用20位地址信号能够寻址1MB的内存空间,但是其内部存放地址信息的指令指针IP、堆栈指针SP、基指针BP和变址寄存器SI、DI等都只有十六位,显然不能直接寻址1MB空间,为此,在十六位微处理器引入分段的新概念。 8086把1MB空间分为若干逻辑段,每段最多可含64KB长的连续存储单元。每个段的起始地址又叫基址(BaseAddress),基址是一个能被16整除的数,即最后4位为0。 例如,00000H,00010H,00020H, ...,FFFF0H都可以是段基址。  引入了逻辑段后,我们可以将一个内存单元的地址用两个部分表示:段地址与偏移地址,段地址表示段的基址,数值上为基址除以16,例如上面的基址对应的段地址为:0000H,0001H,0002H, ...,FFFFH,这是一些16位长的数。偏移地址表示每个逻辑段中的单元相对于段基址(起始地址)的距离,由于一个段最长为64KB,因此,距离最大也不超过FFFFH,所以偏移地址最大为FFFFH,即它也可用16位二进制表示。 段和段之间可以是连续的、分开的、部分重叠的或完全重叠的,如图2-30所示。一个程序所用的具体存储空间可以为一个逻辑段,也可为多个逻辑段。                           段地址存放于段寄存器CS,DS,SS和ES中,所以,程序可以从四个段寄存器给出的逻辑段中存取代码和数据。若要从别的段存取信息。程序必须首先改变对应的段寄存器内容,将其设置成所要存取段的基址。22.单模块程序的编写。答:为了使学习者尽早将存储器的分段和它在汇编语言程序中的具体实现方法结合起来,下面列出了一个具有四个现行段的单模块汇编语言程序。重点在于了解运行一个程序所需的四个现行段——代码段,数据段,堆栈段和附加段的实现方法。其中:前三个段是分开的,而附加段是与数据段完全重叠的。每个段都标有段名,且用伪指令SEGMENT/ENDS来定义段,每个段不超过64KB,操作系统DOS将给各个段分配存储地址。本示例程序的功能是最简单的:5+2=7,其结果一方面可存入数据区中的SUM单元,另一方面也可在屏幕上显示出来。其源程序如下所示:         ;SAMPLE  PROGRAMFORADDANDDISPLAYSUMTOTHESCREEN          ;------------------------------------------------------                    DATA   SEGMENT            ;数据段                    AUGEND DB  05H                    ADDEND DB  02H                    SUM     DB ?           DATA    ENDS         ;------------------------------------------------------           STACK   SEGMENTPARASTACK"STACK’;堆栈段                            DB 64 DUP(?)           STACK   ENDS         ;------------------------------------------------------                    CODE   SEGMENT            ;代码段                    START   PROCFAR                            ASSUMECS:CODE,DS:DATA,SS:STACK,ES:DATA                             PUSH DS           ;保存返回地址                             MOV  AX,0                             PUSH AX                             MOVAX,DATA       ;初始化DS,ES                             MOVDS,AX                             MOVES,AX                             MOVAL,AUGEND     ;完成05H+02H的程序正文                           ADDAL,ADDEND                             MOVSUM,AL       ;存结果                            ADDAL,30H        ;将结果变为ASCll码                             MOVDL,AL         ;显示结果                             MOVAH,02H                             INT21H                             RET               ;返回DOS                     START  ENDP                     CODE   ENDS                             ENDSTART          ;汇编结束 本程序是一个完整的汇编语言源程序。经过汇编,可以在DOS操作系统上运行。 第1行为程序的注释,用";"开头。 2~6行为数据段,该段中放置有本程序运行所需的被加数AUGEND,加数ADDEND,还设置有一个存和的结果单元SUM,它们均用伪操作指令DB来定义的。本段的段名为DATA,第2行和第6行是段定义语句,分别定义段的开始和终止。  7~9行为堆栈段,STACK为其段名,第7行和第9行分别定义该段的开始和终止,该段中用DB定义了一个深度为64个字节的堆栈区。 10~28行为代码段,该段段名为CODE,第10行和第28行分别定又该段的开始和终止。代码段中用";"开始的汉字部分为注释(也可用英文注释),注释部分为非执行部分,用它来说明一条或几条指令的作用;第11行为过程(Procedure)说明语句PROC,过程有NEAR(近)过程和FAR(远)过程之分,这里为FAR过程,它是DOS下面的一个远过程。第11行和第27行分别表示过程的开始和结束,第26行RET是返回DOS的语句;第12行ASSUME也是一个说明语句,由它设定运行该程序时所需的四个现行段是什么段名,其中:ES和DS用相同的段名,表示这两个段完全重叠。19~21行是完成5+2功能程序的正文,其结果为7(一位十进制数),因此可用22行先将它变为ASCll码后,由23~25行的一个中断调用INT21H交由屏幕显示出来。这里的19~25行是本模块的程序段,它随程序功能不同而不同;而13~18行对不同功能的程序段都是需要的,是不能改变的部分,通常称之为程序的内务操作。内务操作是每个程序要能正确执行,并返回操作系统而不被死锁的操作保证。内务操作又包含两部分:13~15行是保存返回地址,16~18行是对数据段和附加段进行初始化,即把DOS给每个段分配的首地址(即段名的地址)填入相应段寄存器DS,ES中。 2~6行的数据段和7~9行的堆栈段也是随程序段的功能不同而可以改变的。23.寄存器相对寻址的原理。答:在这种寻址方式的指令中,也是指定BX,BP,SI,DI的内容进行间接寻址。但是,和寄存器间接寻址方式不同的是:指令中还要指定一个8位或16位的位移量DISP(Displacement),操作数的有效地址EA则是等于间址寄存器内容和位移量之和。即   EA= (BX)+(DISP8)(BP)(SI)(DISP16)(DI)    对于寄存器为BX,SI,DI的情况,用段寄存器DS内容作段首址,而对于寄存器BP,则使用段寄存器SS内容作段首址。操作数的实际地址为: PA= 16*(DS)+(BX)+(DISP8)(SI)(DISP16)(DI)PA= 16*(SS)+(BP)+(DISP8)(DISP16) 寄存器相对寻址通常也是用来访问数组中的元素,位移量定位于数组的起点,间址寄存器的值选择一个元素。和寄存器间接寻址一样,因数组中所有元素具有相同长度,只要改变间址寄存器内容,就可选择数组中的任何元素。24.基址变址寻址的原理。答:用这种寻址方式,存储器操作数的有效地址EA是由指令指定的一个基址寄存器和一个变址寄存器的内容之和,即EA= (BX)+(SI)(BP)(DI)这共有四种组合情况,将根据基址是在BX,还是在BP中,确定寻址操作是在数据段,还是在堆栈段。对于前者,段寄存器使用DS,对于后者,段寄存器使用SS。基址寻址的操作数的实际地址为:PA=16*(DS)+(BX)+(SI)(DI)PA=16*(SS)+(BP)+(SI)(DI)例如:MOVAX,[BX][SI]或写为:MOVAX,[BX十SI]设:(DS=2000H,(BX)=0158H,(SI)=10A4H,则:EA=0158H+10A4H=11FCHPA=20000H+11FCH=211FCH指令执行后,将把2llFCH和2llFDH相邻两个单元内容传送到AX。而(AL)=(211FCH),(AH)=(2llFDH)。  基址变址寻址方式也可使用段超越前缀。例如:MOVCL,ES:[BX][SI]。 这种寻址方式同样适合数组或表格的处理,由于基址和变址寄存器中的内容都可以修改,因而在处理二维数组时特别方便。用基址变址寻址时,也允许诺一步8位或16位的位移量,带位移量的基址加变址寻址又称为相对的基址寻址。25.根据表3-4,设8086的时钟频率为5MHZ(即时钟周期=0.2uS),试求ADD指令在各种寻址方式下,指令的执行时间t。解:l.两操作数为:寄存器,寄存器,结果在寄存器。这种情况下,对于字操作数或字节操作数均花3个时钟周期,即t=3×0.2=0.6us 2.两操作数为:寄存器,存储器(用相对基址加变址寻址),结果存寄存器,这时需访问一次内存。在这种情况下,对于字节操作或对规则字操作,所需时间为t=9+EA=9+12=21(T)第一项9为这种寻址方式下指令基本运算和基本操作时间,第二项为计算EA的时间,则t=21×0.2=4.2us对于非规则字的操作,则应在上面的时间上再加上一个总线周期时间,如4T,即t=(21+4)T=5.0ns 3.两个操作数为:存储器(用基址变址寻址),寄存器,结果存存储器,这时需访问二次内存。对于字节操作或对规则字操作,指令执行时间为:t=16+EA=16+8=24(T)=4.8us第一项的16为这种寻址方式下指令基本运算和基本操作时间,第二项为计算EA时间。对于非规则字操作,指令执行时间应在上面的时间上加上两个总统周期,则t=(6+8+4+4)T=32T=6.4us还有其它三种寻址方式下,ADD的执行时间,请读者练习计算。 从这个例子可以看出:对于同一种ADD指令,因寻址方式不同,执行指令的时间相差甚远,这是指令的时间指标概念。从表3-4还可以看到:同一类指令使用不同的寻址方式,其指令长度也不一样,即占有的内存的字节数相差也很大,这是指令的空间指标的概念,合起来就是指令的时/空指标。指令是程序的基本组成单元,那么当要求程序有较高的时/空利用率时,就要求程序设计者,不仅要研究程序的算法,数据结构,还要研究指令与寻址方式的选用,才能编制出理想的程序。26.请将当前数据段1000H单元内容送至AH和AL中解:MOVAH,[2000H]MOVAL,AH27.请将当前数据段1000H单元内容送至当前数据段2000H单元处解:MOVAH,[1000H]MOV[2000H],AH 注:存储单元送存储单元,必须用某个寄存器过渡。 28.请将当前数据段1000H单元内容与当前数据段2000H单元内容互换解:MOVAH,[1000H]MOVAL,[2000H]MOV[1000H],ALMOV[2000H],AH  29、有一主程序调用一子程序,子程序中将用到AX,BX、CX和DX。为了使主程序中这些寄存器内容不被破坏,在进入子程序时应进行入栈保护,子程序执行完后,再出栈恢复原来的数据。子程序中的保护现场和恢复现场的 程序段为:SUBROUTPROCNEAR;定义过程(即子程序)PUSHF;以下保护现场PUSHAXPUSHBXPUSHCXPUSHDX..    ;(子程序主体) .POPDX      ;以下恢复现场POPCXPOPBXPOPAXPOPFRET       ;返回SUBROUT  ENDP ;过程结束 请注意PUSH指令与POP指令的用法。他们的使用一定是对称的。这样,调用该子程序前后,堆栈没有变化。30.数字0~9对应的格雷码为:18H,34H,05H,06H,09H,0AH,0CH,11H,12H,14H,依次放在内存以TABLE开始的区域。当10号端口输入一位十进制数码时,要求CPU将之转换为相应的格雷码再输出给该端口,源程序段如下:MOVBX,TABLEINAL,10XLATTABLEOUT10,AL若10号端口输入值为7,则查表转换后输出值为11H。31.将数据段中从AREA1开始存放的100个字节数搬到附加段以AREA2为首址的区中。这里,假设用SI和DI寄存器分别作AREA1区和AREA2区的指针,指向起始地址,采用重复传送一个字节数的循环结构实现。实现100个字节数搬家的程序段如下:LEASI,AREA1;将AREA1区的首地址放入SI中LEADI,AREA2;将AREA2区的首地址放入DI中MOVCX,100;CX作计数器,值为要操作的字节数100AGAIN:MOVAL,[SI];取第一个字节的内容MOV[DI],AL;将第一个字节的内容放入DI所指的AREA2区的第一个地址单元中INCSI;SI的内容加一,即指向AREA1区的第二个地址单元INCDI;DI的内容加一,即指向AREA2区的第二个地址单元DECCX;CX减一,表示已完成搬运一个字节JNZAGAIN;跳转到标号为AGAIN的语句继续执行。循环操作,当CX减为零时,不执行跳转操作而直接执行下一条语句。32.设某程序在调用子程序ROUT之前,在堆栈顶部存放着一个字符串的首地址。要求在执行子程序ROUT时,将该字符串首地址取道到ES和DI,然后调用字符串显示子程序DISP进行显示。调用子程序ROUT前后的堆栈状况如图所示。其程序段为:ROUT:PUSHBP;保存BPMOVBP,SP;保存当前栈顶到BP中PUSHES;保护现场PUSHDILESDI,[BP+4];取堆栈中字符串首址到ES和DI中CALLDISP;调显示子程序(后续处理)OPDI;恢复现场POPESPOPBPRET;返回 本例子很重要,除了说明LEA指令用法以外,还演示了主程序调用子程序(在这里为ROUT)时,如何通过堆栈传递参数。  本例中,主程序在调用子程序ROUT之前,先将要传递的参数(字符串的首地址),推入到堆栈,然后再执行调用ROUT的指令(CALLROUT)。这样,堆栈内容即如图所示。 进入ROUT子程序后,代码要在堆栈中取出入口参数,可用BP作为间接寻址的寄存器。因此,ROUT中,首先将BP原内容进行保护起来,再将当前堆栈顶地址SP送到BP,这样,BP+4,就指向了人口参数所在的单元。 注意:在堆栈中,地址是向上生长的,即由高地址向低地址方向生长。33分析ADDAX,0F0F0H的执行情况。设指令执行前(AX)=5463H;解:(AX)=0101010001100011+Imm=11110000111100001<-0100,0101,0101,0011->AX执行后,得结果(AX)=4553H,且CF=1,ZF=0,SF=0,OF=034现有两个双倍精度字1234FEDCH和11228765H,分别放在数据段中从1000H和2000H开始的存储单元中,低位在前,高位在后。要求相加之后所得的和放在从1000H开始的内存单元中。解:对双倍精度字相加,可分为两段进行,先对低位字相加,后对高位字相加,实现对此双倍精度字相加的程序段如下:MOVSI,1000H;设源指针指向1000HMOVAX,[SI];将第一数的低位字取入AXMOVDI,2000H;设目的指针指向2000HADDAX,[DI];低位字相加MOV[SI],AX;存低位字相加之和MOVAX,[SI+2];将第一数的高位字取入AXADCAX,[DI+2];两高位字连同进位相加MOV[SI+2],AX;存高位字相加之和加法指令只能对八位或十六位二进制数进行运算,所以对于超过十六位的二进制数,必须从底位开始计算。35.无符号数和带符号数的特点。 答: 1)用CF可检测无符号数是否溢出,用OF可检测带符号数是否溢出;   2)无符号数运算结果溢出是在超出了最大的表示范围这唯一的原因下发生的,溢出也就是产生进位,这不能叫出错。因此,在多字节数的相加过程中,正是利用溢出的CF来传递低位字节向高位字节的进位;而带符号数运算产生溢出就不同了,它是由Cs和C。两种综合因素表示的,一当发生溢出,就表示运算结果出错。   这种情况的出现在于,在CPU内部,有符号数依然是作为无符号数来运算的,即符号位也是要参与运算的,所以会出错。   算术运算指令涉及的操作数从表示的进制来讲,可以是二、十六进制数,也可以是BCD码表示的十进制数,因一位BCD码用4位二进位表示,因此操作数为BCD十进制数时,是不带符号的十进制数。十进制数运算所得结果,应加校正指令进行调整,8086专门设有对BCD码运算结果进行调整的各种指令。   8086算术运算指令可用的BCD码有两种;一种叫组合的BCD码(PackedBCD),即l个字节表示2位BCD码;另一类叫非组合的BCD码(UnPackedBCD),用这类代码时,1个字节只用低4位来表示l位BCD码,高4位为0(无意义)。   算术运算指令的特点有:    1)在加、减、乘、除基本运算指令中,除±1指令外,都具有两个操作数;    2)这类指令执行后,除±1指令不影响CF标志外,对CF,OF,ZF,SF,PF和AF等6位标志均可产生影响,由这6位状态标志反映的操作结果的性质如下:     ①当无符号数运算产生溢出时,CF=l;     ②当带符号数运算产生溢出时,OF=1;     ③当运算结果为零,ZF=l;     ④当运算结果为负,SF=1;      ⑤当运算结果中有偶数个1,PF=1;     ⑥当操作数为BCD码,半字节间出现进位,需要进行BCD码调整,AF=1。 36.将两个具有16位的BCD数相加,被加数和加数分别放在从FIRST和SECOND开始的存储单元中,结果放在THIRD开始的单元。16位BCD数有8个字节长,因此不再像前面的双倍精度数用顺序相加的办法。这里,采用循环结构,每循环一遍,对一个字节的BCD相加,相加之后,立即进行DAA调整,共循环8次,且采用ADC带进位加。当进行最低字节相加时,可预先设置CF为0(用CLC清进位)。解:程序段如下所示:MOVBX,OFFSETFIRST;指向被加数MOVSI,OFFSETSECOND;指向加数MOVDI,OFFSETTHIRD;指向和MOVCX,8;设计数初值CLC;清CF为0AGN:MOVAL,[BX];取被加数一个字节到AL中ADCAL,[SI];将AL中的内容与相应的加数的一个字节相加,结果放在AL中DAA;组合BCD码调整MOV[DI],AL;将AL中的内容放入DI所指的和的一个字节中INCBX;指向被加数的下一个字节INCSI;指向加数的下一个字节INCDI;指向和的下一个字节DECCX;完成一个字节的操作,CX中的内容减1JNZAGN;如果CX中的内容不为0,表示还有字节没有相加,进行下一个字节的加法运算INT27H;完成 在计算机内部,数的存放是将低字节放在低地址单元,而将高字节放在高地址单元。所以这里我们对BX,SI,DI的操作是加1。CLC指令的作用是将CF中的内容清为0,这样保证在执行第一个字节的加法运算时,CF=0H,这样,使用ADC指令也不会出错。 大家要注意:DAA指令应在每一个字节的加法完成后就指令一次。37.非组合十进制数加法调整指令AAA的含义理解。 答:AAA指令用于对非组合BCD码相加结果进行调整,调整操作仍在AL中进行,调整后的结果在AX中。AAA指令的操作如下:  若(AL)&0FH>9,或AF=1则(AL)<-(AL)+6(AF)<-1(CF)<-(AF)(AH)<-(AH)+1(AL)<-(AL)&OFH  指令执行后,除影响AF和CF标志外,其余标志均无定义。 可以看出:数字0~9的ASCll码是一种非组合的BCD码,因为其高4位为0011,而低4位才是以8421码表示的十进制数,这符合非组合BCD码高4位无意义(定为0)的规定,这也是AAA指令又称为ASCll码加法调整指令的原因。  现以两个非组合的十进制数06+07,结果应为非组合的十进制数0103,就其操作过程来说明AAA指令的作用。         00000110=06                       ;unpackedBCD      +00000111=07………………………………………………        00001101=0DH                     ;不是unpackedBCD      +    .0110                          ;(AL)<-(AL)+6……………………………………………     AL00010011                         ;packedBCD,再调整               AF=1                             ;AF<-1  AH=00000000+            1                            ;AH<-AH+1………………………………………………………………………     00000001              &00001111                   ;AL&0FH………………………………………………………………………AX  0000000100000011=0103            ;结果送AX 这里的具体操作是和上一个指令的操作一样的,不同的是对于组合的BCD码,高4位是有意义的,而对于非组合的BCD码,高4位是没有意义的,所以要对高4位清零。即AL&0FH。38.比较指令的含义。答: CMPdst,srcCMP指令和SUB指令类似,也是执行两操作数相减,但和SUB指令不同的是,不送回相减结果,只是使结果影响标志位OF,SF,ZF,PF和CF。换句括说,由受影响的标志位状态便可判断两操作数比较的结果。如何利用上述标志判断两操作数是否相等的关系呢?现设比较的两操作数为A和B:(1)当两数相等(不管是无符号数或带符号数),则ZF=l,否则,ZF=0;(2)若两数不相等,则应区分两数是无符号数还是带符号数:①A和B均为无符号数:两个无符号数相减,CF就是借位标志。若CF=0,表示A-B无借位,则A>B;否则,当CF=l,有借位,则A<B;②A和B均为带符号数,两个带符号数比较,将可能出现4种情况:第一种情况:A>0,B>0(两正数比较):两正数相减,结果不会溢出,若结果的符号标志SF=0,则A>B;反之,结果的SF=l,则A<B;SF表示的是运算结果的符号位是正还是负,结果为负时,SF=1。第二种情况:A<0,B<0(两负数比较):两负数相减,结果也不会溢出,这种情况下,仍然是SF=0,则A>B;反之,结果的SF=l,则A<B;第三种情况:A>0,B<0(两异号数比较):显然,结果应该是A>B,而且这时应该有SF=0。例如:A=+50,B=-63,结果:A?/FONT>B=113=01110001<+127,不发生溢出,OF=0。但如果A=+127,B=-63,比较结果是:A-B=+127-(-63)==+190>+127,溢出,这时,机器中的结果为: [+127]补=01111111B+[+63]补=00111111B          10111110BSF=1,OF=1因此,当结果发生溢出时,OF=1,应当SF=1才反映A>B。第四种情况:A<0,B>0(两异号数比较):若A=-63,B=+50,显然A<B,比较结果:A-B=-113=10001111B,其SF=1,OF=0。但若果A=-63,B=+127,比较结果是:A-B=-63-(+127)=-190<-128,溢出。这时,在机器中的结果为: [-63]补=11000001B+[-127]补=10000001B        10100010SF=0,OF=1因此,当结果发生溢出时,OF=1,应当SF=0,才反映ADB1O0DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKSTARTPROCFARPUSHDSMOVAX,0PUSHAXMOVAX,DATAMOVDS,AXDISP:MOVDX,OFFSETMESG;显示提问信息MOVAH,09INT21HRET;返回DOSSTART ENDPCODE ENDSEND START47.测试某程序段(过程)PROCET的执行时间,可借用BIOS的INT1AH的1号功能调用。先将时间计数器CX:DX设置为0,然后执行程序段。计数器自动计时,最后执行0号功能调用,读时间计数器值,此值放在CX:DX中,乘以0.055或除以18.2,即可测得PROCET过程的执行时间。这种测试方法所产生的误差约为54.9ms。该程序段如下:;............................................................STIMOVCX,0;设时间计数器初值为0MOVDX,0MOVAH,1INT1AHCALLPROCET;执行过程MOVAH,0;读时间计数器的值INT1AH;............................................................48用BIOS的中断调用作定时控制。要求每隔1.1s从键盘读一个字符并将该字符的ASCll码送入内存缓冲区,共读入10字符(最后一个字符为$,以便显示)解:源程序如下:DATASEGMENTCHARDB10DUP(?)DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATAMAINPROCPARPUSHDSXORAX,AX PUSHAXMOVAX,DATAMOVDS,AXSTART:LEABX,CHAR;指向存储区MOVCX,10;设计数STI;开中断LOPI:MOVAH,1PUSHCXMOVCX,0;设时间计数器为0MOVDX,0INT1AHLOPZ:MOVAX,0;读时间计数值INT1AHCMPDL,20JNZLOPZMOVAH,0;从键盘接收字符(以$结束)INT16HMOV[BX],AL;放入存储区INCBX;修改指针POPCXL00PLOPI;循环MOVDX,OFFSETCHAR;显示输入字符MOVAH,9INT21HRET;返回DOSMAINENDPCODEENDSENDMAIN49.设计一个程序:其功能是对被测试字中1的个数进行计数。本例作为子程序设计的一个例子,是程序与子程序不在一个代码段,和调用程序与子程序在一个代码段这两种情况都具备的应用实例,也是一个子程序嵌套结构的实例。解: ;源模块1PUBICTWORD,MASKS            ;可供外部使用的公共变量及数据EXTRNWCNTIS:FAR,OPSYS:FAR ;用到的外部子程序及外部过程STACKSEGMENTSTACK           ;堆栈段DW32DUP(?)                  ;堆栈区STKELABELWORD STACKENDSMAINDSEGMENT                 ;数据段MASKSDB80H,40H,20H,10H,08H,04H,02H,01H;测试用的屏蔽字TWORDDW27A9H            ;被测试数MAINDENDSMAINCSEGMENTPUBIC       ;主程序码段     MCS:MAINC,DS:MAIND,SS:STACK,ES:MAIND。MAIN:MOVAX,STACK      ;堆栈段寄存器初始化MOVSS,AXMOVSP,OFFSETSTKE       ;堆栈格外初始化MOVAX,MAIND             ;数据段初始化 MOVDS,AXMOVES,AX                ;附加段初始他CALLFARPTRWCNTIS       ;调用计算1个数的外部子程序CALLFARPTROPSYS        ;调用返回报作系统的外部过程MAINCENDSENDMAIN ;原模块2;子程序目的:WCNT是计等一个字中1的个数;出口:AX中放该字的1的个数;所门用于程序:调用2次计等一个字节中1个数的手程序WCNTIS.调用前将阿AX中数分为高低两字节PUBICWCNTIS               ;可供外部使用的干程序EXTRNTWORD:WORD,MASKS:BYTE;用到的外都变量及数据MSEGMENTPARASTACK‘STACK’DB20DUP(?)CNTSEGSEGMENTPUBLIN      ;子程序码段ASSUMECS:CNTSEG,SS:STACK;这里CS被赋予新值WCNTISPROCFAR            ;子程序WCNTIS开始MOVAX,TWORD              ;取入被测试数CALLNEARPTRBCNTIS       ;计算AL中1的个数,结果在CX中PUSHCX                    ;1的个数人栈M0VAL,AHCALLNEARPTRBCNTS        ;计算AH中1的个数POPAX                     ;取出低字节1个数ADDAX,CX                 ;加上高字节1个数RET                        ;返回WCNISENDP                 ;子程序WCNIS结束BCNTISPROCNEAR           ;子程序BCNTIS开始;子程序目的:计算字节中1的个数;人口:字节数在AL中;出口:1的个数在CX中MOVCX,0                   ;初始化MOVSI,0                   ;第一个选位字节的变址BL00P:TESTAL,MASKS[SI]   ;测试1位JZBNEXT                    ;为零,转移INCCL                      ;为1,计数加1BNEXT:INCSI               ;指向下一位CMPSI,8                   ;测试完?JNEBL00P                   ;否,继续RET                         ;是,返回BCNISENDPCNGENDSEND;源模块3PUBICOPSYS                 ;可供外部使用的公共过程CODESEGMENTPUBICASSUMECS:CODEOPSYSPROCFARMOVAH,4CH                 ;返回DOS INT21HRETOPSYENDCODEENDSEND被测试字TWORD被取入AX中,主程序MAIN调用于程序WCNTIS以计数AX中1的个数WCNTIS又调用于程序BCNTIS两次,BCNIS为计数字节中1个数的子程序,最后结果在CX中。50.设乘数以MZ和被乘数MI分别放在数据段中,乘积为32位数,存入PI和PZ的字单元中。PZ为高位积,PI为低位积。源程序如下所示。DATASEGMENMIDW00FFH;被乘数MZDW00FFH;乘数PIDW?PZDD?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTRPROCFARMULT:PUSHDSMOVAX,0PUSHAXMOVAX,DATAMOVDS,AX;初始化DSMOVAX,MIMULMZ;相乘MOVPI,AX;存结果MOVPZ,DXRETSTRENDPCODEENDSENDMULT;汇编结束51.编一程序实现对数据段中一个多位的非组合的BCD串A与一个一位的非组合的BCD数B相乘,乘积放入C为首址的连续单元中。解:源程序如下所示。DATASEGMENTADB3,7,5,4,9COUNTEQU$一ABDB6CDBCOUNT+1DUP(?)DATAENDSSTACKSEGMENPARASTACK"STACK?"STAPNDB100DUP(?)STACKENDSCOSEGSEGMENTASSUMECS:COSE,DS:DATA,ES:DATASTRPROCFARMAIN:PUSHDS;保存返回地址MOVAX,0PUSHAXMOVAX,DATA;初始化ES,DSMOVEX,AXMOVES,AXMOVDS,AXCLDMOVSI,OFFSETA;指向被乘数MOVDI,OFFSETC;指向积MOVCX,COUNT;设计数初值MOVBYTEPTR[DI],0CYCLE:LODS;取一位被乘数ANDAL,OFHMULB AAMADDAL,[DI]AAASTOSB;存一位积MOV[DI],AHL00PCYCLE;循环RETSTRENDPCOSEGENDSENDMAIN;汇编结束52.:已知两个两位的BCD数FIRST和SECOND存放在数据段,所得乘积放在THIRD开始的两个字节中。解:用累加算法完成相乘的源程序如下所示。要注意:BCD数存入时应与十进数相区别。例如25(BCD)不应写为25,而应写为25H。NAMEMULTIPLY_BCDDATASEGMENTFIRSTDB25HSECONDDB25HTHIRDDB2DUP(?)DATAENDSSTACKSEGMENTPARASTACK“STACK”STAPNDB100DUP(?)STACKENDSCOSGSEGMENTASSUMECS:COSEG,DS:DATA,ES:DATASTRPROCFARSTART:PUSHDS;保存返回地址MOVAX,0PUSHAXMOVAX,DATA;初始化DS,ESMOVDS,AXMOVES,AXMOVBL,FIRST;取乘数MOVCL,SECOND;取被乘数MOVDX,0;DX存积MOVAX,BLAGAIN:ORAL,ALJZDONE;若乘数为0,则转DONEMOVAL,DLADDAL,CLDAA;结果在ALMOVDL,ALADDAL,DHADCAL,0;处理进位(加进位)DAAMOVDL,ALADDAL,DHADCAL,0;处理进位(加进位)DAA53:设有两个32位数,被乘数存放在字单元MCDI-HI和MCDI-LO中,乘数存放在字单元MCDZ-HI和MCDZ-LO中,试求它们的积。设积存放入从RESUL开始的8个字节单元中(低位字节在前),积的符号存放在RLT-S单元中。解:其源程序如下所示。STACKSEOMENTPARASTACK‘STACK‘DW100DUP(?)STACKENDSDATASEGMENRLT-SDB?;存结果符号位MCD1_HIDW?;被乘数MCD1_LODW?MCD2_HIDW?MCD2_LODW?RESULTDB8DUP(0);结果区(低位字节在前)DATAENDSCODESEGMENTASSLUMECS:CODE,ES:DATA,ES:DATAMUL32B_SPROCFARPUSHDS;保存返回地址MOVAX,0PUSHAXMOVAX,DATA;初始化DS,ESMOVDS,AXMOVES,AXMOVDX,MCDI.HIMOVAX,MCDI.LOMOVCX,MCDZ_HIMOVBX,MCDZ.LOMOVRI,T一SO;结果符号位置初值0CMPDX,0;被乘数是负数吗?JNSSIGN;不是负数,转走NOTAXNOTDXADDAX,1;是负数,求补ADCDX,0NOTRLT_S;结果符号位置1SIGN:CMPCX,0;乘数为负数吗?JNSCALMUL;非负,转走XOREXNOTBX;负乘数求补ADDBX,1ADCCX,0 NOTRLT_S;结果符号取反OLMUL:CALLMUL32B;用无符号数乘法过程CMPRLT;查者结果符号数JZDONE;为正,即结束NOTWORDPTR[DI];为负,求补NOTWORDPTR[DI+Z]NOTWORDPTR[DI+4]NOTWORDPTR[DI+6]ADDWORDPTR[DI],1ADCWORDPTR[DI+2],0ADCWORDPTR[DI+4],0ADCWORDPTR[DI+6],0DONE:RETMUL32B_SENDMUL32BPROCNEARMOVDI,OFFSETRESULTMOVMCDI桯I,DXMOVMCDI_LD,AXMULBX;产生部分积1ADD[DI],AXADD[DI+Z],DXMOVAX,MCDI_HIMULBX;产生部分积2ADD[DI],AXADC[DI+4],DXMOVAX,MCDI_LOMULCX;产生部分积3ADD[DI十2],AXADC[DI+4],DXADCWORDPTR[DI+6],0MOVAX,MCDI_HIMULCX;产生部分积4ADD[DI+4],AXADC[DI+6],DXRETMUL32BENDPCODEENDSENDMUL32B_S;汇编结束54:编写一个通用程序,完成32位数/16位数。解:源程序如下所示。DATASEGMENTOPRDI-HIDW?;被除数OPRDI-LODW?OPRDZDW?;除数RESULXIHIDW?;结果RESULThLODW?ERRDB‘DIVISOR?0’,"$’DATAENDSSTACKSEOMENPARASTACK"STACK"DB100DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,ES:DATASTAPROCPARPUSHDSMOVAX,0PUSHAXMOVAX,DATAMOVDS,AXMOVES,AXPUSHESMOVCX,0MOVES,CXPUSHES:[0]PUSHES:[2]LEACX,MODIPY_INTMOVES:[O],CXMOVCX,CSMOVES:[2],CXSTIMOVBX,OPRDZCMPBX,0JEDONEIMOVDX,OPRDI_HIMOVAX,OPRDI_LODIVBXMOVSESULT_LO,AXMOVRESULT_HI,0DONE:POPES:[2]POPES:[0]POPESRETMOVAH,9INT21HJMPDONEMODIPY_INT:POPCXLEACX,DONEPUSHCXMOVAX,OPRDI_HIM0VDX,0DIVBXMOVRESULT_HI,AXMOVAX,OPPDI_LODIVBXMOVRESULT_LO,AX STIIRETSTAENDPCODEENDSENDSTA55编一个程序在屏幕上定点显示右图1的小人图形。该小人图形由五种方块字符图形构成,并将头定在参考点10行40列上,指定头部方块的图形的参考点座标为(0,0),其余各方块座桥用相对于头的偏移星表示,这样,形成一个字符表CHRTAB存于数据段中。每个方块字符含三个数据:它的ASCll和相对于参考点的行,列偏移量,并将此三个数据分别取人AL,DH和DL中。解:源程序如下所示:PDATASEGMENTCHRTABDW5DB01,0,0,0DBH,l,0,13H,l,0DB2FH,-l,一1,5CH,0,2PDATENDSSTACKSEGMENTPARASTACK"STACK"DB100DUP(?)STACKENDSCODESEGMENTASSUMECS:CODE,DS:PDATAPICTUREPROCFARSTART:PUSHDSMOVAX,0PUSHAXMOVAX,PDATAMOVDS,AXSTIMOVAL,02;设置显示方式:80*25黑白MOVAH,0INT10HMOVDI,OFFSETCHRTABMOVCX,[DI]MOVDH,10;定参考点于I0行40列MOVDL,40ADDDI,2NEXT:ADDDH,[DI+1]ADDDL,[DI+2]MOVAH,2;显示字符图形INT10HMOVAL,[DI]PUSHCXMOVCX,1MOVAH,10INT10HPOPCXADDDI,3;指向下一字符LOOPNEXTRETPICTUREENDCODEENDENDSTART56.编写在屏幕上显示彩条的程序。设背景色为兰色,调色板为0#,在满屏上显示彩条,每个彩条由四种颜色组成(兰、绿、红、棕),每行显示一种颜色,每4行重复一次。解:TITLEORAPHIC.COMCODESEGMENTASSUMECS:CODE,DS:CODE,ES:CODE,SS:CODEMAINPROCNEARMOVAH,15INT10HPUSHAXMOVAH,0MOVAL,04INT10HMOVAH,0BHMOVBH,0M0VBL,1INT10HMOVAH,0BHMOVBH,01MOVBL,0INT10HMOVBX,0400HMOVCX,0MOVDX,0LINE:MOVAH,OCHMOVAL,BLINT10HINCCXCMPCX,320JNELINEMOVCX,0INCDXDECBHJNZLINEINCBLANDBL,03M0VBH,04CMPDX,200 JNELINEMOVAH,07INT21HPOPAXM0VAH,0INT10HINT20HMAINENDPCODEENDSENDMAIN'