• 635.00 KB
  • 2022-04-22 11:51:56 发布

《IBM—PC汇编语言程序设计》习题参考答案.doc

  • 59页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'5162dbd488c339375742f5ffddba7d7a.doc-58-《IBM—PC汇编语言程序设计》习题参考答案习题一1.1用降幂法和除法将下列十进制数转换为二进制数和十六进制数:(1)369(2)10000(3)4095(4)32767答:(1)369=101110001B=171H(2)10000=10011100010000B=2710H(3)4095=111111111111B=FFFH(4)32767=111111111111111B=7FFFH1.2将下列二进制数转换为十六进制数和十进制数:E5H000B0H1EH000B1H3CH000B3H2AH000B4H存储器2.2题的信息存放情况…000B2H(1)101101(2)10000000(3)1111111111111111(4)11111111答:(1)101101B=2DH=45(2)10000000B=80H=128(3)1111111111111111B=FFFFH=65535(4)11111111B=FFH=2551.3将下列十六进制数转换为二进制数和十进制数:(1)FA(2)5B(3)FFFE(4)1234答:(1)FAH=11111010B=250(2)5BH=1011011B=91(3)FFFEH=1111111111111110B=65534(4)1234H=1001000110100B=46601.4完成下列十六进制数的运算,并转换为十进制数进行校核:(1)3A+B7(2)1234+AF(3)ABCD-FE(4)7AB×6F答:(1)3A+B7H=F1H=241(2)1234+AFH=12E3H=4835(3)ABCD-FEH=AACFH=43727(4)7AB×6FH=35325H=2178931.5下列各数均为十进制数,请用8位二进制补码计算下列各题,并用十六进制数表示其运算结果。(1)(-85)+76(2)85+(-76)(3)85-76(4)85-(-76)(5)(-85)-76(6)-85-(-76)答:(1)(-85)+76=10101011B+01001100B=11110111B=0F7H;CF=0;OF=0(2)85+(-76)=01010101B+10110100B=00001001B=09H;CF=1;OF=0(3)85-76=01010101B-01001100B=01010101B+10110100B=00001001B=09H;CF=0;OF=0(4)85-(-76)=01010101B-10110100B=01010101B+01001100B=10100001B=0A1H;CF=0;OF=1(5)(-85)-76=10101011B-01001100B=10101011B+10110100B=01011111B=5FH;CF=0;OF=1(6)-85-(-76)=10101011B-10110100B=10101011B+01001100B=11110111B=0F7H;CF=0;OF=01.6下列各数为十六进制表示的8位二进制数,请说明当它们分别被看作是用补码表示的带符号数或无符号数时,它们所表示的十进制数是什么?(1)D8(2)FF答:(1)D8H表示的带符号数为-40,D8H表示的无符号数为216;(2)FFH表示的带符号数为-1,FFH表示的无符号数为255。1.7下列各数均为用十六进制表示的8位二进制数,请说明当它们分别被看作是用补码表示的数或字符的ASCII码时,它们所表示的十进制数及字符是什么?(1)4F(2)2B(3)73(4)59答:(1)4FH表示的十进制数为79,4FH表示的字符为O;(2)2BH表示的十进制数为43,2BH表示的字符为+;(3)73H表示的十进制数为115,73H表示的字符为s;(4)59H表示的十进制数为89,59H表示的字符为Y。1.8请写出下列字符串的ASCII码值。Forexample,Thisisanumber3692.答:46H6FH72H20H65H78H61H6DH70H6CH65H2CH0AH0DH54H68H69H73H20H69H73H20H61H20H6EH75H6DH62H65H72H20H33H36H39H32H2EH0AH0DH习题二2.1在80x86微机的输入/输出指令中,I/O端口号通常是由DX寄存器提供的,但有时也可以在指令中直接指定00~FFH的端口号。试问可直接由指令指定的I/O端口数。答:可直接由指令指定的I/O端口数为256个。2.2有两个16位字1EE5H和2A3CH分别存放在80x86微机的存储器的000B0H和000B3H单元中,请用图表示出它们在存储器里的存放情况。答:存储器里的存放情况如右上图所示。2.3在IBMPC机的存储器中存放信息如右下图所示。试读出30022H和30024H字节单元的内容,以及30021H和30022H字单元的内容。答:30022H字节单元的内容为ABH;30024H字节单元的内容为EFH。30021H字单元的内容为AB34H;30022H字单元的内容为CDABH。2.4在实模式下,段地址和偏移地址为3017:000A的存储单元的物理地址是什么?如果段地址和偏移地址是3015:002A和3010:007A呢?答:3017:000A、3015:002A和3010:007A的存储单元的物理地址都是3017AH。2.5如果在一个程序开始执行以前(CS)=0A7F0H,(如16进制数的最高位为字母,则应在其前加一个0)(IP)=2B40H,试问该程序的第一个字的物理地址是多少?答:该程序的第一个字的物理地址是0AAA40H。2.6在实模式下,存储器中每一段最多可有10000H个字节。如果用调试程序DEBUG的r命令在终端上显示出当前各寄存器的内容如下,请画出此时存储器分段的示意图,以及条件标志OF、SF、ZF、CF的值。C>debug34H30021HABH30022HCDH30023HEFH30024H存储器2.3题的信息存放情况12H30020H-rAX=0000BX=0000CX=0079DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=10E4ES=10F4SS=21F0CS=31FFIP=0100NVUPDIPLNZNAPONC答:此时存储器分段的示意图如右图所示。OF、SF、ZF、CF的值都为0。2.7下列操作可使用那些寄存器?(1)加法和减法数据寄存器等(2)循环计数CX(3)乘法和除法AX、DX,乘数和除数用其他寄存器或存储器(4)保存段地址段寄存器(5)表示运算结果为0ZF=1(6)将要执行的指令地址CS:IP(7)将要从堆栈取出数据的地址SS:SP答:答案见题目的右边。2.8那些寄存器可以用来指示存储器地址?答:BX、BP、SI、DI、堆栈操作时的SP、对应的段地址、386及其后继机型的Exx。2.9请将下列左边的项和右边的解释联系起来(把所选字母放在括号中):(1)CPU(M)A.保存当前栈顶地址的寄存器。(2)存储器(C)B.指示下一条要执行的指令的地址。(3)堆栈(D)C.存储程序、数据等信息的记忆装置,微机有RAM和ROM两种。(4)IP(B)D.以后进先出方式工作的存储空间。(5)SP(A)E.把汇编语言程序翻译成机器语言程序的系统程序。(6)状态标志(L)F.唯一代表存储空间中每个字节单元的地址。(7)控制标志(K)G.能被计算机直接识别的语言。(8)段寄存器(J)H.用指令的助记符、符号地址、标号等符号书写程序的语言。(9)物理地址(F)I.把若干个模块连接起来成为可执行文件的系统程序。(10)汇编语言(H)J.保存各逻辑段的起始地址的寄存器,8086/8088机有四个:CS、DS、SS、ES。(11)机器语言(G)K.控制操作的标志,如DF位。(12)汇编程序(E)L.记录指令操作结果的标志,共6位:OF、SF、ZF、AF、PF、CF。(13)连接程序(I)M.分析、控制并执行指令的部件,由算术逻辑部件ALU和寄存器等组成。(14)指令(O)N.由汇编程序在汇编过程中执行的指令。(15)伪指令(N)O.告诉CPU要执行的操作(一般还要指出操作数地址),在程序运行时执行。答:答案见题目的括号中。习题三3.1给定(BX)=637DH,(SI)=2A9BH,位移量D=7237H,试确定在以下各种寻址方式下的有效地址是什么?(1)立即寻址;(2)直接寻址;(3)使用BX的寄存器寻址;(4)使用BX的简接寻址;(5)使用BX的寄存器相对寻址;(6)基址变址寻址;(7)相对基址变址寻址答:(1)操作数在指令中,即立即数;10F4010E4020F4020E4021F0031F0031FF041FF0附加段数据段堆栈段代码段2.6题的存储器分段示意图(2)EA=D=7237H;(3)无EA,操作数为(BX)=637DH;(4)EA=(BX)=637DH;(5)EA=(BX)+D=0D5B4H;(6)EA=(BX)+(SI)=8E18H; 5162dbd488c339375742f5ffddba7d7a.doc-58-(7)EA=(BX)+(SI)+D=1004FH;超过了段的边界,最高进位位丢失,因此EA=004FH。3.2试根据以下要求写出相应的汇编语言指令(1)把BX寄存器和DX寄存器的内容相加,结果存入DX寄存器中。(2)用寄存器BX和SI的基址变址寻址方式把存储器中的一个字节与AL寄存器的内容相加,并把结果送到AL寄存器中。(3)用寄存器BX和位移量0B2H的寄存器相对寻址方式把存储器中的一个字和(CX)相加,并把结果送回存储器中。(4)用位移量为0524H的直接寻址方式把存储器中的一个字与数2A59H相加,并把结果送回存储单元中。(5)把数0B5H与(AL)相加,并把结果送回AL中。答:(1)ADDDX,BX;(2)ADDAL,[BX][SI];(3)ADD[BX+0B2H],CX;(4)ADDWORDPTR[0524H],2A59H//不允许这么用,不能用立即数0524H,而且不加wordPtry也可以。(5)ADDAL,0B5H3.3写出把首地址为BLOCK的字数组的第6个字送到DX寄存器的指令。要求使用以下几种寻址方式:(1)寄存器间接寻址;(2)寄存器相对寻址;(3)基址变址寻址答:(1)MOVBX,OFFSETBLOCKADDBX,(6–1)*2MOVDX,[BX](2)MOVBX,OFFSETBLOCK改为:MOVBX,(6-1)*2MOVDX,[BX+(6–1)*2]也可MOVDX,BLOCK[BX](3)MOVBX,OFFSETBLOCKMOVSI,(6–1)*2MOVDX,[BX][SI]3.4现有(DS)=2000H,(BX)=0100H,(SI)=0002H,(20100H)=12H,(20101H)=34H,(20102H)=56H,(20103H)=78H,(21200H)=2AH,(21201H)=4CH,(21202H)=B7H,(21203H)=65H,试说明下列各条指令执行完后AX寄存器的内容。(1)MOVAX,1200H;(2)MOVAX,BXFFH00H80H3.6题的作图表示10H1B00:2000H1B00:2001H1B00:2002H1B00:2003H8000:FF10H8000:FF11H?→(AL)?→(AH);(3)MOVAX,[1200H];(4)MOVAX,[BX];(5)MOVAX,1100[BX];(6)MOVAX,[BX][SI](7)MOVAX,1100[BX][SI]答:(1)(AX)=1200H;(2)(AX)=0100H;(3)(AX)=4C2AH;(4)(AX)=3412H;(5)(AX)=4C2AH;(6)(AX)=7856H;(7)(AX)=65B7H3.5给定(IP)=2BC0H,(CS)=0200H,位移量D=5119H,(BX)=1200H,(DS)=212AH,(224A0H)=0600H,(275B9H)=098AH,试为以下的转移指令找出转移的偏移地址。MOVBX,2000HLESBX,[BX]MOVAX,ES :[BX](1)段内直接寻址3.6题目解答:——>(2)使用BX及寄存器间接寻址方式的段内间接寻址(3)使用BX及寄存器相对寻址方式的段内间接寻址答:(1)JMPNEARPTR5119H;(IP)=5119H+((IP)+03H)=7CDCH,物理地址PA=09CDCH(IP)+03H是JMPNEARPTR5119H指令的下一条指令的首地址。(2)JMPWORDPTR[BX];(IP)=((DS)*10H+(BX))=0600H,PA=02600H(3)JMPD[BX];(IP)=((DS)*10H+(BX)+D)=098AH,PA=0298AH3.6设当前数据段寄存器的内容为1B00H,在数据段的偏移地址2000H单元内,含有一个内容为0FF10H和8000H的指针,它们是一个16位变量的偏移地址和段地址,试写出把该变量装入AX的指令序列,并画图表示出来。答:MOVBX,[2000H];图示如上所示。MOVAX,[2000H+2]MOVES,AXMOVAX,ES:[BX]3.7在0624H单元内有一条二字节JMPSHORTOBJ指令,如其中位移量为(1)27H,(2)6BH,(3)0C6H,试问转向地址OBJ的值是多少?答:(1)OBJ=0624H+02H+27H=064DH;(2)OBJ=0624H+02H+6BH=0691H;(3)OBJ=0624H+02H+0C6H=05ECH;C6H对应的负数为-3AH(向上转移,负位移量)3.8假定(DS)=2000H,(ES)=2100H,(SS)=1500H,(SI)=00A0H,(BX)=0100H,(BP)=0010H,数据段中变量名VAL的偏移地址为0050H,试指出下列源操作数字段的寻址方式是什么?其物理地址值是多少?(1)MOVAX,0ABH(2)MOVAX,BX0AH00H14H00H1EH00H28H00H32H00HTABLETABLE+33.11题的TABLE存储方式(3)MOVAX,[100H](4)MOVAX,VAL(5)MOVAX,[BX](6)MOVAX,ES:[BX](7)MOVAX,[BP](8)MOVAX,[SI](9)MOVAX,[BX+10](10)MOVAX,VAL[BX](11)MOVAX,[BX][SI](12)MOVAX,VAL[BX][SI]答:(1)立即方式;操作数在本条指令中(2)寄存器寻址方式;操作数为(BX)=0100H(3)直接寻址方式;PA=20100H(4)直接寻址方式;PA=20050H(5)BX寄存器间接寻址方式;PA=20100H(6)附加段BX寄存器间接寻址方式;PA=21100H(7)BP寄存器间接寻址方式;PA=15010H(8)SI寄存器间接寻址方式;PA=200A0H(9)BX寄存器相对寻址方式;PA=20110H(10)BX寄存器相对寻址方式;PA=20150H(11)BX和SI寄存器基址变址寻址方式;PA=201A0H(12)BX和SI寄存器相对基址变址寻址方式;PA=201F0H3.9在ARRAY数组中依次存储了七个字数据,紧接着是名为ZERO的字单元,表示如下:ARRAYDW23,36,2,100,32000,54,0ZERODW?(1)如果BX包含数组ARRAY的初始地址,请编写指令将数据0传送给ZERO单元。(2)如果BX包含数据0在数组中的位移量,请编写指令将数据0传送给ZERO单元。答:(1)MOVAX,[BX+(7-1)*2]MOV[BX+(7)*2],AX(2)MOVAX,ARRAY[BX]MOVARRAY[BX+2],AX3.10如TABLE为数据段中0032单元的符号名,其中存放的内容为1234H,问以下两条指令有什么区别?指令执行完后AX寄存器的内容是什么?MOVAX,TABLELEAAX,TABLE79H0FH57H80HFFAACHFFAB0H3.13题的堆栈区和SP的内容变化过程示意图FFAAEH←首次进栈(SP)←(SP)-2←再次进栈(SP)←(SP)-2出栈时(SP)←(SP)+2答:MOVAX,TABLE是将TABLE单元的内容送到AX,(AX)=1234HLEAAX,TABLE是将TABLE单元的有效地址送到AX,(AX)=0032H3.11执行下列指令后AX寄存器中的内容是什么?TABLEDW10,20,30,40,50;000AH,0014H,001EH,0028H,0032HENTRYDW3┇MOVBX,OFFSETTABLEADDBX,ENTRYMOVAX,[BX]答:(AX)=1E00H(TABLE的存储方式如右图所示)3.12下列ASCII码串(包括空格符)依次存储在起始地址为CSTRING的字节单元中:CSTRINGDB‘BASEDADDRESSING’请编写指令将字符串中的第1个和第7个字符传送给DX寄存器。答:MOVDH,CSTRINGMOVDL,CSTRING+7-13.13已知堆栈段寄存器SS的内容是0FFA0H,堆栈指针寄存器SP的内容是00B0H,先执行两条把8057H和0F 5162dbd488c339375742f5ffddba7d7a.doc-58-79H分别进栈的PUSH指令,再执行一条POP指令。试画出堆栈区和SP的内容变化过程示意图(标出存储单元的物理地址)。8000H1B00:20003.14题的存储区情况2B00HX1B00:20022B00:8000答:堆栈区和SP的内容变化过程示意图如下左图所示。3.14设(DS)=1B00H,(ES)=2B00H,有关存储单元的内容如上右图所示。请写出两条指令把字变量X装入AX寄存器。答:MOVBX,[2000H]MOVAX,ES:[BX]3.15求出以下各十六进制数与十六进制数62A0H之和,并根据结果设置标志位SF、ZF、CF和OF的值。(1)1234H(2)4321H(3)CFA0H(4)9D60H答:(1)和为74D4H;SF=0,ZF=0,CF=0,OF=0;(2)和为A5C1H;SF=1,ZF=0,CF=0,OF=1;(3)和为3240H;SF=0,ZF=0,CF=1,OF=0(4)和为0000H;SF=0,ZF=1,CF=1,OF=03.16求出以下各十六进制数与十六进制数4AE0H的差值,并根据结果设置标志位SF、ZF、CF和OF的值。(1)1234H(2)5D90H(3)9090H(4)EA04H答:(1)差为C754H;SF=1,ZF=0,CF=1,OF=0(2)差为12B0H;SF=0,ZF=0,CF=0,OF=0(3)差为45B0H;SF=0,ZF=0,CF=0,OF=1(4)差为9F24H;SF=1,ZF=0,CF=0,OF=03.17写出执行以下计算的指令序列,其中X、Y、Z、R、W均为存放16位带符号数单元的地址。(1)Z←W+(Z-X)(2)Z←W-(X+6)-(R+9)(3)Z←(W*X)/(Y+6),R←余数(4)Z←((W-X)/5*Y)*2答:(1)MOVAX,Z;以下程序都未考虑带符号数的溢出SUBAX,XADDAX,WMOVZ,AX(2)MOVBX,XADDBX,6MOVCX,RADDCR,9MOVAX,WSUBAX,BXSUBAX,CXMOVZ,AX(3)ADDY,6MOVAX,WIMULXIDIVYMOVZ,AXMOVR,DX(4)MOVAX,WSUBAX,XCWDMOVBX,5IDIVBXIMULYSHLAX,1;((DX),(AX))*2RCLDX,13.18已知程序段如下:MOVAX,1234H;(AX)=1234H,标志位不变MOVCL,4;(AX)和标志位都不变ROLAX,CL;(AX)=2341H,CF=1,SF和ZF不变DECAX;(AX)=2340H,CF=1不变,SF=0,ZF=0MOVCX,4;(AX)和标志位都不变MULCX;(AX)=8D00H,CF=OF=0,其它标志无定义INT20H试问:(1)每条指令执行完后,AX寄存器的内容是什么?(2)每条指令执行完后,进位、符号和零标志的值是什么?(3)程序结束时,AX和DX的内容是什么?答:(1)见注释;(2)见注释;(3)(AX)=8D00H,(DX)=03.19下列程序段中的每条指令执行完后,AX寄存器及CF、SF、ZF和OF的内容是什么?MOVAX,0;(AX)=0,标志位不变DECAX;(AX)=0FFFFH,CF不变,SF=1,ZF=0,OF=0ADDAX,7FFFH;(AX)=7FFEH,CF=1,SF=0,ZF=0,OF=0ADDAX,2;(AX)=8000H,CF=0,SF=1,ZF=0,OF=1NOTAX;(AX)=7FFFH,标志位不变SUBAX,0FFFFH;(AX)=8000H,CF=1,SF=1,ZF=0,OF=1ADDAX,8000H;(AX)=0,CF=1,SF=0,ZF=1,OF=1SUBAX,1;(AX)=0FFFFH,CF=1,SF=1,ZF=0,OF=0ANDAX,58D1H;(AX)=58D1H,CF=0,SF=0,ZF=0,OF=0SALAX,1;(AX)=0B1A2H,CF=0,SF=1,ZF=0,OF=1SARAX,1;(AX)=0D8D1H,CF=0,SF=1,ZF=0,OF=0NEGAX;(AX)=272FH,CF=1,SF=0,ZF=0,OF=0RORAX,1;(AX)=9397H,CF=1,SF和ZF不变,OF=1答:见注释。3.20变量DATAX和变量DATAY的定义如下:DATAXDW0148HDW2316HDATAYDW0237HDW4052H请按下列要求写出指令序列:(1)DATAX和DATAY两个字数据相加,和存放在DATAY中。(2)DATAX和DATAY两个双字数据相加,和存放在从DATAY开始的双字单元中。(3)解释下列指令的作用:STCMOVBX,DATAXADCBX,DATAY(4)DATAX和DATAY两个字数据相乘(用MUL)。(5)DATAX和DATAY两个双字数据相乘(用MUL)。(6)DATAX除以23(用DIV)。(7)DATAX双字除以字DATAY(用DIV)。答:(1)MOVAX,DATAXADDDATAY,AXMOVAX,DATAX+2ADDDATAY+2,AX 5162dbd488c339375742f5ffddba7d7a.doc-58-(2)MOVAX,DATAXADDDATAY,AXMOVAX,DATAX+2ADCDATAY+2,AXMOVDATAY+4,0;用于存放进位位ADCDATAY+4,0(3)DATAX和DATAY两个字数据之和加1,结果存入BX寄存器。(4)RESULT1DW0DW0RESULT2DW0DW0┇MOVAX,DATAXMULDATAYMOVRESULT1,AXMOVRESULT1+2,DXMOVAX,DATAX+2MULDATAY+2MOVRESULT2,AXMOVRESULT2+2,DX(5)AADW0BBDW0CCDW0DDDW0┇MOVAX,DATAXMULDATAYMOVAA,AXMOVBB,DXMOVAX,DATAXMULDATAY+2ADDBB,AXADCCC,DXMOVAX,DATAX+2MULDATAYADDBB,AXADCCC,DXADCDD,0MOVAX,DATAX+2MULDATAY+2ADDCC,AXADCDD,DX(6)MOVAX,DATAXMOVBL,23DIVBL(7)MOVDX,DATAX+2MOVAX,DATAXDIVDATAY3.21写出对存放在DX和AX中的双字长数求补的指令序列。答:NEGDX也可为:NOTDXNEGAXNOTAXSBBDX,0ADDAX,1ADCDX,03.22试编写一程序求出双字长数的绝对值。双字长数在A和A+2单元中,结果存放在B和B+2单元中。答:程序段如下:MOVAX,AMOVDX,A+2CMPDX,0JNSZHENSHU;不是负数则转走NEGDXNEGAXSBBDX,0ZHENSHU:MOVB,AXMOVB+2,DXINT20H3.23假设(BX)=0E3H,变量VALUE中存放的内容为79H,确定下列各条指令单独执行后的结果。(1)XORBX,VALUE;(BX)=9AH,CF、OF都为0,AF无定义,SF=1,ZF=0,PF=1(2)ANDBX,VALUE;(BX)=61H,CF、OF都为0,AF无定义,SF=0,ZF=0,PF=0(3)ORBX,VALUE;(BX)=0FBH,CF、OF都为0,AF无定义,SF=1,ZF=0,PF=0(4)XORBX,0FFH;(BX)=1CH,CF、OF都为0,AF无定义,SF=0,ZF=0,PF=0(5)ANDBX,0;(BX)=00H,CF、OF都为0,AF无定义,SF=0,ZF=1,PF=1(6)TESTBX,01H;(BX)=0E3H,CF、OF都为0,AF无定义,SF=1,ZF=0,PF=0答:见注释。3.24试写出执行下列指令序列后BX寄存器的内容。执行前(BX)=6D16H。MOVCL,7SHRBX,CL答:(BX)=00DAH。3.25试用移位指令把十进制数+53和-49分别乘以2。它们应该用什么指令?得到的结果是什么?如果要除以2呢?答:MOVAL,53SALAL,1;(AL)=(+53*2)=6AHMOVAL,-49SALAL,1;(AL)=(-49*2)=9EHMOVAL,53SARAL,1;(AL)=(53/2)=1AHMOVAL,-49SARAL,1;(AL)=(-49/2)=0E7H3.26试分析下面的程序段完成什么功能?MOVCL,04SHLDX,CL 5162dbd488c339375742f5ffddba7d7a.doc-58-MOVBL,AHSHLAX,CLSHRBL,CLORDL,BL答:本程序段将((DX),(AX))的双字同时左移4位,即将此双字乘以10H(16)。3.27假定(DX)=0B9H,(CL)=3,(CF)=1,确定下列各条指令单独执行后DX中的值。(1)SHRDX,1;(DX)=05CH(2)SARDX,CL;(DX)=17H(3)SHLDX,CL;(DX)=5C8H(4)SHLDL,1;(DX)=72H(5)RORDX,CL;(DX)=2017H(6)ROLDL,CL;(DX)=0CDH(7)SALDH,1;(DX)=0B9H(8)RCLDX,CL;(DX)=2CCH(4)RCRDL,1;(DX)=0DCH答:见注释。3.28下列程序段执行完后,BX寄存器的内容是什么?MOVCL,3MOVBX,0B7HROLBX,1RORBX,CL答:(BX)=0C02DH。3.29假设数据段定义如下:CONAMEDB‘SPACEEXPLORERSINC.’PRLINEDB20DUP(‘’)用串指令编写程序段分别完成以下功能:(1)从左到右把CONAME中的字符串传送到PRLINE。(2)从右到左把CONAME中的字符串传送到PRLINE。(3)把CONAME中的第3和第4个字节装入AX。(4)把AX寄存器的内容存入从PRLINE+5开始的字节中。(5)检查CONAME字符串中有无空格字符,如有则把第一个空格字符的地址传送给BX寄存器。答:(1)MOVCX,20CLDMOVSI,SEGCONAMEMOVDS,SIMOVES,SILEASI,CONAMELEADI,PRLINEREPMOVSB(2)MOVCX,20STDMOVSI,SEGCONAMEMOVDS,SIMOVES,SILEASI,CONAMEADDSI,20-1LEADI,PRLINEADDDI,20-1REPMOVSB(3)MOVAX,WORDPTRCONAME+3-1(4)MOVWORDPTRPRLINE+5,AX(5)MOVAL,‘’;空格的ASCII码送AL寄存器CLDMOVDI,SEGCONAMEMOVES,DILEADI,CONAMEREPNESCASBJNENEXTDECDIMOVBX,DINEXT:┇3.30编写程序段,把字符串STRING中的‘&’字符用空格符代替。STRINGDB‘ThedateisFEB&03’答:程序段如下:MOVCX,18MOVAL,‘&’CLDMOVDI,SEGSTRINGMOVES,DILEADI,STRINGREPNESCASBJNENEXTDECDIMOVES:BYTEPTR[DI],‘’;送空格符NEXT:┇3.31假设数据段中数据定义如下:STUDENT_NAMEDB30DUP(?)STUDENT_ADDRDB9DUP(?)PRINT_LINEDB132DUP(?)分别编写下列程序段:(1)用空格符清除PRINT_LINE域。(2)在STUDENT_ADDR中查找第一个‘-’。(3)在STUDENT_ADDR中查找最后一个‘-’。(4)如果STUDENT_NAME域中全是空格符时,填入‘*’。(5)把STUDENT_NAME移到PRINT_LINE的前30个字节中,把STUDENT_ADDR移到PRINT_LINE的后9个字节中。答:公共的程序段如下:MOVDI,DSMOVES,DI(1)MOVCX,132 5162dbd488c339375742f5ffddba7d7a.doc-58-MOVAL.,‘’;空格的ASCII码送AL寄存器CLDLEADI,PRINT_LINEREPSTOSB(2)MOVCX,9MOVAL.,‘-’CLDLEADI,STUDENT_ADDRREPNESCASBJNENO_DASHDECDINO_DASH:┇(3)MOVCX,9MOVAL.,‘-’STDLEADI,STUDENT_ADDRADDDI,9-1REPNESCASBJNENO_DASHINCDINO_DASH:┇(4)MOVCX,30MOVAL,‘’;空格的ASCII码送AL寄存器CLDLEADI,STUDENT_NAMEREPESCASBJNENEXTMOVCX,30MOVAL,‘*’;“*”的ASCII码送AL寄存器LEADI,STUDENT_NAMEREPSTOSBNEXT:┇(5)MOVCX,30CLDLEASI,STUDENT_NAMELEADI,PRINT_LINEREPMOVSBMOVCX,9STDLEASI,STUDENT_ADDR+9-1LEADI,PRINT_LINE+132-1REPMOVSB3.32编写一程序段:比较两个5字节的字符串OLDS和NEWS,如果OLDS字符串不同于NEWS字符串则执行NEW_LESS;否则顺序执行程序。答:程序段如下:MOVCX,5CLDMOVDI,SEGOLDSMOVDS,DIMOVES,DILEASI,OLDSLEADI,NEWSREPECMPSBJNENEW_LESS┇NEW_LESS:┇3.33假定AX和BX中的内容为带符号数,CX和DX中的内容为无符号数,请用比较指令和条件转移指令实现以下判断:(1)若DX的内容超过CX的内容,则转去执行EXCEED。(2)若BX的内容大于AX的内容,则转去执行EXCEED。(3)若CX的内容等于0,则转去执行ZERO。(4)BX与AX的内容相比较是否产生溢出?若溢出则转OVERFLOW。(5)若BX的内容小于等于AX的内容,则转EQ_SMA。(6)若DX的内容低于等于CX的内容,则转EQ_SMA。答:(1)CMPDX,CXJAEXCEED(2)CMPBX,AXJGEXCEED(3)JCXZZERO(4)CMPBX,AXJOOVERFLOW(5)CMPBX,AXJLEEQ_SMA(6)CMPDX,CXJBEEQ_SMA3.34试分析下列程序段:ADDAX,BXJNOL1JNCL2SUBAX,BXJNCL3JNOL4JMPSHORTL5如果AX和BX的内容给定如下:AXBX(1)147BH80DCH(2)B568H42C8H(3)42C8H608DH(4)D023H9FD0H(5)94B7HB568H问该程序分别在上面5种情况下执行后,程序转向哪里? 5162dbd488c339375742f5ffddba7d7a.doc-58-答:(1)转向L1(2)转向L1(3)转向L2(4)转向L5;因为加法指令后AX中已经是6FF3H(5)转向L5;因为加法指令后AX中已经是4A14H3.35指令CMPAX,BX后面跟着一条格式为J…L1的条件转移指令,其中…可以是B、NB、BE、NBE、L、NL、LE、NLE中的任意一个。如果AX和BX的内容给定如下:AXBX(1)1F52H1F52H(2)88C9H88C9H(3)FF82H007EH(4)58BAH020EH(5)FFC5HFF8BH(6)09A0H1E97H(7)8AEAHFC29H(8)D367H32A6H问以上8条转移指令中的哪几条将引起转移到L1?答:(1)JNB、JBE、JNL、JLE(2)JNB、JBE、JNL、JLE(3)JNB、JNBE、JL、JLE(4)JNB、JNBE、JNL、JNLE(5)JNB、JNBE、JL、JLE(6)JB、JBE、JL、JLE(7)JB、JBE、JNL、JNLE(8)JNB、JNBE、JL、JLE3.36假设X和X+2单元的内容为双精度数p,Y和Y+2单元的内容为双精度数q,(X和Y为低位字)试说明下列程序段做什么工作?MOVDX,X+2MOVAX,XADDAX,XADCDX,X+2CMPDX,Y+2JLL2JGL1CMPAX,YJBEL2L1:MOVAX,1JMPSHORTEXITL2:MOVAX,2EXIT:INT20H答:此程序段判断p*2>q,则使(AX)=1后退出;p*2≤q,则使(AX)=2后退出。3.37要求测试在STATUS中的一个字节,如果第1、3、5位均为1则转移到ROUTINE_1;如果此三位中有两位为1则转移到ROUTINE_2;如果此三位中只有一位为1则转移到ROUTINE_3;如果此三位全为0则转移到ROUTINE_4。试画出流程图,并编制相应的程序段。全为0吗?二位为1吗?仅一位为1执行ROUTINE_3转去执行ROUTINE_4NNYY3.44题的程序流程图程序开始(AL)←(STATUS)只保留第1,3,5位转去执行ROUTINE_2全为1吗?NY转去执行ROUTINE_1执行EXIT程序结束答:程序段如下:MOVAL,STATUSANDAL,00010101B;只保留第1、3、5位JZROUTINE_4;3位全为0转ROUTINE_4JPEROUTINE_2;两位为1转ROUTINE_2CMPAL,00010101BJZROUTINE_1;3位全为1转ROUTINE_1ROUTINE_3:┇;仅一位为1执行ROUTINE_3JMPEXITROUTINE_1:┇JMPEXITROUTINE_2:┇JMPEXITROUTINE_4:┇EXIT:INT20H3.38在下列程序的括号中分别填入如下指令:(1)LOOPL20(2)LOOPEL20(3)LOOPNEL20试说明在三种情况下,当程序执行完后,AX、BX、CX、DX四个寄存器的内容分别是什么?TITLEEXLOOP.COMCODESGSEGMENTASSUMECS:CODESG,DS:CODSEG,SS:CODSEGORG100HBEGIN:MOVAX,01MOVBX,02MOVDX,03MOVCX,04L20:INCAXADDBX,AXSHRDX,1()RETCODESGENDSENDBEGIN答:(1)(AX)=5H,(BX)=10H,(CX)=0H,(DX)=0H(2)(AX)=2H,(BX)=4H,(CX)=3H,(DX)=1H(3)(AX)=3H,(BX)=7H,(CX)=2H,(DX)=0H3.39考虑以下的调用序列:(1)MAIN调用NEAR的SUBA过程(返回的偏移地址为0400);(2)SUBA调用NEAR的SUBB过程(返回的偏移地址为0A00);(3)SUBB调用FAR的SUBC过程(返回的段地址为B200,返回的偏移地址为0100);(4)从SUBC返回SUBB;(5)SUBB调用NEAR的SUBD过程(返回的偏移地址为0C00);(6)从SUBD返回SUBB;(7)从SUBB返回SUBA; 5162dbd488c339375742f5ffddba7d7a.doc-58-(8)从SUBA返回MAIN;0004原SP位置新SP位置(1)MAIN调用SUBA过程000A0004原SP位置新SP位置(2)SUBA调用SUBB过程000100B2000A00原SP位置新SP位置(3)SUBB调用SUBC过程000100B2000A00原SP位置新SP位置(4)从SUBC返回SUBB0001000C000A0004原SP位置新SP位置(5)SUBB调用SUBD过程0001000C000A0004原SP位置新SP位置(6)从SUBD返回SUBB0001000C000A0004原SP位置新SP位置(7)从SUBB返回SUBA0001000C000A0004原SP位置新SP位置(8)从SUBA返回MAIN0001000C00060010原SP位置新SP位置(9)从MAIN调用SUBC(9)从MAIN调用SUBC(返回的段地址为1000,返回的偏移地址为0600);请画出每次调用及返回时的堆栈状态。答:每次调用及返回时的堆栈状态图如下所示:3.40假设(EAX)=00001000H,(EBX)=00002000H,(DS)=0010H,试问下列指令访问内存的物理地址是什么?(1)MOVECX,[EAX+EBX](2)MOV[EAX+2*EBX],CL(3)MOVDH,[EBX+4*EAX+1000H]答:(1)PA=(DS)*10H+EA=00100H+00001000H+00002000H=00003100H(2)PA=(DS)*10H+EA=00100H+00001000H+2*00002000H=00005100H(3)PA=(DS)*10H+EA=00100H+00002000H+4*00001000H+1000H=00007100H3.41假设(EAX)=9823F456H,(ECX)=1F23491H,(BX)=348CH,(SI)=2000H,(DI)=4044H。在DS段中从偏移地址4044H单元开始的4个字节单元中,依次存放的内容为92H,6DH,0A2H和4CH,试问下列各条指令执行完后的目的地址及其中的内容是什么?(1)MOV[SI],EAX(2)MOV[BX],ECX(3)MOVEBX,[DI]答:(1)目的地址为DS:2000H,内容依次为:56H,0F4H,23H和98H;(2)目的地址为DS:348CH,内容依次为:91H,34H,0F2H和01H;(3)目的操作数为EBX寄存器,(EBX)=4CA26D92H3.42说明下列指令的操作(1)PUSHAX;将(AX)压入堆栈(2)POPESI;将堆栈中的双字弹出到ESI寄存器中(3)PUSH[BX];将((BX))对应存储单元中的字压入堆栈(4)PUSHAD;32位通用寄存器依次进栈(5)POPDS;将堆栈中的字弹出到DS寄存器中(6)PUSH4;将立即数4以字的方式压入堆栈答:见注释。3.43请给出下列各指令序列执行完后目的寄存器的内容。(1)MOVEAX,299FF94HADDEAX,34FFFFH;(EAX)=2CEFF93H(2)MOVEBX,40000000SUBEBX,1500000;(EBX)=3EB00000H(3)MOVEAX,39393834HANDEAX,0F0F0F0FH;(EAX)=09090804H(4)MOVEDX,9FE35DHXOREDX,0F0F0F0H;(EDX)=6F13ADH答:见注释。3.44请给出下列各指令序列执行完后目的寄存器的内容。(1)MOVBX,-12MOVSXEBX,BX;(EBX)=0FFFFFFF4H(2)MOVCL,-8MOVSXEDX,CL;(EDX)=0FFFFFFF8H(3)MOVAH,7MOVZXECX,AH;(ECX)=00000007H(4)MOVAX,99HMOVZXEBX,AX;(EBX)=00000099H答:见注释。3.45请给出下列指令序列执行完后EAX和EBX的内容。MOVECX,307F455HBSFEAX,ECX;(EAX)=0DBSREBX,ECX;(EBX)=25D答:见注释。3.46请给出下列指令序列执行完后AX和DX的内容。MOVBX,98HBSFAX,BX;(AX)=3DBSRDX,BX;(DX)=7D答:见注释。3.47请编写一程序段,要求把ECX、EDX和ESI的内容相加,其和存入EDI寄存器中(不考虑溢出)。答:MOVEDI,0也可为:MOVEDI,ECXADDEDI,ECXADDEDI,EDXADDEDI,EDXADDEDI,ESIADDEDI,ESI3.48请说明IMULBX,DX,100H指令的操作。答:(BX)←(DX)*100H 5162dbd488c339375742f5ffddba7d7a.doc-58-3.49试编写一程序段,要求把BL中的数除以CL中的数,并把其商乘以2,最后的结果存入DX寄存器中。答:MOVAL,BLMOVAH,0;假定为无符号数,否则用CBW指令即可DIVCLMOVAH,0SHLAX,1MOVDX,AX3.50请说明JMPDI和JMP[DI]指令的区别。答:JMPDI是转移到以(DI)内容为偏移地址的单元去执行指令;JMP[DI]是转移到以(DI)间接寻址的内存单元内容为偏移地址的单元去执行指令。3.51试编写一程序段,要求在长度为100H字节的数组中,找出大于42H的无符号数的个数并存入字节单元UP中;找出小于42H的无符号数的个数并存入字节单元DOWN中。答:JMPBEGIN原(BP)低字节原(BP)高字节存储器002EH002FH0030H0031H0032H0033H0034H0035H0036H0037H0038H0039H003AH003BH003CH003DH003EH003FH0040H堆栈帧原(SP)新(BP)新(SP)3.52题的答案UPDB0DOWNDB0TABLEDB100HDUP(?);数组BEGIN:MOVCX,100HMOVBX,-1MOVSI,0MOVDI,0L1:INCBXCMPTABLE[BX],42HJAL2JBL3JMPL4L2:INCSIJMPL4L3:INCDIL4:LOOPL1MOVUP,SIMOVDOWN,DI3.52请用图表示ENTER16,0所生成的堆栈帧的情况。答:答案见右图。习题44.1指出下列指令的错误:(1)MOVAH,BX;寄存器类型不匹配(2)MOV[BX],[SI];不能都是存储器操作数(3)MOVAX,[SI][DI];[SI]和[DI]不能一起使用(4)MOVMYDAT[BX][SI],ES:AX;AX寄存器不能使用段超越(5)MOVBYTEPTR[BX],1000;1000超过了一个字节的范围(6)MOVBX,OFFSETMYDAT[SI];MYDAT[SI]已经是偏移地址,不能再使用OFFSET(7)MOVCS,AX;CS不能用作目的寄存器(8)MOVECX,AX;两个操作数的数据类型不同答:见注释。4.2下面哪些指令是非法的?(假设OP1,OP2是已经用DB定义的变量)(1)CMP15,BX;错,立即数不能作为目的操作数(2)CMPOP1,25(3)CMPOP1,OP2;错,不能都是存储器操作数(4)CMPAX,OP1;错,类型不匹配,应为CMPax,wordptrop1答:见注释。4.3假设下列指令中的所有标识符均为类型属性为字的变量,请指出下列哪些指令是非法的?它们的错误是什么?(1)MOVBP,AL;错,寄存器类型不匹配(2)MOVWORD_OP[BX+4*3][DI],SP(3)MOVWORD_OP1,WORD_OP2;错,不能都是存储器操作数(4)MOVAX,WORD_OP1[DX];错,DX不能用于存储器寻址(5)MOVSAVE_WORD,DS(6)MOVSP,SS:DATA_WORD[BX][SI](7)MOV[BX][SI],2;错,[BX][SI]未指出数据类型(8)MOVAX,WORD_OP1+WORD_OP2(9)MOVAX,WORD_OP1-WORD_OP2+100(10)MOVWORD_OP1,WORD_OP1-WORD_OP2答:见注释。4.4假设VAR1和VAR2为字变量,LAB为标号,试指出下列指令的错误之处:(1)ADDVAR1,VAR2;不能都是存储器操作数(2)SUBAL,VAR1;数据类型不匹配(3)JMPLAB[SI];LAB是标号而不是变量名,后面不能加[SI](4)JNZVAR1;VAR1是变量而不是标号(5)JMPNEARLAB;应使用NEARPTR答:见注释。4.5画图说明下列语句所分配的存储空间及初始化的数据值。(1)BYTE_VARDB‘BYTE’,12,-12H,3DUP(0,?,2DUP(1,2),?)(2)WORD_VARDW5DUP(0,1,2),?,-5,‘BY’,‘TE’,256H答:答案如下图所示。4.6试列出各种方法,使汇编程序把5150H存入一个存储器字中(如:DW5150H)。4.5题答案42H59H54H45H0DHEEH00H-01H02H01H02H-00H-01H02H01H02H-BYTE_VAR00H00H01H00H02H00H┇┇┇--FBHFFH00H59H42H45H54H56H02HWORD_VAR将上面内容再重复4次答:DW5150HDB50H,51HDB‘PQ’DW‘QP’ORG5150HDW$4.7请设置一个数据段DATASG,其中定义以下字符变量或数据变量。(1)FLD1B为字符串变量:‘personalcomputer’;(2)FLD2B为十进制数字节变量:32;(3)FLD3B为十六进制数字节变量:20;(4)FLD4B为二进制数字节变量:01011001;(5)FLD5B为数字的ASCII字符字节变量:32654;(6)FLD6B为10个零的字节变量;(7)FLD7B为零件名(ASCII码)及其数量(十进制数)的表格:PART120 5162dbd488c339375742f5ffddba7d7a.doc-58-PART250PART314(8)FLD1W为十六进制数字变量:FFF0;(9)FLD2W为二进制数的字变量:01011001;(10)FLD3W为(7)零件表的地址变量;(11)FLD4W为包括5个十进制数的字变量:5,6,7,8,9;(12)FLD5W为5个零的字变量;(13)FLD6W为本段中字数据变量和字节数据变量之间的地址差。答:DATASGSEGMENTFLD1BDB‘personalcomputer’FLD2BDB32FLD3BDB20HFLD4BDB01011001BFLD5BDB‘32654’FLD6BDB10DUP(0)FLD7BDB‘PART1’,20DB‘PART2’,50DB‘PART3’,14FLD1WDW0FFF0HFLD2WDW01011001BFLD3WDWFLD7BFLD4WDW5,6,7,8,9FLD5WDW5DUP(0)FLD6WDWFLD1W-FLD1BDATASGENDS4.8假设程序中的数据定义如下:PARTNODW?PNAMEDB16DUP(?)COUNTDD?PLENTHEQU$-PARTNO问PLENTH的值为多少?它表示什么意义?答:PLENTH=22=16H,它表示变量PARTNO、PNAME、COUNT总共占用的存储单元数(字节数)。4.9有符号定义语句如下:BUFFDB1,2,3,‘123’EBUFFDB0LEQUEBUFF-BUFF问L的值是多少?答:L=6。4.10假设程序中的数据定义如下:LNAMEDB30DUP(?)ADDRESSDB30DUP(?)CITYDB15DUP(?)CODE_LISTDB1,7,8,3,2(1)用一条MOV指令将LNAME的偏移地址放入AX。(2)用一条指令将CODE_LIST的头两个字节的内容放入SI。(3)用一条伪操作使CODE_LENGTH的值等于CODE_LIST域的实际长度。答:(1)MOVAX,OFFSETLNAME(2)MOVSI,WORDPTRCODE_LIST(3)CODE_LENGTHEQU$-CODE_LIST;此语句必须放在CODE_LIST语句之后4.11试写出一个完整的数据段DATA_SEG,它把整数5赋予一个字节,并把整数-1,0,2,5和4放在10字数组DATA_LIST的头5个单元中。然后,写出完整的代码段,其功能为:把DATA_LIST中头5个数中的最大值和最小值分别存入MAX和MIN单元中。答:DATA_SEGSEGMENTNUMDB5DATA_LISTDW-1,0,2,5,4,5DUP(?)MAXDW?MINDW?DATA_SEGENDS;----------------------------------------------------------------CODE_SEGSEGMENTMAINPROCFARASSUMECS:CODE_SEG,DS:DATA_SEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DATA_SEG;给DS赋值MOVDS,AX;MOVCX,4;程序段开始LEABX,DATA_LISTMOVAX,[BX]MOVMAX,AXMOVMIN,AXROUT1:ADDBX,2MOVAX,[BX]CMPAX,MAXJNGEROUT2MOVMAX,AXROUT2:CMPAX,MINJNLEROUT3MOVMIN,AXROUT3:LOOPROUT1;程序段结束RETMAINENDPCODE_SEGENDS;----------------------------------------------------------------ENDSTART4.12给出等值语句如下:ALPHAEQU100BETAEQU25 5162dbd488c339375742f5ffddba7d7a.doc-58-GAMMAEQU2下列表达式的值是多少?(1)ALPHA*100+BETA;=2729H(2)ALPHAMODGAMMA+BETA;=19H(3)(ALPHA+2)*BETA–2;=9F4H(4)(BETA/3)MOD5;=3H(5)(ALPHA+3)*(BETAMODGAMMA);=67H(6)ALPHAGEGAMMA;=0FFFFH(7)BETAAND7;=01H(8)GAMMAOR3;=03H答:见注释。4.13对于下面的数据定义,三条MOV指令分别汇编成什么?(可用立即数方式表示)TABLEADW10DUP(?)TABLEBDB10DUP(?)TABLECDB‘1234’┇MOVAX,LENGTHTABLEA;汇编成MOVAX,000AHMOVBL,LENGTHTABLEB;汇编成MOVBL,000AHMOVCL,LENGTHTABLEC;汇编成MOVCL,0001H答:见注释。4.14对于下面的数据定义,各条MOV指令单独执行后,有关寄存器的内容是什么?FLDBDB?TABLEADW20DUP(?)TABLEBDB‘ABCD’(1)MOVAX,TYPEFLDB;(AX)=0001H(2)MOVAX,TYPETABLEA;(AX)=0002H(3)MOVCX,LENGTHTABLEA;(CX)=0014H(4)MOVDX,SIZETABLEA;(DX)=0028H(5)MOVCX,LENGTHTABLEB;(CX)=0001H答:见注释。4.15指出下列伪操作表达方式的错误,并改正之。(1)DATA_SEGSEG;DATA_SEGSEGMENT(伪操作错)(2)SEGMENT‘CODE’;SEGNAMESEGMENT‘CODE’(缺少段名字)(3)MYDATASEGMENT/DATA;MYDATASEGMENT┇ENDS;MYDATAENDS(缺少段名字)(4)MAIN_PROCPROCFAR;删除ENDMAIN_PROC也可以┇ENDMAIN_PROC;MAIN_PROCENDP;上下两句交换位置MAIN_PROCENDP;ENDMAIN_PROC答:见注释。4.16按下面的要求写出程序的框架(1)数据段的位置从0E000H开始,数据段中定义一个100字节的数组,其类型属性既是字又是字节;(2)堆栈段从小段开始,段组名为STACK;(3)代码段中指定段寄存器,指定主程序从1000H开始,给有关段寄存器赋值;(4)程序结束。答:程序的框架如下:DATA_SEGSEGMENTAT0E000HARRAY_BLABELBYTEARRAY_WDW50DUP(?)DATA_SEGENDS;以上定义数据段;----------------------------------------------------------------STACK_SEGSEGMENTPARASTACK‘STACK’DW100HDUP(?)TOSLABELWORDSTACK_SEGENDS;以上定义堆栈段;----------------------------------------------------------------CODE_SEGSEGMENTMAINPROCFARASSUMECS:CODE_SEG,DS:DATA_SEG,SS:STACK_SEGORG1000HSTART:MOVAX,STACK_SEGMOVSS,AX;给SS赋值MOVSP,OFFSETTOS;给SP赋值PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DATA_SEGMOVDS,AX;给DS赋值┇;程序段部分RETMAINENDPCODE_SEGENDS;以上定义代码段;----------------------------------------------------------------ENDSTART4.17写一个完整的程序放在代码段C_SEG中,要求把数据段D_SEG中的AUGEND和附加段E_SEG中的ADDEND相加,并把结果存放在D_SEG段中的SUM中。其中AUGEND、ADDEND和SUM均为双精度数,AUGEND赋值为99251,ADDEND赋值为-15962。答:程序如下:D_SEGSEGMENTAUGWLABELWORDAUGENDDD99251SUMDD?D_SEGENDS;以上定义数据段;----------------------------------------------------------------E_SEGSEGMENTADDWLABELWORDADDENDDD-15962E_SEGENDS;以上定义附加段;---------------------------------------------------------------- 5162dbd488c339375742f5ffddba7d7a.doc-58-C_SEGSEGMENTMAINPROCFARASSUMECS:C_SEG,DS:D_SEG,ES:E_SEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,D_SEGMOVDS,AX;给DS赋值MOVAX,E_SEGMOVES,AX;给ES赋值;MOVAX,AUGW;以下6条指令进行加法计算MOVBX,AUGW+2ADDAX,ES:ADDWADCBX,ES:ADDW+2;不考虑有符号数溢出MOVWORDPTRSUM,AXMOVWORDPTR[SUM+2],BXRETMAINENDPC_SEGENDS;以上定义代码段;----------------------------------------------------------------ENDSTART4.18请说明表示程序结束的微操作和结束程序执行的语句之间的差别。它们在源程序中应如何表示?答:表示程序结束的微操作是指示汇编程序MASM结束汇编的标志,在源程序中用END表示;结束程序执行的语句是结束程序运行而返回操作系统的指令,在源程序中有多种表示方法,比如INT20H或MOVAX,4C00HINT21H以及RET等。4.19试说明下述指令中哪些需要加上PTR操作符:BVALDB10H,20HWVALDW1000H(1)MOVAL,BVAL;不需要(2)MOVDL,[BX];不需要(3)SUB[BX],2;需要,如SUBBYTEPTR[BX],2(4)MOVCL,WVAL;需要,如MOVCL,BYTEPTRWVAL(5)ADDAL,BVAL+1;不需要答:见注释。习题5试编写一个汇编语言程序,要求对键盘输入的小写字母用大写字母显示出来。答:程序段如下:BEGIN:MOVAH,1;从键盘输入一个字符的DOS调用INT21HCMPAL,‘a’;输入字符<‘a’吗?JBSTOPCMPAL,‘z’;输入字符>‘z’吗?JASTOPSUBAL,20H;转换为大写字母,用ANDAL,11011111B也可MOVDL,AL;显示一个字符的DOS调用MOVAH,2INT21HJMPBEGINSTOP:RET编写程序,从键盘接收一个小写字母,然后找出它的前导字符和后续字符,再按顺序显示这三个字符。答:程序段如下:BEGIN:MOVAH,1;从键盘输入一个字符的DOS调用INT21HCMPAL,‘a’;输入字符<‘a’吗?JBSTOPCMPAL,‘z’;输入字符>‘z’吗?JASTOPDECAL;得到前导字符MOVDL,AL;准备显示三个字符MOVCX,3DISPLAY:MOVAH,2;显示一个字符的DOS调用INT21HINCDLLOOPDISPLAYSTOP:RET将AX寄存器中的16位数分成4组,每组4位,然后把这四组数分别放在AL、BL、CL和DL中。答:程序段如下:DSEGSEGMENTSTOREDB4DUP(?)DSEGENDS┇BEGIN:MOVCL,4;右移四次MOVCH,4;循环四次LEABX,STOREA10:MOVDX,AXANDDX,0FH;取AX的低四位MOV[BX],DL;低四位存入STORE中INCBXSHRAX,CL;右移四次DECCHJNZA10;循环四次完了码?B10:MOVDL,STORE;四组数分别放在AL、BL、CL和DL中MOVCL,STORE+1MOVBL,STORE+2MOVAL,STORE+3STOP:RET试编写一程序,要求比较两个字符串STRING1和STRING2所含字符是否完全相同,若相同则显示‘MATCH’,若不相同则显示‘NOMATCH’。答:程序如下: 5162dbd488c339375742f5ffddba7d7a.doc-58-DSEGSEGMENTSTRING1DB‘Iamastudent.’STRING2DB‘Iamastudent!’YESDB‘MATCH’,0DH,0AH,‘$’NODB‘NOMATCH’,0DH,0AH,‘$’DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEG,ES:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值MOVES,AX;给ES赋值;BEGIN:LEASI,STRING1;设置串比较指令的初值LEADI,STRING2CLDMOVCX,STRING2-STRING1REPECMPSB;串比较JNEDISPNOLEADX,YES;显示MATCHJMPDISPLAYDISPNO:LEADX,NO;显示NOMATCHDISPLAY:MOVAH,9;显示一个字符串的DOS调用INT21HRETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART试编写一程序,要求能从键盘接收一个个位数N,然后响铃N次(响铃的ASCII码为07)。答:程序段如下:BEGIN:MOVAH,1;从键盘输入一个字符的DOS调用INT21HSUBAL,‘0’JBSTOP;输入字符<‘0’吗?CMPAL,9;输入字符>‘9’吗?JASTOPCBWMOVCX,AX;响铃次数NJCXZSTOPBELL:MOVDL,07H;准备响铃MOVAH,2;显示一个字符的DOS调用,实际为响铃INT21HCALLDELAY100ms;延时100msLOOPBELLSTOP:RET编写程序,将一个包含有20个数据的数组M分成两个数组:正数数组P和负数数组N,并分别把这两个数组中数据的个数显示出来。答:程序如下:DSEGSEGMENTCOUNTEQU20ARRAYDW20DUP(?);存放数组COUNT1DB0;存放正数的个数ARRAY1DW20DUP(?);存放正数COUNT2DB0;存放负数的个数ARRAY2DW20DUP(?);存放负数ZHENDB0DH,0AH,‘Thepositivenumberis:’,‘$’;正数的个数是:FUDB0DH,0AH,‘Thenegativenumberis:’,‘$’;负数的个数是:CRLFDB0DH,0AH,‘$’DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVCX,COUNTLEABX,ARRAYLEASI,ARRAY1LEADI,ARRAY2BEGIN1:MOVAX,[BX]CMPAX,0;是负数码?JSFUSHUMOV[SI],AX;是正数,存入正数数组INCCOUNT1;正数个数+1ADDSI,2JMPSHORTNEXTFUSHU:MOV[DI],AX;是负数,存入负数数组INCCOUNT2;负数个数+1ADDDI,2NEXT:ADDBX,2LOOPBEGIN1 5162dbd488c339375742f5ffddba7d7a.doc-58-LEADX,ZHEN;显示正数个数MOVAL,COUNT1CALLDISPLAY;调显示子程序LEADX,FU;显示负数个数MOVAL,COUNT2CALLDISPLAY;调显示子程序RETMAINENDP;--------------------------------------------------------------------------DISPLAYPROCNEAR;显示子程序MOVAH,9;显示一个字符串的DOS调用INT21HAAM;将(AL)中的二进制数转换为二个非压缩BCD码ADDAH,‘0’;变为0~9的ASCII码MOVDL,AHMOVAH,2;显示一个字符的DOS调用INT21HADDAL,‘0’;变为0~9的ASCII码MOVDL,ALMOVAH,2;显示一个字符的DOS调用INT21HLEADX,CRLF;显示回车换行MOVAH,9;显示一个字符串的DOS调用INT21HRETDISPLAYENDP;显示子程序结束CSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART试编写一个汇编语言程序,求出首地址为DATA的100D字数组中的最小偶数,并把它存放在AX中。答:程序段如下:BEGIN:MOVBX,0MOVCX,100COMPARE:MOVAX,DATA[BX];取数组的第一个偶数ADDBX,2TESTAX,01H;是偶数吗?LOOPNZCOMPARE;不是,比较下一个数JNZSTOP;没有偶数,退出JCXZSTOP;最后一个数是偶数,即为最小偶数,退出COMPARE1:MOVDX,DATA[BX];取数组的下一个偶数ADDBX,2TESTDX,01H;是偶数吗?JNZNEXT;不是,比较下一个数CMPAX,DX;(AX)<(DX)吗?JLENEXTMOVAX,DX;(AX)<(DX),则置换(AX)为最小偶数NEXT:LOOPCOMPARE1STOP:RET把AX中存放的16位二进制数K看作是8个二进制的“四分之一字节”。试编写程序要求数一下值为3(即11B)的四分之一字节数,并将该数(即11B的个数)在终端上显示出来。答:程序段如下:BEGIN:MOVDL,0;计数初始值MOVCX,8COMPARE:TESTAX,03H;是数03吗?JNZNOEQUAL;不是,转走INCDL;是,计数NOEQUAL:RORAX,1;准备判断下一个数RORAX,1LOOPCOMPAREADDDL,‘0’;将计数值转换为ASCII码MOVAH,2;进行显示INT21HSTOP:RET试编写一个汇编语言程序,要求从键盘接收一个四位的16进制数,并在终端上显示与它等值的二进制数。答:程序段如下:BEGIN:MOVBX,0;用于存放四位的16进制数MOVCH,4MOVCL,4INPUT:SHLBX,CL;将前面输入的数左移4位MOVAH,1;从键盘取数INT21HCMPAL,30H;<0吗?JBINPUT;不是‘0~F’的数重新输入CMPAL,39H;是‘0~9’吗?JAAF;不是,转‘A~F’的处理ANDAL,0FH;转换为:0000B~1001BJMPBINARYAF:ANDAL,11011111B;转换为大写字母CMPAL,41H;又F吗?JAINPUT;不是‘A~F’的数重新输入ANDAL,0FH;转换为:1010B~1111BADDAL,9BINARY:ORBL,AL;将键盘输入的数进行组合DELCHJNZINPUTDISPN:MOVCX,16;将16位二进制数一位位地转换成ASCII码显示DISP:MOVDL,0ROLBX,1 5162dbd488c339375742f5ffddba7d7a.doc-58-RCLDL,1ORDL,30HMOVAH,2;进行显示INT21HLOOPDISPSTOP:RET设有一段英文,其字符变量名为ENG,并以$字符结束。试编写一程序,查对单词SUN在该文中的出现次数,并以格式“SUN:xxxx”显示出次数。答:程序如下:DSEGSEGMENTENGDB‘Hereissun,sun,…,$’DISPDB‘SUN:’DATDB‘0000’,0DH,0AH,‘$’KEYWORDDB‘sun’DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEG,ES:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值MOVES,AX;给ES赋值BEGIN:MOVAX,0MOVDX,DISP-ENG-2;计算ENG的长度(每次比较sun,因此比较次数-2)LEABX,ENGCOMP:MOVDI,BXLEASI,KEYWORDMOVCX,3REPECMPSB;串比较JNZNOMATCHINCAX;是,SUN的个数加1ADDBX,2NOMATCH:INCBX;指向ENG的下一个字母DECDXJNZCOMPDONE:MOVCH,4;将次数转换为16进制数的ASCII码MOVCL,4LEABX,DAT;转换结果存入DAT单元中DONE1:ROLAX,CLMOVDX,AXANDDL,0FH;取一位16进制数ADDDL,30HCMPDL,39HJLESTOREADDDL,07H;是“A~F”所以要加7STORE:MOV[BX],DL;转换结果存入DAT单元中INCBXDECCHJNZDONE1DISPLAY:LEADX,DISP;显示字符串程序(将DISP和DAT一起显示)MOVAH,09HINT21HRETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART从键盘输入一系列以$为结束符的字符串,然后对其中的非数字字符计数,并显示出计数结果。答:程序段如下:DSEGSEGMENTBUFFDB50DUP(‘’)COUNTDW0DSEGENDS┇BEGIN:LEABX,BUFFMOVCOUNT,0INPUT:MOVAH,01;从键盘输入一个字符的功能调用INT21HMOV[BX],ALINCBXCMPAL,‘$’;是$结束符吗?JNZINPUT;不是,继续输入LEABX,BUFF;对非数字字符进行计数NEXT:MOVCL,[BX]INCBXCMPCL,‘$’;是$结束符,则转去显示JZDISPCMPCL,30H;小于0是非数字字符JBNEXTCMPCL,39H;大于9是非数字字符JANEXTINCCOUNT;个数+1JMPNEXTDISP:┇;16进制数显示程序段(省略)有一个首地址为MEM的100D字数组,试编制程序删除数组中所有为0的项,并将后续项向前压缩,最后将数组的剩余部分补上0。答:程序如下:DSEGSEGMENT 5162dbd488c339375742f5ffddba7d7a.doc-58-MEMDW100DUP(?)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVSI,(100-1)*2;(SI)指向MEM的末元素的首地址MOVBX,-2;地址指针的初值MOVCX,100COMP:ADDBX,2CMPMEM[BX],0JZCONSLOOPCOMPJMPFINISH;比较完了,已无0则结束CONS:MOVDI,BXCONS1:CMPDI,SI;到了最后单元码?JAENOMOVMOVAX,MEM[DI+2];后面的元素向前移位MOVMEM[DI],AXADDDI,2JMPCONS1NOMOV:MOVWORDPTR[SI],0;最后单元补0LOOPCOMPFINISH:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART在STRING到STRING+99单元中存放着一个字符串,试编制一个程序测试该字符串中是否存在数字,如有则把CL的第5位置1,否则将该位置0。答:程序如下:DSEGSEGMENTSTRINGDB100DUP(?)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVSI,0;(SI)作为地址指针的变化值MOVCX,100REPEAT:MOVAL,STRING[SI]CMPAL,30HJBGO_ONCMPAL,39HJAGO_ONORCL,20H;存在数字把CL的第5位置1JMPEXITGO_ON:INCSILOOPREPEATANDCL,0DFH;不存在数字把CL的第5位置0EXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART在首地址为TABLE的数组中按递增次序存放着100H个16位补码数,试编写一个程序把出现次数最多的数及其出现次数分别存放于AX和CX中。答:程序如下:DSEGSEGMENTTABLEDW100HDUP(?);数组中的数据是按增序排列的DATADW?COUNTDW0DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVCX,100H;循环计数器MOVSI,0NEXT:MOVDX,0MOVAX,TABLE[SI]COMP:CMPTABLE[SI],AX;计算一个数的出现次数JNEADDR 5162dbd488c339375742f5ffddba7d7a.doc-58-INCDXADDSI,2LOOPCOMPADDR:CMPDX,COUNT;此数出现的次数最多吗?JLEDONEMOVCOUNT,DX;目前此数出现的次数最多,记下次数MOVDATA,AX;记下此数DONE:LOOPNEXT;准备取下一个数MOVCX,COUNT;出现最多的次数存入(CX)MOVAX,DATA;出现最多的数存入(AX)RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART数据段中已定义了一个有n个字数据的数组M,试编写一程序求出M中绝对值最大的数,把它放在数据段的M+2n单元中,并将该数的偏移地址存放在M+2(n+1)单元中。答:程序如下:DSEGSEGMENTnEQU100H;假设n=100HMDWnDUP(?)DATADW?;M+2n单元ADDRDW?;M+2(n+1)单元DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVCX,n;循环计数器LEADI,MMOVAX,[DI];取第一个数MOVADDR,DI;记下绝对值最大的数的地址CMPAX,0;此数是正数吗?JNSZHEN;是正数,即为绝对值,转去判断下一个数NEGAX;不是正数,变为其绝对值ZHEN:MOVBX,[DI]CMPBX,0;此数是正数吗?JNSCOMP;是正数,即为绝对值,转去比较绝对值大小NEGBX;不是正数,变为其绝对值COMP:CMPAX,BX;判断绝对值大小JAEADDRESSMOVAX,BX;(AX)<(BX),使(AX)中为绝对值最大的数MOVADDR,DI;记下绝对值最大的数的地址ADDRESS:ADDDI,2LOOPZHENMOVDATA,AX;记下此数RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART在首地址为DATA的字数组中存放着100H个16位补码数,试编写一个程序求出它们的平均值放在AX寄存器中;并求出数组中有多少个数小于此平均值,将结果放在BX寄存器中。答:程序如下:DSEGSEGMENTDATADW100HDUP(?)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVCX,100H;循环计数器MOVSI,0MOVBX,0;和((DI),(BX))的初始值MOVDI,0NEXT:MOVAX,DATA[SI]CWDADDBX,AX;求和ADCDI,DX;加上进位位ADDSI,2LOOPNEXTMOVDX,DI;将((DI),(BX))中的累加和放入((DX),(AX))中MOVAX,BXMOVCX,100HIDIVCX;带符号数求平均值,放入(AX)中MOVBX,0MOVSI,0COMP:CMPAX,DATA[SI];寻找小于平均值的数JLENO 5162dbd488c339375742f5ffddba7d7a.doc-58-INCBX;小于平均值数的个数+1NO:ADDSI,2LOOPCOMPRETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART试编制一个程序把AX中的16进制数转换为ASCII码,并将对应的ASCII码依次存放到MEM数组中的四个字节中。例如,当(AX)=2A49H时,程序执行完后,MEM中的4个字节内容为39H,34H,41H,32H。答:程序如下:DSEGSEGMENTMEMDB4DUP(?)NDW2A49HDSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVCH,4;循环计数器MOVCL,4MOVAX,NLEABX,MEMROTATE:MOVDL,AL;从最低四位开始转换为ASCII码ANDDL,0FHADDDL,30HCMPDL,3AH;是0~9吗?JLNEXTADDDL,07H;是A~FNEXT:MOV[BX],DL;转换的ASCII码送入MEM中INCBXRORAX,CL;准备转换下一位DECCHJNZROTATERETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART把0~100D之间的30个数存入以GRADE为首地址的30字数组中,GRADE+i表示学号为i+1的学生的成绩。另一个数组RANK为30个学生的名次表,其中RANK+i的内容是学号为i+1的学生的名次。编写一程序,根据GRADE中的学生成绩,将学生名次填入RANK数组中。(提示:一个学生的名次等于成绩高于这个学生的人数加1。)答:程序如下:DSEGSEGMENTGRADEDW30DUP(?);假设已预先存好30名学生的成绩RANKDW30DUP(?)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVDI,0MOVCX,30;外循环计数器LOOP1:PUSHCXMOVCX,30;内循环计数器MOVSI,0MOVAX,GRADE[DI]MOVDX,1;起始名次为第1名LOOP2:CMPGRADE[SI],AX;成绩比较JBEGO_ONINCDX;名次+1GO_ON:ADDSI,2LOOPLOOP2POPCXMOVRNAK[DI],DX;名次存入RANK数组ADDDI,2LOOPLOOP1RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART已知数组A包含15个互不相等的整数,数组B包含20个互不相等的整数。试编制一程序把既在A中又在B中出现的整数存放于数组C中。答:程序如下:DSEGSEGMENTADW15DUP(?)BDW20DUP(?)CDW15DUP(‘’) 5162dbd488c339375742f5ffddba7d7a.doc-58-DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVSI,0MOVBX,0MOVCX,15;外循环计数器LOOP1:PUSHCXMOVCX,20;内循环计数器MOVDI,0MOVAX,A[SI];取A数组中的一个数LOOP2:CMPB[DI],AX;和B数组中的数相等吗?JNENOMOVC[BX],AX;相等存入C数组中ADDBX,2NO:ADDDI,2LOOPLOOP2ADDSI,2POPCXLOOPLOOP1RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART设在A、B和C单元中分别存放着三个数。若三个数都不是0,则求出三数之和存放在D单元中;若其中有一个数为0,则把其它两单元也清0。请编写此程序。答:程序如下:DSEGSEGMENTADW?BDW?CDW?DDW0DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:CMPA,0JENEXTCMPB,0JENEXTCMPC,0JENEXTMOVAX,AADDAX,BADDAX,CMOVD,AXJMPSHORTEXITNEXT:MOVA,0MOVB,0MOVC,0EXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART试编写一程序,要求比较数组ARRAY中的三个16位补码数,并根据比较结果在终端上显示如下信息:(1)如果三个数都不相等则显示0;(2)如果三个数有二个数相等则显示1;(3)如果三个数都相等则显示2。答:程序如下:DSEGSEGMENTARRAYDW3DUP(?)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:LEASI,ARRAYMOVDX,0;(DX)用于存放所求的结果 5162dbd488c339375742f5ffddba7d7a.doc-58-MOVAX,[SI]MOVBX,[SI+2]CMPAX,BX;比较第一和第二两个数是否相等JNENEXT1INCDXNEXT1:CMP[SI+4],AX;比较第一和第三两个数是否相等JNENEXT2INCDXNEXT2:CMP[SI+4],BX;比较第二和第三两个数是否相等JNENUMINCDXNUM:CMPDX,3JLDISPDECDXDISP:ADDDL,30H;转换为ASCII码MOVAH,2;显示一个字符INT21HRETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART从键盘输入一系列字符(以回车符结束),并按字母、数字、及其它字符分类计数,最后显示出这三类的计数结果。答:程序如下:DSEGSEGMENTALPHABETDB‘输入的字母字符个数为:’,‘$’NUMBERDB‘输入的数字字符个数为:’,‘$’OTHERDB‘输入的其它字符个数为:’,‘$’CRLFDB0DH,0AH,‘$’DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVBX,0;字母字符计数器MOVSI,0;数字字符计数器MOVDI,0;其它字符计数器INPUT:MOVAH,1;输入一个字符INT21HCMPAL,0DH;是回车符吗?JEDISPCMPAL,30H;<数字0吗?JAENEXT1OTHER:INCDI;是其它字符JMPSHORTINPUTNEXT1:CMPAL,39H;>数字9吗?JANEXT2INCSI;是数字字符JMPSHORTINPUTNEXT2:CMPAL,41H;<字母A吗?JAENEXT3JMPSHORTOTHER;是其它字符NEXT3:CMPAL,5AH;>字母Z吗?JANEXT4INCBX;是字母字符A~ZJMPSHORTINPUTNEXT4:CMPAL,61H;<字母a吗?JAENEXT5JMPSHORTOTHER;是其它字符NEXT5:CMPAL,7AH;>字母z吗?JASHORTOTHER;是其它字符INCBX;是字母字符a~zJMPSHORTINPUTDISP:LEADX,ALPHABETCALLDISPLAYLEADX,NUMBERMOVBX,SICALLDISPLAYLEADX,OTHERMOVBX,DICALLDISPLAYRETMAINENDP;--------------------------------------------------------------------------DISPLAYPROCNEARMOVAH,09H;显示字符串功能调用INT21HCALLBINIHEX;调把BX中二进制数转换为16进制显示子程序LEADX,CRLFMOVAH,09H;显示回车换行INT21HRET 5162dbd488c339375742f5ffddba7d7a.doc-58-DISPLAYENDP;--------------------------------------------------------------------------BINIHEXPROCNEAR;将BX中二进制数转换为16进制数显示子程序MOVCH,4ROTATE:MOVCL,4ROLBX,CLMOVDL,BLANDDL,0FHADDDL,30HCMPDL,3AH;是A~F吗?JLPRINT_ITADDDL,07HPRINT_IT:MOVAH,02H;显示一个字符INT21HDECCHJNZROTATERETBINIHEXENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART已定义了两个整数变量A和B,试编写程序完成下列功能:(1)若两个数中有一个是奇数,则将奇数存入A中,偶数存入B中;(2)若两个数中均为奇数,则将两数加1后存回原变量;(3)若两个数中均为偶数,则两个变量均不改变。答:程序如下:DSEGSEGMENTADW?BDW?DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVAX,AMOVBX,BXORAX,BXTESTAX,0001H;A和B同为奇数或偶数吗?JZCLASS;A和B都为奇数或偶数,转走TESTBX,0001HJZEXIT;B为偶数,转走XCHGBX,A;A为偶数,将奇数存入A中MOVB,BX;将偶数存入B中JMPEXITCLASS:TESTBX,0001H;A和B都为奇数吗?JZEXIT;A和B同为偶数,转走INCBINCAEXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART假设已编制好5个歌曲程序,它们的段地址和偏移地址存放在数据段的跳跃表SINGLIST中。试编制一程序,根据从键盘输入的歌曲编号1~5,转去执行五个歌曲程序中的某一个。答:程序如下:DSEGSEGMENTSINGLISTDDSING1DDSING2DDSING3DDSING4DDSING5ERRMSGDB‘Error!Invalidparameter!’,0DH,0AH,‘$’DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVAH,1;从键盘输入的歌曲编号1~5INT21HCMPAL,0DHJZEXIT;是回车符,则结束SUBAL,‘1’;是1~5吗?JBERROR;小于1,错误CMPAL,4JAERROR;大于5,错误MOVBX,OFFSETSINGLISTMULAX,4;(AX)=(AL)*4,每个歌曲程序的首地址占4个字节 5162dbd488c339375742f5ffddba7d7a.doc-58-ADDBX,AXJMPDWORDPTR[BX];转去执行歌曲程序ERROR:MOVDX,OFFSETERRMSGMOVAH,09HINT21H;显示错误信息JMPBEGINSING1:┇JMPBEGINSING2:┇JMPBEGINSING3:┇JMPBEGINSING4:┇JMPBEGINSING5:┇JMPBEGINEXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART试用8086的乘法指令编制一个32位数和16位数相乘的程序;再用80386的乘法指令编制一个32位数和16位数相乘的程序,并定性比较两个程序的效率。答:8086的程序如下(假设为无符号数):DSEGSEGMENTMUL1DD?;32位被乘数MUL2DW?;16位乘数MUL0DW0,0,0,0;乘积用64位单元存放DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVBX,MUL2;取乘数MOVAX,WORDPTRMUL1;取被乘数低位字MULBXMOVMUL0,AX;保存部分积低位MOVMUL0+2,DX;保存部分积高位MOVAX,WORDPTR[MUL1+2];取被乘数高位字MULBXADDMUL0+2,AX;部分积低位和原部分积高位相加ADCMUL0+4,DX;保存部分积最高位,并加上进位EXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART80386的程序如下(假设为无符号数):.386DSEGSEGMENTMUL1DD?;32位被乘数MUL2DW?;16位乘数MUL0DD0,0;乘积用64位单元存放DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVZXEBX,MUL2;取乘数,并0扩展成32位MOVEAX,MUL1;取被乘数MULEBXMOVDWORDPTRMUL0,EAX;保存积的低位双字MOVDWORDPTR[MUL0+4],EDX;保存积的高位双字EXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART80386作32位乘法运算用一条指令即可完成,而8086则需用部分积作两次完成。如数据段中在首地址为MESS1的数据区内存放着一个长度为35的字符串,要求把它们传送到附加段中的缓冲区MESS2中去。为提高程序执行效率,希望主要采用MOVSD指令来实现。试编写这一程序。答:80386的程序如下:.386.MODELSMALL.STACK100H.DATAMESS1DB‘123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ’,?;长度为35的字符串.FARDATA 5162dbd488c339375742f5ffddba7d7a.doc-58-MESS2DB36DUP(?).CODESTART:MOVAX,@DATAMOVDS,AX;给DS赋值MOVAX,@FARDATAMOVES,AX;给ES赋值ASSUMEES:@FARDATABEGIN:LEAESI,MESS1LEAEDI,MESS2CLDMOVECX,(35+1)/4;取传送的次数REPMOVSD;--------------------------------------------------------------------------MOVAX,4C00H;返回DOSINT21HENDSTART试用比例变址寻址方式编写一386程序,要求把两个64位整数相加并保存结果。答:80386的程序如下:.386.MODELSMALL.STACK100H.DATADATA1DQ?DATA2DQ?.CODESTART:MOVAX,@DATAMOVDS,AX;给DS赋值BEGIN:MOVESI,0MOVEAX,DWORDPTRDATA2[ESI*4]ADDDWORDPTRDATA1[ESI*4],EAXINCESIMOVEAX,DWORDPTRDATA2[ESI*4]ADCDWORDPTRDATA1[ESI*4],EAX;--------------------------------------------------------------------------MOVAX,4C00H;返回DOSINT21HENDSTART习题下面的程序段有错吗?若有,请指出错误。CRAYPROCPUSHAXADDAX,BXRETENDPCRAY答:程序有错。改正如下:CRAYPROCADDAX,BXRETCRAYENDP;CRAY是过程名,应放在ENDP的前面9BHF7H57H80HF0A0:00B0H先PUSH,SP-2再PUSH,SP-2POP,SP+26.2题堆栈及SP内容的变化过程已知堆栈寄存器SS的内容是0F0A0H,堆栈指示器SP的内容是00B0H,先执行两条把8057H和0F79BH分别入栈的PUSH指令,然后执行一条POP指令。试画出示意图说明堆栈及SP内容的变化过程。答:变化过程如右图所示:分析下面的程序,画出堆栈最满时各单元的地址及内容。;********************************************S_SEGSEGMENTAT1000H;定义堆栈段DW200DUP(?);200*2=190HTOSLABELWORDS_SEGENDS;********************************************C_SEGSEGMENT;定义代码段ASSUMECS:C_SEG,SS:S_SEGSTART:MOVAX,S_SEG(FLAGS)(AX)T_ADDR0000(DS)1000:0184:0186:0188:018A:018C:018ESP:01866.3题堆栈最满时各单元的地址及内容MOVSS,AXMOVSP,OFFSETTOSPUSHDSMOVAX,0PUSHAX┇PUSHT_ADDRPUSHAXPUSHF┇POPFPOPAXPOPT_ADDRRET;--------------------------------------------------------------------------C_SEGENDS;代码段结束;******************************************ENDSTART;程序结束答:堆栈最满时各单元的地址及内容如右图所示:分析下面的程序,写出堆栈最满时各单元的地址及内容。;********************************************STACKSEGMENTAT500H;定义堆栈段DW128DUP(?)TOSLABELWORD 5162dbd488c339375742f5ffddba7d7a.doc-58-STACKENDS;********************************************CODESEGMENT;定义代码段MAINPROCFAR;主程序部分ASSUMECS:CODE,SS:STACKSTART:MOVAX,STACKMOVSS,AXMOVSP,OFFSETTOSPUSHDSSUBAX,AXPUSHAX;MAINPARTOFPROGRAMGOESHEREMOVAX,4321HCALLHTOARETMAINENDP;主程序部分结束;--------------------------------------------------------------------HTOAPROCNEAR;HTOA子程序CMPAX,15JLEB1PUSHAX0500:00EC:00EE:00F0:00F2:00F4:00F6:00F8:00FA:00FC:00FESP:00EE返回POPBP地址0003H返回POPBP地址0002H返回POPBP地址0001H主程序返回地址0000(DS)6.4题堆栈最满时各单元的地址及内容PUSHBPMOVBP,SPMOVBX,[BP+2]ANDBX,000FHMOV[BP+2],BXPOPBPMOVCL,4SHRAX,CLCALLHTOAPOPBPB1:ADDAL,30HCMPAL,3AHJLPRINTITADDAL,7HPRINTIT:MOVDL,ALMOVAH,2INT21HRETHOTAENDP;HOTA子程序结束;--------------------------------------------------------------------CODEENDS;代码段结束;******************************************ENDSTART;程序结束答:堆栈最满时各单元的地址及内容如右上图所示:下面是一个程序清单,请在下面的图中填入此程序执行过程中的堆栈变化。;*************************0000STACKSGSEGMENT000020[.DW32DUP(?)????]0040STACKSGENDS;*************************0000CODESGSEGMENTPARA‘CODE’;--------------------------------------0000BEGINPROCFARASSUMECS:CODESG,SS:STACKSG00001EPUSHDS00012BC0SUBAX,AX000350PUSHAX0004E80008RCALLB10;--------------------------------------0007CBRET0008BEGINENDP;--------------------------------------0008B10PROC0008E8000CRCALLC10;--------------------------------------000BC3RET000CB10ENDP;--------------------------------------000CC10PROC;--------------------------------------000CC3RET000DC10ENDP;--------------------------------------000DCODESGENDS;*************************ENDBEGIN答:程序执行过程中的堆栈变化如下图所示。 5162dbd488c339375742f5ffddba7d7a.doc-58-(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)SP:(DS)(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)0000(DS)(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)00070000(DS)0020H001EH001CH001AH(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)000B00070000(DS)(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)SP:000B00070000(DS)(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)000B00070000(DS)(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)000B00070000(DS)0018H001AH001CH0020H(0016H)(0018H)(001AH)(001CH)(001EH)(0020H)BEGINPUSHDSPUSHAXCALLB10偏移地址堆栈写一段子程序SKIPLINES,完成输出空行的功能。空出的行数在AX寄存器中。答:程序如下:CSEGSEGMENTSKIPLINESPROCFARASSUMECS:CSEGBEGIN:PUSHCXPUSHDXMOVCX,AXDISP:MOVDL,0DH;显示回车换行,即输出空行MOVAH,2;显示一个字符的DOS调用INT21HMOVDL,0AHMOVAH,2;显示一个字符的DOS调用INT21HLOOPDISPPOPDXPOPCXRETSKIPLINESENDPEND设有10个学生的成绩分别是76,69,84,90,73,88,99,63,100和80分。试编制一个子程序统计60~69分,70~79分,80~89分,90~99分和100分的人数,分别存放到S6,S7,S8,S9和S10单元中。答:程序如下:DSEGSEGMENTRECORDDW76,69,84,90,73,88,99,63,100,80S6DW0S7DW0S8DW0S9DW0S10DW0DSEGENDS;******************************************CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVCX,10CALLCOUNT┇;后续程序RETMAINENDP;--------------------------------------------------------------------------COUNTPROCNEAR;成绩统计子程序MOVSI,0NEXT:MOVAX,RECORD[SI]MOVBX,10;以下5句是根据成绩计算相对S6的地址变化量DIVBL;计算公式为:((成绩)/10-6)*2送(BX)MOVBL,AL;此时(BH)保持为0不变SUBBX,6;应为只统计60分以上成绩SALBX,1;(BX)*2INCS6[BX];S6是S6,S7,S8,S9和S10单元的首地址ADDSI,2LOOPNEXTRETCOUNTENDP;COUNT子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART 5162dbd488c339375742f5ffddba7d7a.doc-58-编写一个有主程序和子程序结构的程序模块。子程序的参数是一个N字节数组的首地址TABLE,数N及字符CHAR。要求在N字节数组中查找字符CHAR,并记录该字符出现的次数。主程序则要求从键盘接收一串字符以建立字节数组TABLE,并逐个显示从键盘输入的每个字符CHAR以及它在TABLE数组中出现的次数。(为简化起见,假设出现次数≤15,可以用16进制形式把它显示出来。)答:程序如下:DSEGSEGMENTTABLEDB255DUP(?)NDW255CHARDB?CHAR_NDB0;用于记录CHAR出现的次数CRLFDB0DH,0AH,‘$’DSEGENDS;以上定义数据段;******************************************STACKSEGMENTDW100DUP(?)TOSLABELWORDSTACKENDS;以上定义堆栈段;******************************************CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEG,SS:STACKSTART:MOVAX,STACKMOVSS,AX;给SS赋值MOVSP,OFFSETTOS;给SP赋值PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVBX,0MOVCX,255;最多输入255个字符INPUT:MOVAH,1;从键盘接收一个字符的DOS功能调用INT21HCMPAL,0DH;输入回车符结束输入JZIN_NMOVTABLE[BX],ALINCBXLOOPINPUTIN_N:MOVN,BX;TABLE数组中的字符个数送NCALLDISP_CRLFIN_CHAR:MOVAH,1;从键盘接收一个字符并回显的DOS功能调用INT21HCMPAL,0DH;输入回车符结束JZEXITMOVCHAR,AL;输入的字符存入CHAR单元CALLSEARCH;调搜索字符子程序MOVDL,‘:’;显示“:”,在字符CHAR(输入时回显)的后面MOVAH,2;显示一个字符INT21HMOVDL,CHAR_N;再显示CHAR出现的次数(次数≤15)ANDDL,0FHADDDL,30HCMPDL,39HJBENEXTADDDL,07H;是A~FNEXT:MOVAH,2;显示一个字符INT21HCALLDISP_CRLFJMPSHORTIN_CHAREXIT:RETMAINENDP;--------------------------------------------------------------------------SEARCHPROCNEAR;搜索字符子程序MOVSI,0MOVCX,NMOVCHAR_N,0MOVAL,CHARROTATE:CMPAL,TABLE[SI]JNZROTATE1INCCHAR_N;搜索到字符,则出现次数+1ROTATE1:INCSILOOPROTATERETSEARCHENDP;SEARCH子程序结束;--------------------------------------------------------------------------DISP_CRLFPROCNEAR;显示回车换行符子程序LEADX,CRLFMOVAH,09HINT21HRETDISP_CRLFENDP;DISP_CRLF子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名及8个字符的电话号码,并以一定的格式显示出来。主程序TELIST:显示提示符“INPUTNAME:”;调用子程序INPUT_NAME输入姓名;显示提示符“INPUTATELEPHONENUMBER:”;调用子程序INPHONE输入电话号码; 5162dbd488c339375742f5ffddba7d7a.doc-58-调用子程序PRINTLINE显示姓名及电话号码。子程序INPUT_NAME:调用键盘输入子程序GETCHAR,把输入的姓名存放在INBUF缓冲区中;把INBUF中的姓名移入输出行OUTNAME。子程序INPHONE:调用键盘输入子程序GETCHAR,把输入的8位电话号码存放在INBUF缓冲区中;把INBUF中的号码移入输出行OUTPHONE。子程序PRINTLINE:显示姓名及电话号码,格式为:NAMETEL.XXXXXXXXXXX答:程序如下:DSEGSEGMENTINBUFDB12DUP(‘’);输入缓冲区,初始值为空格OUTNAMEDB16DUP(‘’),;姓名输出行,初始值为空格OUTPHONEDB12DUP(‘’),0DH,0AH,‘$’;号码输出行,初始值为空格MESG1DB‘INPUTNAME:’,‘$’MESG2DB‘INPUTATELEPHONENUMBER:’,‘$’MESG3DB‘NAME’,12DUP(‘’),‘TEL.’,0DH,0AH,‘$’CRLFDB0DH,0AH,‘$’DSEGENDS;以上定义数据段;******************************************STACKSEGMENTDW100DUP(?)TOSLABELWORDSTACKENDS;以上定义堆栈段;******************************************CSEGSEGMENTTELISTPROCFAR;主程序TELISTASSUMECS:CSEG,DS:DSEG,ES:DSEG,SS:STACKSTART:MOVAX,STACKMOVSS,AX;给SS赋值MOVSP,OFFSETTOS;给SP赋值PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值MOVES,AX;给ES赋值BEGIN:LEADX,MESG1MOVAH,09H;显示字符串功能调用INT21HCALLINPUT_NAME;输入姓名LEADX,MESG2MOVAH,09H;显示字符串功能调用INT21HCALLINPHONE;输入电话号码CALLPRINTLINE;显示姓名及电话号码RETTELISTENDP;--------------------------------------------------------------------------INPUT_NAMEPROCNEAR;输入姓名子程序CALLGETCHAR;调输入字符子程序输入姓名LEASI,INBUF;把INBUF中的姓名移入输出行OUTNAMELEADI,OUTNAMEMOVCX,12CLDREPMOVSBRETINPUT_NAMEENDP;INPUT_NAME子程序结束;--------------------------------------------------------------------------INPHONEPROCNEAR;输入电话号码子程序CALLGETCHAR;调输入字符子程序输入电话号码LEASI,INBUF;把INBUF中的电话号码移入输出行OUTPHONELEADI,OUTPHONEMOVCX,12CLDREPMOVSBRETINPHONEENDP;INPHONE子程序结束;--------------------------------------------------------------------------GETCHARPROCNEAR;键盘输入子程序MOVAL,20H;先将INBUF中填满空格字符MOVCX,12LEADI,INBUFCLDREPSTOSBMOVCX,12;向INBUF输入字符MOVDI,0INPUT:MOVAH,1;从键盘接收一个字符并回显的DOS功能调用INT21HCMPAL,0DH;输入回车符返回JZQUITMOVINBUF[DI],ALINCDILOOPINPUTQUIT:CALLDISP_CRLFRETGETCHARENDP;GETCHAR子程序结束 5162dbd488c339375742f5ffddba7d7a.doc-58-;--------------------------------------------------------------------------PRINTLINEPROCNEAR;显示姓名及电话号码子程序LEADX,MESG3MOVAH,09H;显示字符串功能调用INT21HLEADX,OUTNAME;显示姓名及电话号码MOVAH,09H;显示字符串功能调用INT21HRETPRINTLINEENDP;PRINTLINE子程序结束;--------------------------------------------------------------------------DISP_CRLFPROCNEAR;显示回车换行符子程序LEADX,CRLFMOVAH,09HINT21HRETDISP_CRLFENDP;DISP_CRLF子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART编写子程序嵌套结构的程序,把整数分别用二进制和八进制形式显示出来。主程序BANDO:把整数字变量VAL1存入堆栈,并调用子程序PAIRS;子程序PAIRS:从堆栈中取出VAL1;调用二进制显示程序OUTBIN显示出与其等效的二进制数;输出8个空格;调用八进制显示程序OUTOCT显示出与其等效的八进制数;调用输出回车及换行符子程序。答:程序如下:DSEGSEGMENTVAL1DW?CRLFDB0DH,0AH,‘$’DSEGENDS;以上定义数据段;******************************************CSEGSEGMENTBANDOPROCFAR;主程序BANDOASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值PUSHVAL1CALLPAIRSRETBANDOENDP;--------------------------------------------------------------------------PAIRSPROCNEAR;PAIRS子程序PUSHBPMOVBP,SPPUSHBXMOVBX,[BP+4];从堆栈中取出VAL1CALLOUTBIN;调用二进制显示子程序MOVCX,8;显示8个空格符SPACE:MOVDL,‘’MOVAH,2INT21HLOOPSPACECALLOUTOCT;调用八进制显示子程序CALLDISP_CRLFPOPBXPOPBPRET2PAIRSENDP;PAIRS子程序结束;--------------------------------------------------------------------------OUTBINPROCNEAR;二进制显示子程序PUSHBXMOVCX,16ONEBIT:ROLBX,1MOVDX,BXANDDX,1ORDL,30H;转换为ASCII码MOVAH,2INT21HLOOPONEBITPOPBXRETOUTBINENDP;OUTBIN子程序结束;--------------------------------------------------------------------------OUTOCTPROCNEAR;八进制显示子程序ROLBX,1;16位二进制数包含6位八进制数,最高位仅1位MOVDX,BXANDDX,1ORDL,30H;转换为ASCII码MOVAH,2INT21HMOVCX,5;余下还有5位八进制数NEXT:PUSHCXMOVCL,3;1位八进制数包含3位二进制数ROLBX,CLMOVDX,BXANDDX,07H 5162dbd488c339375742f5ffddba7d7a.doc-58-ORDL,30H;转换为ASCII码MOVAH,2INT21HPOPCXLOOPNEXTRETOUTOCTENDP;OUTOCT子程序结束;--------------------------------------------------------------------------DISP_CRLFPROCNEAR;显示回车换行符子程序LEADX,CRLFMOVAH,09HINT21HRETDISP_CRLFENDP;DISP_CRLF子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART假定一个名为MAINPRO的程序要调用子程序SUBPRO,试问:(1)MAINPRO中的什么指令告诉汇编程序SUBPRO是在外部定义的?(2)SUBPRO怎么知道MAINPRO要调用它?答:(1)EXTRNSUBPRO:FAR(2)PUBLICSUBPRO假定程序MAINPRO和SUBPRO不在同一模块中,MAINPRO中定义字节变量QTY和字变量VALUE和PRICE。SUBPRO程序要把VALUE除以QTY,并把商存在PRICE中。试问:(1)MAINPRO怎么告诉汇编程序外部子程序要调用这三个变量?(2)SUBPRO怎么告诉汇编程序这三个变量是在另一个汇编语言程序定义的?答:(1)PUBLICQTY,VALUE,PRICE(2)EXTRNQTY:BYTE,VALUE:WORD,PRICE:WORD假设:(1)在模块1中定义了双字变量VAR1,首地址为VAR2的字节数据和NEAR标号LAB1,它们将由模块2和模块3所使用;(2)在模块2中定义了字变量VAR3和FAR标号LAB2,而模块1中要用到VAR3,模块3中要用到LAB2;(3)在模块3中定义了FAR标号LAB3,而模块2中要用到它。试对每个源模块给出必要的EXTRN和PUBLIC说明。答:模块1:EXTRNVAR3:WORDPUBLICVAR1,VAR2,LAB1模块2:EXTRNVAR1:DWORD,VAR2:BYTE,LAB1:NEAR,LAB3:FARPUBLICVAR3,LAB2模块3:EXTRNVAR1:DWORD,VAR2:BYTE,LAB1:NEAR,LAB2:FARPUBLICLAB3主程序CALLMUL定义堆栈段、数据段和代码段,并把段寄存器初始化,数据段中定义变量QTY和PRICE;代码段中将PRICE装入AX,QTY装入BX,然后调用子程序SUBMUL。程序SUBMUL没有定义任何数据,它只简单地把AX中的内容(PRICE)乘以BX中的内容(QTY),乘积放在DX:AX中。请编制这两个要连接起来的程序。答:程序如下:TITLECALLMUL;主程序EXTRNSUBMUL:FAR;-----------------------------------------------------------------STACKSEGMENTPARASTACK‘STACK’DW64DUP(?)TOSLABELWORDSTACKENDS;--------------------------------------------------------------DATASGSEGMENTPARA‘DATA’QTYDW0140HPRICEDW2500HDATASGENDS;--------------------------------------------------------------CODESGSEGMENTPARA‘CODE’CALLMULPROCFARASSUMECS:CODESG,DS:DATASG,SS:STACKSTART:MOVAX,STACKMOVSS,AX;给SS赋值MOVSP,OFFSETTOS;给SP赋值PUSHDSSUBAX,AXPOPAXMOVAX,DATASGMOVDS,AXMOVAX,PRICEMOVBX,QTYCALLSUBMULRETCALLMULENDPCODESGENDS;-----------------------------------------------------------------ENDCALLMUL;***************************************************************TITLESUBMUL;子程序PUBLICSUBMUL;-----------------------------------------------------------------CODESG1SEGMENTPARA‘CODE’ASSUMECS:CODESG1SUBMULPROCFARASSUMECS:CODESG1MULBXRETSUBMULENDP 5162dbd488c339375742f5ffddba7d7a.doc-58-CODESG1ENDS;-----------------------------------------------------------------END试编写一个执行以下计算的子程序COMPUTE:R←X+Y-3其中X,Y及R均为字数组。假设COMPUTE与其调用程序都在同一代码段中,数据段D_SEG中包含X和Y数组,数据段E_SEG中包含R数组,同时写出主程序调用COMPUTE过程的部分。如果主程序和COMPUTE在同一程序模块中,但不在同一代码段中,程序应如何修改?如果主程序和COMPUTE不在同一程序模块中,程序应如何修改?答:(1)主程序和COMPUTE在同一代码段中的程序如下:TITLEADDITION;主程序;--------------------------------------------------------------D_SEGSEGMENTPARA‘DATA’COUNTEQU10HXDWCOUNTDUP(?)YDWCOUNTDUP(?)D_SEGENDS;--------------------------------------------------------------E_SEGSEGMENTPARA‘DATA’RDWCOUNTDUP(?)E_SEGENDS;--------------------------------------------------------------C_SEGSEGMENTPARA‘CODE’ADDITIONPROCFARASSUMECS:C_SEG,DS:D_SEG,ES:E_SEGSTART:PUSHDSSUBAX,AXPUSHAXMOVAX,D_SEGMOVDS,AXMOVAX,E_SEGMOVES,AXCALLCOMPUTE;调用求和子程序RETADDITIONENDP;********************************************COMPUTEPROCNEAR;同一段的求和子程序MOVCX,COUNTMOVBX,0REPEAT:MOVAX,X[BX]ADDAX,Y[BX]SUBAX,3MOVES:R[BX],AXRETCOMPUTEENDP;-----------------------------------------------------------------C_SEGENDS;*******************************************ENDSTART(2)主程序和COMPUTE在同一程序模块中,但不在同一代码段中的程序如下:TITLEADDITION;主程序;--------------------------------------------------------------D_SEGSEGMENTPARA‘DATA’COUNTEQU10HXDWCOUNTDUP(?)YDWCOUNTDUP(?)D_SEGENDS;--------------------------------------------------------------E_SEGSEGMENTPARA‘DATA’RDWCOUNTDUP(?)E_SEGENDS;--------------------------------------------------------------C_SEGSEGMENTPARA‘CODE’ADDITIONPROCFARASSUMECS:C_SEG,DS:D_SEG,ES:E_SEGSTART:PUSHDSSUBAX,AXPOPAXMOVAX,D_SEGMOVDS,AXMOVAX,E_SEGMOVES,AXCALLFARPTRCOMPUTE;调用求和子程序RETADDITIONENDPC_SEGENDS;********************************************CODESGSEGMENTPARA‘CODE’ASSUMECS:CODESGCOMPUTEPROCFAR;不同段的求和子程序MOVCX,COUNTMOVBX,0REPEAT:MOVAX,X[BX]ADDAX,Y[BX]SUBAX,3MOVES:R[BX],AXRETCOMPUTEENDP;-----------------------------------------------------------------CODESGENDS 5162dbd488c339375742f5ffddba7d7a.doc-58-;********************************************ENDSTART(3)主程序和COMPUTE不在同一程序模块中的程序如下:TITLEADDITION;主程序EXTRNCOMPUTE:FARPUBLICCOUNT,X,Y,R;--------------------------------------------------------------D_SEGSEGMENTPARA‘DATA’COUNTDW10HXDW10HDUP(?)YDW10HDUP(?)D_SEGENDS;--------------------------------------------------------------E_SEGSEGMENTPARA‘DATA’RDW10HDUP(?)E_SEGENDS;--------------------------------------------------------------C_SEGSEGMENTPARA‘CODE’ADDITIONPROCFARASSUMECS:C_SEG,DS:D_SEG,ES:E_SEGSTART:PUSHDSSUBAX,AXPOPAXMOVAX,D_SEGMOVDS,AXMOVAX,E_SEGMOVES,AXCALLFARPTRCOMPUTE;调用求和子程序RETADDITIONENDPC_SEGENDS;-----------------------------------------------------------------ENDSTART;***************************************************************TITLECOMPUTE;求和子程序EXTRNCOUNT:WORD,X:WORD,Y:WORD,R:WORDPUBLICCOMPUTE;-----------------------------------------------------------------CODESGSEGMENTPARA‘CODE’ASSUMECS:CODESGCOMPUTEPROCFAR;不同模块的求和子程序MOVCX,COUNTMOVBX,0REPEAT:MOVAX,X[BX]ADDAX,Y[BX]SUBAX,3MOVES:R[BX],AXRETCOMPUTEENDP;-----------------------------------------------------------------CODESGENDS;********************************************END习题编写一条宏指令CLRB,完成用空格符将一字符区中的字符取代的工作。字符区首地址及其长度为变元。答:宏定义如下:CLRBMACRON,CFILMOVCX,NCLDMOVAL,‘’;;取空格符的ASCII码LEADI,CFILREPSTOSBENDM某工厂计算周工资的方法是每小时的工资率RATE乘以工作时间HOUR,另外每工作满10小时加奖金3元,工资总数存放在WAG中。请将周工资的计算编写成一条宏指令WAGES,并展开宏调用:WAGESR1,42,SUM答:宏定义如下:WAGESMACRORATE,HOUR,WAGMOVAL,HOUR;;计算周工资(WAG),公式为:HOUR*RATEMOVBL,RATEMULBLMOVWAG,AXMOVAL,HOUR;;计算奖金存入(AX),公式为:HOUR/10的商*3MOVAH,0MOVBL,10DIVBLMOVBL,3MULBLADDWAG,AX;;计算周工资总数ENDM宏调用:WAGESR1,42,SUM宏展开:1MOVAL,421MOVBL,R11MULBL1MOVSUM,AX1MOVAL,42 5162dbd488c339375742f5ffddba7d7a.doc-58-1MOVAH,01MOVBL,101DIVBL1MOVBL,31MULBL1ADDSUM,AX给定宏定义如下:(注意:此宏指令的功能是V3←|V1-V2|)DIFMACROX,YMOVAX,XSUBAX,YENDMABSDIFMACROV1,V2,V3LOCALCONTPUSHAXDIFV1,V2CMPAX,0JGECONTNEGAXCONT:MOVV3,AXPOPAXENDM试展开以下调用,并判定调用是否有效。(1)ABSDIFP1,P2,DISTANCE(2)ABSDIF[BX],[SI],X[DI],CX(3)ABSDIF[BX][SI],X[BX][SI],240H(4)ABSDIFAX,AX,AX答:(1)宏调用ABSDIFP1,P2,DISTANCE的宏展开如下:此宏调用有效。1PUSHAX1DIFP1,P21MOVAX,P11SUBAX,P21CMPAX,01JGE??00001NEGAX1??0000:MOVDISTANCE,AX1POPAX(2)宏调用ABSDIF[BX],[SI],X[DI],CX的宏展开如下:此宏调用有效。1PUSHAX1DIF[BX],[SI]1MOVAX,[BX]1SUBAX,[SI]1CMPAX,01JGE??00011NEGAX1??0001:MOVX[DI],AX1POPAX(3)宏调用ABSDIF[BX][SI],X[BX][SI],240H的宏展开如下:此宏调用无效。1PUSHAX1DIF[BX][SI],X[BX][SI]1MOVAX,[BX][SI]1SUBAX,X[BX][SI]1CMPAX,01JGE??00021NEGAX1??0002:MOV240H,AX1POPAX(4)宏调用ABSDIFAX,AX,AX的宏展开如下:此宏调用有效但无多大意义。1PUSHAX1DIFAX,AX1MOVAX,AX1SUBAX,AX1CMPAX,01JGE??00031NEGAX1??0003:MOVAX,AX1POPAX试编制宏定义,要求把存储器中的一个用EOT(ASCII码04H)字符结尾的字符串传送到另一个存储区去。答:宏定义如下:SENDMACROSCHARS,DCHARSLOCALNEXT,EXITPUSHAXPUSHSIMOVSI,0NEXT:MOVAL,SCHARS[SI]MOVDCHARS[SI],ALCMPAL,04H;;是EOT字符吗?JZEXITINCSIJMPNEXTEXIT:POPSIPOPAXENDM宏指令BIN_SUB完成多个字节数据连减的功能:RESULT←(A-B-C-D-…)要相减的字节数据顺序存放在首地址为OPERAND的数据区中,减数的个数存放在COUNT单元中,最后结果存入RESULT单元。请编写此宏指令。答:宏定义如下:BIN_SUBMACRORESULT,A,OPERAND,COUNTLOCALNEXT_SUBPUSHCX 5162dbd488c339375742f5ffddba7d7a.doc-58-PUSHBXPUSHAXMOVCX,COUNTMOVAL,ALEABX,OPERANDCLCNEXT_SUB:SBBAL,[BX]INCBXLOOPNEXT_SUBMOVRESULT,ALPOPAXPOPBXPOPCXENDM请用宏指令定义一个可显示字符串GOOD:‘GOODSTUDENTS:CLASSXNAME’,其中X和NAME在宏调用时给出。答:宏定义如下:DISP_GOODMACROX,NAMEGOODDB‘GOODSTUDENTS:CLASS&X&NAME’,0DH,0AH,‘$’ENDM下面的宏指令CNT和INC1完成相继字存储。CNTMACROA,BA&BDW?ENDMINC1MACROA,BCNTA,%BB=B+1ENDM请展开下列宏调用:C=0INC1DATA,CINC1DATA,C答:宏展开如下:C=0INC1DATA,C1DATA0DW?INC1DATA,C1DATA0DW?(注意:C为0没有变)定义宏指令并展开宏调用。宏指令JOE把一串信息‘MESSAGENO.K’存入数据存储区XK中。宏调用为:I=0JOETEXT,I┇JOETEXT,I┇JOETEXT,I┇答:宏定义如下:MARYMACROX,KX&KDB‘MESSAGENO.&K’ENDMJOEMACROA,IMARYA,%II=I+1ENDM宏调用和宏展开:I=0JOETEXT,I1TEXT0DB‘MESSAGENO.0’┇JOETEXT,I1TEXT1DB‘MESSAGENO.1’┇JOETEXT,I1TEXT2DB‘MESSAGENO.2’宏指令STORE定义如下:STOREMACROX,NMOVX+I,II=I+1IFI-NSTOREX,NENDIFENDM试展开下列宏调用:I=0STORETAB,7答:宏展开如下:I=0STORETAB,71MOVTAB+0,01MOVTAB+1,11MOVTAB+2,21MOVTAB+3,31MOVTAB+4,41MOVTAB+5,51MOVTAB+6,6试编写非递归的宏指令,使其完成的工作与7.9题的STORE相同。答:宏定义如下:STOREMACROKMOVTAB+K,KENDM 5162dbd488c339375742f5ffddba7d7a.doc-58-宏调用:I=0REPT7STORE%II=I+1ENDM试编写一段程序完成以下功能,如给定名为X的字符串长度大于5时,下列指令将汇编10次。ADDAX,AX答:程序段如下:XDB‘ABCDEFG’IF($-X)GT5REPT10ADDAX,AXENDMENDIF定义宏指令FINSUM:比较两个数X和Y(X、Y为数,而不是地址),若X>Y则执行SUM←X+2*Y;否则执行SUM←2*X+Y。答:宏定义如下:CALCULATEMACROA,B,RESULT;;计算RESULT←2*A+BMOVAX,ASHLAX,1ADDAX,BMOVRESULT,AXENDMFINSUMMACROX,Y,SUMIFXGTYCALCULATEY,X,SUMELSECALCULATEX,Y,SUMENDIFENDM试编写一段程序完成以下功能:如变元X=‘VT55’,则汇编MOVTERMINAL,0;否则汇编MOVTERMINAL,1。答:宏定义如下:BRANCHMACROXIFIDN,MOVTERMINAL,0ELSEMOVTERMINAL,1ENDIFENDM对于DOS功能调用,所有的功能调用都需要在AH寄存器中存放功能码,而其中有一些功能需要在DX中放一个值。试定义宏指令DOS21,要求只有在程序中定义了缓冲区时,汇编为:MOVAH,DOSFUNCMOVDX,OFFSETBUFFINT21H否则,无MOVDX,OFFSETBUFF指令。并展开以下宏调用:DOS2101DOS210AH,IPFIELD答:宏定义如下:DOS21MACRODOSFUNC,BUFFMOVAH,DOSFUNCIFDEFBUFFMOVDX,OFFSETBUFFENDIFINT21HENDM宏展开:DOS21011MOVAH,011INT21HDOS210AH,IPFIELD1MOVAH,0AH1MOVDX,OFFSETIPFIELD1INT21H编写一段程序,使汇编程序根据SIGN中的内容分别产生不同的指令。如果(SIGN)=0,则用字节变量DIVD中的无符号数除以字节变量SCALE;如果(SIGN)=1,则用字节变量DIVD中的带符号数除以字节变量SCALE,结果都存放在字节变量RESULT中。答:程序段如下:MOVAL,DIVDIFSIGNMOVAH,0DIVSCALEELSECBWIDIVSCALEENDIFMOVRESULT,AL试编写宏定义SUMMING,要求求出双字数组中所有元素之和,并把结果保存下来。该宏定义的哑元应为数组首址ARRAY,数组长度COUNT和结果存放单元RESULT。答:宏定义如下:SUMMINGMACROARRAY,COUNT,RESULTLOCALADDITIONMOVESI,0MOVECX,COUNTADDITION:MOVEAX,ARRAY[ESI*4];;双字为4字节ADDRESULT,EAXADCRESULT+4,0;;将进位加到结果的高位双字中INCESILOOPADDITIONENDM为下列数据段中的数组编制一程序,调用题7.16的宏定义SUMMING,求出该数组中各元素之和。DATADD101246,274365,843250,475536 5162dbd488c339375742f5ffddba7d7a.doc-58-SUMDQ?答:程序如下:SUMMINGMACROARRAY,COUNT,RESULTLOCALADDITIONMOVESI,0MOVECX,COUNTADDITION:MOVEAX,ARRAY[ESI*4];;双字为4字节ADDRESULT,EAXADCRESULT+4,0;;将进位加到结果的高位双字中INCESILOOPADDITIONENDM.MODELSMALL.386.DATADATADD101246,274365,843250,475536SUMDQ?.CODESTART:MOVAX,@DATAMOVDS,AXSUMMINGDATA,4,SUMMOVAX,4C00HINT21HENDSTART如把题7.16中的宏定义存放在一个宏库中,则题7.17的程序应如何修改?答:程序修改如下:INCLUDEMACRO.MAC;假设存放的宏库名为MACRO.MAC.MODELSMALL.386.DATADATADD101246,274365,843250,475536SUMDQ?.CODESTART:MOVAX,@DATAMOVDS,AXSUMMINGDATA,4,SUMMOVAX,4C00HINT21HENDSTART输入数据准备好76543210输出寄存器空奇偶校验错溢出错格式错8.3状态寄存器各位含义习题写出分配给下列中断类型号在中断向量表中的物理地址。(1)INT12H(2)INT8答:(1)中断类型号12H在中断向量表中的物理地址为00048H、00049H、0004AH、0004BH;(2)中断类型号8在中断向量表中的物理地址为00020H、00021H、00022H、00023H。用CALL指令来模拟实现INT21H显示字符T的功能。答:MOVAH,2MOVDL,‘T’PUSHDSPUSHF;因中断服务程序的返回指令是IRET,而不是RETMOVBX,0MOVDS,BXCALLDWORDPTR[21H*4];用CALL指令调用21H的中断服务程序POPDS写出指令将一个字节数据输出到端口25H。答:指令为:OUT25H,AL写出指令将一个字数据从端口1000H输入。答:指令为:MOVDX,1000HINAX,DX假定串行通讯口的输入数据寄存器的端口地址为50H,状态寄存器的端口地址为51H,状态寄存器各位为1时含义如右图所示,请编写一程序:输入一串字符并存入缓冲区BUFF,同时检验输入的正确性,如有错则转出错处理程序ERROR_OUT。答:程序段如下:MOVDI,0MOVCX,80;最多输入80个字符BEGIN:INAL,51H;查询输入是否准备好?TESTAL,02HJZBEGININAL,50H;输入数据并存入缓冲区BUFFMOVBUFF[DI],ALINCDIINAL,51H;判断是否有错?TESTAL,00111000BJNZERROR_OUTLOOPBEGIN┇试编写程序,它轮流测试两个设备的状态寄存器,只要一个状态寄存器的第0位为1,则就与其相应的设备输入一个字符;如果其中任一状态寄存器的第3位为1,则整个输入过程结束。两个状态寄存器的端口地址分别是0024H和0036H,与其相应的数据输入寄存器的端口地址则为0026H和0038H,输入字符分别存入首地址为BUFF1和BUFF2的存储区中。答:程序段如下:MOVDI,0MOVSI,0BEGIN:INAL,24HTESTAL,08H;查询第一个设备的输入是否结束?JNZEXITTESTAL,01H;查询第一个设备的输入是否准备好?JZBEGIN1INAL,26H;输入数据并存入缓冲区BUFF1MOVBUFF1[DI],ALINCDIBEGIN1:INAL,36H 5162dbd488c339375742f5ffddba7d7a.doc-58-TESTAL,08H;查询第二个设备的输入是否结束JNZEXITTESTAL,01H;查询第二个设备的输入是否准备好?JZBEGININAL,38H;输入数据并存入缓冲区BUFF2MOVBUFF2[SI],ALINCSIJMPBEGINEXIT:┇假定外部设备有一台硬币兑换器,其状态寄存器的端口地址为0006H,数据输入寄存器的端口地址为0005H,数据输出寄存器的端口地址为0007H。试用查询方式编制一程序,该程序作空闲循环等待纸币输入,当状态寄存器第2位为1时,表示有纸币输入,此时可从数据输入寄存器输入的代码中测出纸币的品种,一角纸币的代码为01,二角纸币为02,五角纸币则为03。然后程序在等待状态寄存器的第3位变为1后,把应兑换的五分硬币数(用16进制表示)从数据输出寄存器输出。答:程序段如下:BEGIN:INAL,06H;查询是否有纸币输入?TESTAL,04HJZBEGININAL,05H;测试纸币的品种CMPAL,01H;是一角纸币吗?JNENEXT1MOVAH,02;是一角纸币,输出2个5分硬币JMPNEXTNEXT1:CMPAL,02H;是二角纸币吗?JNENEXT2MOVAH,04;是二角纸币,输出4个5分硬币JMPNEXTNEXT2:CMPAL,03H;是五角纸币吗?JNEBEGINMOVAH,10;是五角纸币,输出10个5分硬币NEXT:INAL,06H;查询是否允许输出5分硬币?TESTAL,08HJZNEXTMOVAL,AH;输出5分硬币OUT07H,ALJMPBEGIN给定(SP)=0100H,(SS)=0300H,(FLAGS)=0240H,以下存储单元的内容为(00020)=0040H,(00022)=0100H,在段地址为0900及偏移地址为00A0H的单元中有一条中断指令INT8,试问执行INT8指令后,SP,SS,IP,FLAGS的内容是什么?栈顶的三个字是什么?答:执行INT8指令后,(SP)=00FAH,(SS)=0300H,(CS)=0100H,(IP)=0040H,(FLAGS)=0040H栈顶的三个字是:原(IP)=00A2H,原(CS)=0900H,原(FLAGS)=0240H类型14H的中断向量在存储器的哪些单元里?答:在0000:0050H,0000:0051H,0000:0052H,0000:0053H四个字节中。假定中断类型9H的中断处理程序的首地址为INT_ROUT,试写出主程序中为建立这一中断向量而编制的程序段。答:程序段如下:┇MOVAL,1CH;取原中断向量,并保护起来MOVAH,35HINT21HPUSHESPUSHBXPUSHDSMOVAX,SEGINT_ROUTMOVDS,AXMOVDX,OFFSETINT_ROUTMOVAL,09HMOVAH,25H;设置中断向量功能调用INT21HPOPDS┇POPDX;还原原中断向量POPDSMOVAL,1CHMOVAH,25HINT21H编写指令序列,使类型1CH的中断向量指向中断处理程序SHOW_CLOCK。答:程序段如下:┇MOVAL,1CHMOVAH,35H;取中断向量功能调用,取原中断向量INT21HPUSHESPUSHBXPUSHDSMOVAX,SEGSHOW_CLOCKMOVDS,AXMOVDX,OFFSETSHOW_CLOCKMOVAL,1CHMOVAH,25H;设置中断向量功能调用INT21HPOPDS┇POPDXPOPDSMOVAL,1CHMOVAH,25H;设置中断向量功能调用,还原原中断向量INT21H┇如设备D1,D2,D3,D4,D5是按优先级次序排列的,设备D1的优先级最高。而中断请求的次序如下所示,试给出各设备的中断处理程序的运行次序。假设所有的中断处理程序开始后就有STI指令。(1)设备D3和D4同时发出中断请求。(2)在设备D3的中断处理程序完成之前,设备D2发出中断请求。 5162dbd488c339375742f5ffddba7d7a.doc-58-(3)在设备D4的中断处理程序未发出中断结束命令(EOI)之前,设备D5发出中断请求。(4)以上所有中断处理程序完成并返回主程序,设备D1,D3,D5同时发出中断请求。答:各设备的中断处理程序的运行次序是:INT_D3,INT_D2嵌套INT_D3,INT_D4,INT_D5;INT_D1,INT_D3,INT_D5。在8.12题中假设所有的中断处理程序中都没有STI指令,而它们的IRET指令都可以由于FLAGS出栈而使IF置1,则各设备的中断处理程序的运行次序应是怎样的?答:各设备的中断处理程序的运行次序是:INT_D3,INT_D2,INT_D4,INT_D5;INT_D1,INT_D3,INT_D5。试编制一程序,要求测出任一程序的运行时间,并把结果打印出来。答:程序段如下:TITLETEST_TIME.EXE;测试程序运行时间程序;******************************************DSEGSEGMENT;定义数据段COUNTDW0;记录系统时钟(18.2次中断/秒)的中断次数SECDW0;存放秒钟数MINDW0;存放分钟数HOURSDW0;存放小时数PRINTTIMEDB0DH,0AH,‘Thetimeofexectionprogramis:’CHAR_NOEQU$-PRINTTIMEDSEGENDS;以上定义数据段;******************************************CSEGSEGMENT;定义代码段MAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值MOVAL,1CH;取原来的1CH中断向量MOVAH,35HINT21HPUSHES;保存原来的1CH中断向量PUSHBXPUSHDS;设置新的1CH中断向量MOVAX,SEGCLINTMOVDS,AXMOVDX,OFFSETCLINTMOVAL,1CHMOVAH,25HINT21HPOPDSINAL,21H;清除时间中断屏蔽位并开中断ANDAL,0FEHOUT21H,ALSTI┇;要求测试时间的程序段POPDX;恢复原来的1CH中断向量POPDSMOVAL,1CHMOVAH,25HINT21HCALLPRINT;打印输出测试时间RET;返回DOSMAINENDP;----------------------------------------------------------------------------------CLINTPROCNEAR;中断服务子程序PUSHDSPUSHBXMOVBX,SEGCOUNTMOVDS,BXLEABX,COUNTINCWORDPTR[BX];记录系统时钟的中断次数单元+1CMPWORDPTR[BX],18;有1秒钟吗?JNETIMEOKCALLINCTEST;有1秒钟,转去修改时间ADJ:CMPHOURS,12;有12小时吗?JLETIMEOKSUBHOURS,12;有12小时,将小时数减去12TIMEOK:MOVAL,20H;发中断结束命令OUT20H,ALPOPBXPOPDSIRETCLINTENDP;CLINT中断服务子程序结束;----------------------------------------------------------------------------------INCTESTPROCNEAR;修改时间子程序MOVWORDPTR[BX],0;中断次数单元或秒单元或分单元清0ADDBX,2INCWORDPTR[BX];秒单元或分单元或时单元+1CMPWORDPTR[BX],60;有60秒或60分吗?JLERETURNCALLINCTEST;先修改秒单元,再修改分单元,再修改时单元RETURN:RETINCTESTENDP;INCTEST子程序结束;----------------------------------------------------------------------------------PRINTPROCNEAR;打印输出子程序LEABX,PRINTTIME;打印输出PRINTTIME信息MOVCX,CHAR_NOROTATE:MOVDL,[BX] 5162dbd488c339375742f5ffddba7d7a.doc-58-MOVAH,05HINT21HINCBXLOOPROTATEMOVBX,HOURS;打印时间的小时数CALLBINIDEC;调二进制转换为10进制并打印输出子程序MOVDL,‘:’;打印输出冒号‘:’MOVAH,05HINT21HMOVBX,MIN;打印时间的分钟数CALLBINIDECMOVDL,‘:’MOVAH,05HINT21HMOVBX,SEC;打印时间的秒钟数CALLBINIDECRETPRINTENDP;PRINT子程序结束;----------------------------------------------------------------------------------BINIDECPROCNEAR;二进制转换为10进制子程序MOVCX,10000DCALLDEC_DIV;调除法并打印输出子程序MOVCX,1000DCALLDEC_DIVMOVCX,100DCALLDEC_DIVMOVCX,10DCALLDEC_DIVMOVCX,1DCALLDEC_DIVRETBINIDECENDP;BINIDEC子程序结束;----------------------------------------------------------------------------------DEC_DIVPROCNEAR;除法并打印输出子程序MOVAX,BXMOVDX,0DIVCXMOVBX,DX;余数保存在(BX)中作下一次的除法MOVDL,AL;商(在00H~09H范围内)送(DL)ADDDL,30H;转换为0~9的ASCII码MOVAH,05H;打印输出INT21HRETDEC_DIVENDP;DEC_DIV子程序结束;----------------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART;汇编语言源程序结束习题INT21H的键盘输入功能1和功能8有什么区别?答:键盘输入功能1:输入字符并回显(回送显示器显示)(检测Ctrl_Break);键盘输入功能8:输入字符但不回显(也检测Ctrl_Break)。编写一个程序,接受从键盘输入的10个十进制数字,输入回车符则停止输入,然后将这些数字加密后(用XLAT指令变换)存入内存缓冲区BUFFER。加密表为:输入数字:0,1,2,3,4,5,6,7,8,9密码数字:7,5,9,1,3,6,8,0,2,4答:程序段如下:SCODEDB7,5,9,1,3,6,8,0,2,4;密码数字BUFFERDB10DUP(?);┇MOVSI,0MOVCX,10LEABX,SCODEINPUT:MOVAH,1;从键盘输入一个字符的功能调用INT21HCMPAL,0DH;输入回车符则停止输入JZEXITSUBAL,30H;是0~9吗?JBINPUTCMPAL,09HJAINPUTXLAT;换为密码MOVBUFFER[SI],AL;保存密码INCSILOOPINPUTEXIT:RET对应黑白显示器屏幕上40列最下边一个象素的存储单元地址是什么?答:对应黑白显示器屏幕上40列最下边一个象素的存储单元地址是:B000:0F78H写出把光标置在第12行,第8列的指令。答:指令如下:MOVDH,0BH;0BH=12-1MOVDL,07H;07H=8-1MOVBH,0MOVAH,2;置光标功能调用INT10H编写指令把12行0列到22行79列的屏幕清除。答:指令如下:MOVAL,0;清除屏幕MOVBH,07MOVCH,12;左上角行号 5162dbd488c339375742f5ffddba7d7a.doc-58-MOVCL,0;左上角列号MOVDH,22;右下角行号MOVDL,79;右下角列号MOVAH,6;屏幕上滚功能调用INT10H编写指令使其完成下列要求。(1)读当前光标位置(2)把光标移至屏底一行的开始(3)在屏幕的左上角以正常属性显示一个字母M答:指令序列如下:(1)MOVAH,3;读当前光标位置,返回DH/DL=光标所在的行/列MOVBH,0INT10H(2)MOVDH,24;设置光标位置MOVDL,0MOVBH,0MOVAH,2INT10H(3)MOVAH,2;设置光标位置MOVDX,0MOVBH,0INT10HMOVAH,9;在当前光标位置显示一个字符MOVAL,‘M’MOVBH,0MOVBL,7MOVCX,1INT10H写一段程序,显示如下格式的信息:Tryagain,youhavenstarfightersleft.其中n为CX寄存器中的1~9之间的二进制数。答:程序段如下:MESSAGEDB‘Tryagain,youhave’CONTDBnDB‘starfightersleft.$’;┇ADDCL,30HMOVCONT,CL;保存ASCII码LEADX,MESSAGEMOVAH,9;显示一个字符串的DOS调用INT21H从键盘上输入一行字符,如果这行字符比前一次输入的一行字符长度长,则保存该行字符,然后继续输入另一行字符;如果它比前一次输入的行短,则不保存这行字符。按下‘$’输入结束,最后将最长的一行字符显示出来。答:程序段如下:STRINGDB0;存放字符的个数DB80DUP(?),0DH,0AH,‘$’;存放前一次输入的字符串,兼作显示缓冲区BUFFERDB80;输入字符串的缓冲区,最多输入80个字符DB?DB80DUP(20H);┇INPUT:LEADX,BUFFER;输入字符串MOVAH,0AH;输入字符串的DOS调用INT21HLEASI,BUFFER+1;比较字符串长度LESDI,STRINGMOVAL,[SI]CMPAL,[DI]JBENEXTMOVCX,80+1;大于前次输入的字符串,更换前次的字符串CLDREPMOVSBNEXT:MOVAH,1;输入结束符吗?INT21HCMPAL,‘$’;是结束符吗?JNEINPUT;不是则继续输入LEADX,STRING+1;显示字符串MOVAH,9;显示一个字符串的DOS调用INT21H编写程序,让屏幕上显示出信息“Whatisthedate(mm/dd/yy)?”并响铃(响铃符为07),然后从键盘接收数据,并按要求的格式保存在date存储区中。答:程序段如下:MESSAGEDB‘Whatisthedate(mm/dd/yy)?’,07H,‘$’DATAFLDDB10,0DATEDB10DUP(‘’);┇MOVAH,9;显示一个字符串的DOS调用LEADX,MESSAGE;显示字符串INT21HMOVAH,0AH;输入字符串的DOS调用LEADX,DATAFLDINT21H用户从键盘输入一文件并在屏幕上回显出来。每输入一行(≤80字符),用户检查一遍,如果用户认为无需修改,则键入回车键,此时这行字符存入BUFFER缓冲区保存,同时打印机把这行字符打印出来并回车换行。答:程序段如下:INAREADB80;输入字符串的缓冲区,最多输入80个字符ACTLENDB?BUFFERDB80DUP(?);┇INPUT:LEADX,INAREA;输入字符串MOVAH,0AH;输入字符串的DOS调用 5162dbd488c339375742f5ffddba7d7a.doc-58-INT21HCMPACTLEN,0JEEXITMOVBX,0MOVCH,0MOVCL,ACTLENPRINT:MOVAH,5;打印输出MOVDL,BUFFER[BX]INT21HINCBXLOOPPRINTMOVAH,5;打印输出回车换行MOVDL,0AHINT21HMOVDL,0DHINT21HJMPINPUTEXIT:RET使用MODE命令,设置COM2端口的通信数据格式为:每字8位,无校验,1位终止位,波特率为1200b/s。答:命令格式如下:MODECOM2:12,N,8,1习题写出指令,选择显示方式10H,并将背景设为绿色。答:MOVAH,00HMOVAL,10H;选择显示方式10H(16色图形)INT10HMOVAH,10HMOVAL,00HMOVBH,10H;背景设为绿色(02H也可以,是用DEBUG调试出来的)MOVBL,0;选择0号调色板INT10H设置背景色也可用:MOVAH,0BH;设置背景色和调色板MOVBH,0;设置背景色功能MOVBL,8;绿色背景INT10H如何使用INT10H的功能调用改变显示方式?答:在AH中设置功能号00H,在AL中设置显示方式值,调用INT10H即可。VGA独有的一种显示方式是什么?答:像素值为640×480,可同时显示16种颜色,这种显示方式(12H)是VGA独有的。对于EGA和VGA显示适配器,使用显示方式13H时(只有VGA有),显示数据存在哪里?答:显示数据存在显示存储器里。对于VGA的显示方式13H时存放一屏信息需要多少字节的显存?答:需要64000个字节。利用BIOS功能编写图形程序:设置图形方式10H,选择背景色为蓝色,然后每行(水平方向)显示一种颜色,每4行重复一次,一直到整个屏幕都显示出彩条。答:程序如下:TITLEGRAPHIX.COMcodesegsegmentassumecs:codeseg,ds:codeseg,ss:codesegorg100hmainprocfarmovah,00hmoval,10h;选择显示方式10h(16色图形)int10hmovah,0bhmovbh,00hmovbl,01h;背景设为蓝色int10hmovah,0bhmovbh,01hmovbl,00h;设置调色板0#int10hmovbx,0;显存的第0页movcx,0;起始列号为0列movdx,0;起始行号为0行line:movah,0ch;写像素点moval,blint10hinccxcmpcx,640jnelinemovcx,0;起始列号为0列incblandbl,03h;只显示四种颜色(因此保留最低两位)incdxcmpdx,350jnelineint20hmainendpcodesegendsendmain修改10.6题的程序,使整个屏幕都显示出纵向的彩条。答:程序如下:TITLEGRAPHIX.COMcodesegsegmentassumecs:codeseg,ds:codeseg,ss:codesegorg100hmainprocfar 5162dbd488c339375742f5ffddba7d7a.doc-58-movah,00hmoval,10h;选择显示方式10h(16色图形)int10hmovah,0bhmovbh,00hmovbl,01h;背景设为蓝色int10hmovah,0bhmovbh,01hmovbl,00h;设置调色板0#int10hmovbx,0;显存的第0页movcx,0;起始列号为0列movdx,0;起始行号为0行line:movah,0ch;写像素点moval,blint10hincdxcmpdx,350jnelinemovdx,0;起始行号为0行incblandbl,03h;只显示四种颜色(因此保留最低两位)inccxcmpcx,640jnelineint20hmainendpcodesegendsendmain按动键盘上的光标控制键,在屏幕上下左右任一方向上绘图,每画一点之前,由数字键0~3指定该点的颜色值,按动ESC键,绘图结束,返回DOS。答:程序如下:;DRAW—Programtodrawonscreenwithsursorarrows;For640*350colormodeupequ48h;向上键的扫描值downequ50h;向下键的扫描值leftequ4bh;向左键的扫描值rightequ4dh;向右键的扫描值escapeequ1bh;“Esc”charactercodesegsegmentmainprocfarassumecs:codeseg;clearscreenbyscrollingit,usingROMcallstart:movah,06hmoval,00hmovcx,00hmovdl,79movdh,24int10h;screenpointerwillbeinCX,DXregisters;rownumber(0to350d)inDX;coumnnumber(0to640d)inCXmovah,00hmoval,10h;选择显示方式10h(16色图形)int10hmovah,0bhmovbh,00hmovbl,01h;背景设为蓝色int10hmovah,0bhmovbh,01hmovbl,00h;设置调色板0#int10hmovdx,175;设在屏幕中心movcx,320;getcharacterfromkeyboardget_char:movah,0;键盘输入int16hcmpal,escapejzexitcmpal,33h;>‘3’吗?jgplotcmpal,30h;<‘0’吗?jlplotmovbl,al;是‘0’~‘3’,设置颜色andbl,03jmpget_char;figureoutwhichwaytogo,anddrawnewlineplot:moval,ahcmpal,upjnznot_updecdxnot_up:cmpal,downjnznot_downincdxnot_down:cmpal,rightjnznot_rightinccxnot_right:cmpal,leftjnzwrite 5162dbd488c339375742f5ffddba7d7a.doc-58-deccx;useROMroutinetowritedot,reguiresrow#inDX,colinCX,colorinALwrite:moval,blmovah,0chint10hjmpget_charexit:int20hmainendpcodesegendsendstart位屏蔽寄存器的作用是什么?在16色,640×480显示方式中如何使用位屏蔽寄存器?答:位屏蔽寄存器的作用是决定了新的像素值产生的方法。当位屏蔽寄存器的某位设为0时,相对应的像素值直接由锁存器写入显存;位屏蔽寄存器的某位为1时,所对应的像素值由锁存器中的像素值与CPU数据或置位/重置寄存器中相应位合并之后产生。读映像选择寄存器的作用是什么?如果4个位面的内容都需要读取,读映像选择寄存器应如何设置?答:读映像选择寄存器的作用是用于选择哪一个位面的字节读入CPU。读映像选择寄存器的0和1位,用来指定哪个位面的锁存器内容读到CPU。如果4个位面的内容都需要读取,则必须对同一地址执行4次读操作,在每次读之前,用指令分别设置读映像选择寄存器。编写程序使一只“鸟”飞过屏幕。飞鸟的动作可由小写字母v(ASCII码76H)变为破折号(ASCII码0C4H)来模仿,这个字符先后交替在两列显示。鸟的开始位置是0列20行,每个字符显示0.5秒,然后消失。答:程序段如下:TITLEFlier.EXE;飞鸟程序;******************************************DSEGSEGMENT;定义数据段BIRDDB76H,07;小写字母v及属性DB0C4H,07;破折号及属性DSEGENDS;以上定义数据段;******************************************CSEGSEGMENT;定义代码段MAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值MOVAH,0FH;取当前显示方式INT10HPUSHAX;保存当前显示方式(AL)MOVAH,0;设置彩色80×25文本方式MOVAL,3INT10HMOVDH,20;20行MOVDL,0;0列BEGIN:MOVSI,2;字符v和破折号“-”交替显示MOVCX,1;一次显示一个字符及属性LEADI,BIRDDISP:CMPDL,79;飞到79列就退出JAEEXITMOVAH,2;置光标位置INT10HMOVAH,9;在光标位置显示字符及属性MOVAL,[DI];取显示字符及属性MOVBL,[DI+1]INT10HCALLDELAY;延时0.5秒MOVAH,9;在光标位置显示字符及属性MOVAL,‘’;显示空格,擦除该位置的字符MOVBL,7INT10HINCDL;飞到下一列ADDDI,2DECSIJNZDISPJMPBEGINEXIT:POPAX;恢复当前显示方式(AL)MOVAH,0INT10HRET;返回DOSMAINENDP;----------------------------------------------------------------------------------DELAYPROCNEAR;延时0.5s子程序PUSHCXPUSHDXMOVDX,50;延时0.5sDEL1:MOVCX,2801;延时10msDEL2:LOOPDEL2DECDXJNZDEL1POPDXPOPCXRETDELAYENDP;DELAY子程序结束;----------------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART;汇编语言源程序结束 5162dbd488c339375742f5ffddba7d7a.doc-58-ASCII码为0DDHASCII码为0DCHASCII码为0DFHASCII码为0DBHASCII码为0DEH用图形文本的方法设计“Name=XXX”(X为你自己姓名的缩写),并将其数据编码定义在一个数组中。答:用图形文本的方法设计“NAME=YQS”的程序和数组如下:显示格式如下:ShootingTITLENAME_YQS.EXE;显示“NAME=YQS”的程序;******************************************;GraphicsblockmessageforthewordsshootingNAME=YQS;00H→endofmassage,0FFH→endofscreenlineDSEGSEGMENT;定义数据段NAME_YQSDB2;Startrow(开始行)DB2;Startcolumn(开始列)DB10000011B;ColorattributeDB‘Shooting’,0FFH,0FFH;显示“Shooting”DB7DUP(0DCH),0FFH,0FFH;GraphicsencodingofthewordNAME=YQSusingIBMcharactersetDB0DEH,0DBH,4DUP(20H),0DBH,0DDH,20H,0DBH,0DFH,0DBHDB20H,20H,0DBH,5DUP(20H),0DBH,20H,2DUP(0DFH,0DBH)DB8DUP(20H),0DFH,0DBH,20H,20H,0DBH,0DFH,20H,20HDB3DUP(0DBH),3DUP(20H),3DUP(0DBH),0DCH,0FFHDB0DEH,0DBH,0DBH,3DUP(20H),0DBH,0DDH,2DUP(20H,0DBH)DB20H,20H,0DBH,0DBH,3DUP(20H),0DBH,0DBH,20H,20H,0DBHDB11DUP(20H),3DUP(0DBH,20H,20H),20H,0DBH,20H,0DBHDB3DUP(20H),0DFH,0FFHDB0DEH,0DBH,20H,0DBH,20H,20H,0DBH,0DDH,2DUP(20H,0DBH)DB20H,4DUP(20H,0DBH),20H,20H,0DBH,0DCH,0DBH,20HDB7DUP(0DFH),3DUP(20H,20H,0DBH),3DUP(20H),0DBH,20H,0DBHDB3DUP(0DCH),20H,0FFHDB0DEH,0DBH,20H,20H,0DBH,20H,0DBH,0DDH,20H,0DBH,0DFHDB0DBH,4DUP(20H,20H,0DBH),20H,0DFH,20H,7DUP(0DCH),20HDB20H,0DFH,0DBH,0DBH,0DFH,20H,20H,0DBH,3DUP(20H),0DBHDB20H,20H,3DUP(0DFH),0DBH,0FFHDB0DEH,0DBH,3DUP(20H),0DBH,0DBH,0DDH,2DUP(20H,0DBH),20HDB20H,0DBH,5DUP(20H),2DUP(0DBH,20H,20H),10DUP(20H),0DBHDB0DBH,3DUP(20H),0DBH,20H,0DCH,20H,0DBH,20H,0DCHDB3DUP(20H),0DBH,0FFHDB0DEH,0DBH,4DUP(20H),0DBH,0DDH,0DCH,0DBH,20H,0DBHDB0DCH,20H,0DBH,5DUP(20H),0DBH,20H,2DUP(0DCH,0DBH)DB9DUP(20H),0DCH,0DBH,0DBH,0DCH,3DUP(20H),0DFH,0DFHDB0DBH,20H,20H,0DFH,3DUP(0DBH),20H,0FFHDB00;结束显示标志START_COLDB?DSEGENDS;以上定义数据段;******************************************;Textdisplayprocedures:displayamessageonthegraphicsscreenCSEGSEGMENT;定义代码段MAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AXLEADI,NAME_YQSMOVDH,[DI];GetrowintoDHINCDI;BumppointerMOVDL,[DI];AndcolumnintoDLMOVSTART_COL,DL;StorestartcolumnMOVAH,2;SetcursorpositionMOVBH,0;Page0INT10HINCDI;BumppointertoattributeMOVBL,[DI];GetcolorcodeintoBLChar_write:INCDI;BumptomessagestartMOVAL,[DI];GetcharacterCMPAL,0FFH;Endofline?JEBUMP_ROW;NextrowCMPAL,0;TestforterminatorJEEND_TEXT;ExitroutineCALLSHOW_CHARJMPCHAR_WRITEEND_TEXT:RET;返回DOSBump_row:INCDH;RowcontrolregisterMOVDL,START_COL;ColumncontroltostartcolumnMOVAH,2;SetcursorpositionMOVBH,0;Page0 5162dbd488c339375742f5ffddba7d7a.doc-58-INT10HJMPCHAR_WRITEMAINENDP;----------------------------------------------------------------------------------;DisplaycharacterinALandusingthecolorcodeinBLShow_charPROCNEAR;显示字符子程序MOVAH,9;BIOSservicerequestnumberMOVBH,0;Page0MOVCX,1;NorepeatINT10H;BumpcursorINCDLMOVAH,2;SetcursorpositionMOVBH,0;Page0INT10HRETShow_charENDP;SHOW_CHAR子程序结束;----------------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART;汇编语言源程序结束游戏程序常常用随机数来控制其图形在屏幕上移动。请编写一程序,用随机数来控制笑脸符(ASCII码02H)显示的位置。笑脸符每次显示的列号总是递增1。而行的位置可能是前次的上一行,下一行或同一行,这根据随机数是0、1或2来决定,当行号变为0、24或列号变为79时显示结束。笑脸在每个位置上显示0.25s。(提示:INT1AH的AH=0是读当前时间的功能调用,利用该功能返回的随时都在变化的时间值作为产生随机数的基数。)答:程序段如下:TITLEDisp_Laugh.EXE;笑脸显示程序;******************************************CSEGSEGMENT;定义代码段MAINPROCFARASSUMECS:CSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAH,0FH;取当前显示方式INT10HPUSHAX;保存当前显示方式(AL)MOVAH,0;设置彩色80×25文本方式MOVAL,3INT10HMOVCX,1;一次显示一个笑脸字符及属性MOVDH,12H;12行,从屏幕左边的中间开始MOVDL,0;0列BEGIN:CMPDL,79;移到79列就退出JAEEXITCMPDH,0;移到第0行就退出JBEEXITCMPDH,24;移到第24行就退出JAEEXITMOVAH,2;置光标位置INT10HMOVAH,9;在光标位置显示字符及属性MOVAL,02H;取笑字符及属性MOVBL,7INT10HCALLDELAY;延时0.25秒MOVAH,9;在光标位置显示字符及属性MOVAL,‘’;显示空格,擦除该位置的字符MOVBL,7INT10HINCDL;移到下一列PUSHDXMOVAH,0;读当前时间,CH:CL=时:分,DH:DL=秒:1/100秒;产生随机数基数INT1AHMOVAX,DXPOPDXANDAL,03H;随机数为1/100秒的最低两位JZDOWN;随机数的最低两位为0则下降一行CMPAL,1JNZLEVEL;随机数的最低两位为≥2则水平移动DECDH;随机数的最低位为1则上跳一行JMPBEGINDOWN:INCDHLEVEL:JMPBEGINEXIT:POPAX;恢复当前显示方式(AL)MOVAH,0INT10HRET;返回DOSMAINENDP;----------------------------------------------------------------------------------DELAYPROCNEAR;延时0.25s子程序PUSHCXPUSHDXMOVDX,25;延时0.25sDEL1:MOVCX,2801;延时10msDEL2:LOOPDEL2DECDXJNZDEL1POPDX 5162dbd488c339375742f5ffddba7d7a.doc-58-POPCXRETDELAYENDP;DELAY子程序结束;----------------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART;汇编语言源程序结束分配给PC机主板上的8253/54定时器的端口地址是什么?答:8253/54定时器的3个独立计数器Counter0、Counter1和Counter2的端口地址分别为40H、41H和42H。8253/54内部还有一个公用的控制寄存器,端口地址为43H。8253/54定时器的三个计数器,哪一个用于扬声器?它的端口地址是什么?答:8253/54定时器的计数器Counter2用于扬声器,它的端口地址为42H。下面的代码是利用监控端口61H的PB4来产生延迟时间的,它适用于所有的286、386、PentiumPC及兼容机。请指出该程序的延迟时间是多少?MOVDL,200BACK:MOVCX,16572WAIT:INAL,61HANDAL,10HCMPAL,AHJEWAITMOVAH,ALLOOPWAITDECDLJNZBACK答:该程序的延迟时间是200×16572×15.08μs=49981152μs≈50s。在PC机上编写乐曲程序“HappyBirthday”,乐曲的音符及音频如下:歌词音符音频节拍歌词音符音频节拍歌词音符音频节拍hapC2621/2dayC2621soD2943pyC2621/2toG3921hapBb4661/2birthD2941youF3492pyBb4661/2dayC2621hapC2621/2birthA4401toF3491pyC2621/2dayC2621youE3302birthD2941toG3921hapC2621/2dayA4401youF3492pyC2621/2dearF3491birthD2941soE3301答:程序如下:TITLEMUSIC—Amusicof‘HappyBirthday’;连接时需加上GENSOUND程序EXTRNSOUNDF:FAR;SOUNDF是外部过程——通用发声程序;******************************************STACKSEGMENTPARASTACK‘STACK’;定义堆栈段DB64DUP(‘STACK…’)STACKENDS;以上定义堆栈段;******************************************DSEGSEGMENTPARA‘DATA’;定义数据段MUS_FREQDW262,262,294,262,349,330,262,262,294,262,392,349,262,262DW294,440,349,330,294,466,466,440,262,392,349,-1MUS_TIMEDW25,25,50,50,50,100DW25,25,50,50,50,100DW25,25,50,50,50,50,150DW25,25,50,50,50,100DSEGENDS;以上定义数据段;******************************************CSEGSEGMENTPARA‘CODE’;定义代码段ASSUMECS:CSEG,DS:DSEG,SS:STACKMUSICPROCFARPUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值LEASI,MUS_FREQ;取发声的频率(音阶)表首地址LEABP,MUS_TIME;取发声的节拍(时间)表首地址FREQ:MOVDI,[SI];读取频率值CMPDI,-1;歌曲结束了吗?JEEND_MUSMOVBX,DS:[BP];读取节拍CALLSOUNDF;调通用发声子程序ADDSI,2ADDBP,2JMPFREQEND_MUS:RET;返回DOSMUSICENDPCSEGENDS;以上定义代码段;******************************************ENDMUSIC;汇编语言源程序结束以下是SOUNDF——外部的通用发声子程序(教材392页)TITLESOUNDF——通用发声子程序;******************************************PUBLICSOUNDF;定义为公共过程;******************************************CSEG1SEGMENTPARA‘CODE’;定义代码段ASSUMECS:CSEG1SOUNDFPROCFARPUSHAXPUSHBXPUSHCXPUSHDXPUSHDIMOVAL,0B6H;写定时器8253的工作方式 5162dbd488c339375742f5ffddba7d7a.doc-58-OUT43H,ALMOVDX,12H;根据频率求8253的计数值,即533H*896/freqMOVAX,533H*896;(DX),(AX)=123280H=533H*896DIVDI;(DI)=freqOUT42H,AL;向8253送计数值MOVAL,AHOUT42H,ALINAL,61H;取8255的PB口当前内容,并保护MOVAH,ALORAL,3;开始发声,PB1=1,PB0=1OUT61H,ALWAIT1:MOVCX,663;延时(BX)×10msCALLWAITFMOVAL,AHANDAL,0FCH;停止发声,PB1=0,PB0=0OUT61H,ALPOPDIPOPDXPOPCXPOPBXPOPAXRETSOUNDFENDP;******************************************WAITFPROCNEARPUSHAXWAITF1:INAL,61HANDAL,10HCMPAL,AHJEWAITF1MOVAH,ALLOOPWAITF1POPAXRETWAITFENDPCSEG1ENDS;以上定义代码段;******************************************END编写用键盘选择计算机演奏歌曲的程序。首先在屏幕上显示出歌曲名单如下:AMUSIC1BMUSIC2CMUSIC3当从键盘上输入歌曲序号A,B或C时,计算机则演奏所选择的歌曲,当在键盘上按下0键时,演奏结束。答:程序段如下:MUS_LSTDB‘AMUSIC1’,0DH,0AHDB‘BMUSIC2’,0DH,0AHDB‘CMUSIC3’,0DH,0AHDB‘0END’,0DH,0AH,‘$’┇MOVAH,09;显示字符串的DOS功能调用LEADX,MUS_LISTINT21HINPUT:MOVAH,1;键盘输入一个字符的DOS功能调用INT21HCMPAL,‘0’;结束演奏吗?JEEXITORAL,00100000B;变为小写字母CMPAL,‘a’;演奏歌曲a吗?JNZB0CALLMUSIC1;去演奏歌曲AJMPINPUTB0:CMPAL,‘b’;演奏歌曲b吗?JNZC0CALLMUSIC2;去演奏歌曲BJMPINPUTC0:CMPAL,‘c’;演奏歌曲c吗?JNZINPUTCALLMUSIC3;去演奏歌曲CJMPINPUTEXIT:RET;返回习题写出文件代号式磁盘存取操作的错误代码:(1)非法文件代号(2)路径未发现(3)写保护磁盘答:错误代码为:(1)06(2)03(4)19使用3CH功能建立一文件,而该文件已经存在,这时会发生什么情况?答:此操作将文件长度置为0,写新文件,原文件内容被清除。从缓冲区写信息到一个文件,如果没有关闭文件,可能会出现什么问题?答:文件结尾的部分信息就没有被写入磁盘,从而造成写入的文件不完整。下面的ASCIZ串有什么错误?PATH_NAMEDB‘C:PROGRAMSTEST.DAT’答:此ASCIZ串的最后少了一个全0字节,应改为:PATH_NAMEDB‘C:PROGRAMSTEST.DAT’,0下面为保存文件代号定义的变量有什么错误?FILE_HNDLDB?答:文件代号是字类型,因此应改为:FILE_HNDLDW?在ASCPATH字节变量中为驱动器D的文件PATIENT.LST,请定义ASCIZ串。答:ASCPATHDB‘D:PATIENT.LST’,0 5162dbd488c339375742f5ffddba7d7a.doc-58-对11.6题中的文件,它的每个记录包含:病例号(patientnumber):5字符,姓名(name):20字符,城市(city):20字符,街道(streetaddress):20字符,出生年月(mmddyy):6字符,性别(M/Fcode):1字符,病房号(roomnumber):2字符,床号(bednumber):2字符,(1)定义病人记录的各个域(2)定义保存文件代号的变量FHANDLE(3)建文件(4)把PATNTOUT中的记录写入(5)关文件(6)以上文件操作包括测试错误答:(1)PATNTOUTEQUTHISBYTEpatientDB5DUP(?)nameDB20DUP(?)cityDB20DUP(?)streetDB20DUP(?)mmddyyDB6DUP(?)M_FcodeDB?roomDB2DUP(?)bedDB2DUP(?),0AH,0DHCOUNT=$-PATNTOUT;记录长度(2)FHANDLEDW?(3)MOVAH,3CH;建文件功能MOVCX,00;普通文件属性LEADX,ASCPATHINT21HJCERRORMOVFHANDLE,AX;保存文件代号(4)MOVAH,40H;写文件功能MOVBX,FHANDLE;取文件代号MOVCX,COUNT;记录长度LEADX,PATNTOUT;记录的首地址INT21HJCERRORCMPAX,COUNT;所有的字节都写入了吗?JNEERROR1(5)MOVAH,3EH;关闭文件功能MOVBX,FHANDLE;取文件代号INT21HJCERROR(6)文件操作的测试错误已包括在(3)、(4)、(5)的操作中。对11.7题的文件,用文件代号式编写一个完整的读文件程序,读出的每个记录存入PATNTIN并在屏幕上显示。答:程序如下:TITLEREADDISP.EXE;利用文件代号式顺序读文件程序;Readdiskrecordscreatedbyhancreat;-------------------------------------------------------------.modelsmall.stack100h.dataendcdedb0;结束处理指示fhandledw?patntindb80DUP(‘’);DTAascpathdb‘d:patient.lst’,0openmsgdb‘***openerror***’,0dh,0ahreadmsgdb‘***readerror***’,0dh,0ahrowdb0;-------------------------------------------------------------.codebeginprocfarmovax,@datamovds,axmoves,axmovax,0600hcallscreen;清屏callcurs;设置光标callopenh;打开文件,设置DTAcmpendcde,0;打开错误吗?jnza0;错误,转结束contin:callreadh;读磁盘记录cmpendcde,0;读错误吗?jnza0;错误,转结束calldisph;没错,显示记录jmpcontina0:movax,4c00h;退出程序,返回DOSint21hbeginendp;-------------------------------------------------------------;打开文件openhprocnearmovah,3dhmoval,0leadx,ascpathint21hjcb1;打开错误吗?movfhandle,ax;没有错,保存文件代号retb1:movendcde,01;打开错误,指示结束处理leadx,openmsgcallerrm;显示出错信息retopenhendp 5162dbd488c339375742f5ffddba7d7a.doc-58-;-------------------------------------------------------------;读磁盘记录readhprocnearmovah,3fhmovbx,fhandlemovcx,80leadx,patntinint21hjcc1;读错误吗?cmpax,0;文件已读完吗?jec2;读完,退出retc1:leadx,openmsg;读错误callerrm;显示出错信息c2:movendcde,01;读错误或文件读完,指示结束处理retreadhendp;-------------------------------------------------------------;显示记录disphprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,80leadx,patntinint21hcmprow,24;已到屏幕底部吗?jaed1;已到屏幕底部,退出incrowretd1:movax,0601hcallscreen;屏幕上卷一行callcurs;设置光标retdisphendp;-------------------------------------------------------------;屏幕上卷screenprocnear;入口参数为axmovbh,1eh;设置颜色movcx,0;屏幕左上角movdx,184fh;屏幕右下角int10hretscreenendp;-------------------------------------------------------------;设置光标cursprocnearmovah,2;设置光标movbh,0movdh,row;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------endbegin编写建立并写入磁盘文件的程序。允许用户从键盘键入零件号(3字符),零(配)件名称(12字符),单价(1个字)。程序使用文件代号式建立含有这些信息的文件。注意要把单价从ASCII码转换为二进制数。下面是输入的例子:part#Descriptionpricepart#Descriptionprice023Assemblers00315024Linkages00430027Compilers00525049Compressors00920114Extractors11250117Haulers00630122Lifters10520124Processors21335127Labtlers00960232Bailers05635237Grinders08250999000答:程序如下:TITLEHANCREAT.EXE;利用文件代号式建立文件程序;-------------------------------------------------------------.modelsmall.stack100h.dataprompt1db"PleaseinputPart#:$";提示输入零件号prompt2db"PleaseinputDescription:$";提示输入零件名称prompt3db"PleaseinputPrice:$";提示输入单价maxlendb13;最大输入长度,输入字符串功能的缓冲区actlendb?;实际输入长度bufferdb13DUP("");输入字符串缓冲区crlfdb0dh,0ah,"$"pathnamedb"filename.lst",0handledw?dtadb19DUP("");DTA 5162dbd488c339375742f5ffddba7d7a.doc-58-errcdedb0;错误处理指示opnmsgdb"***openerror***",0dh,0ahwrtmsgdb"***writeerror***",0dh,0ah;-------------------------------------------------------------.codebeginprocfarmovax,@datamovds,axmoves,axmovax,0600hcallscren;清屏callcurs;设置光标callcreath;建立文件cmperrcde,0;建立错误吗?jnza0;错误,转结束contin:callproch;记录处理cmpactlen,0;输入的字符串长度为0,结束输入吗?jnecontin;不结束,继续callclseh;结束输入,关闭文件a0:movax,4c00h;退出程序,返回DOSint21hbeginendp;-------------------------------------------------------------;建立文件creathprocnearmovah,3chmovcx,0;普通属性leadx,pathnameint21hjcbbb;建立文件错误吗?movhandle,ax;没有错,保存文件代号retbbb:leadx,opnmsg;建立文件错误callerrm;显示出错信息retcreathendp;-------------------------------------------------------------;接收输入prochprocnearcldleadi,dta;在di中设置dta的首地址leadx,prompt1;输入零件号movbx,3;零件号最多3个字符callin_procjcexit;没有输入,结束leadx,prompt2;输入零件名称movbx,12;零件名称最多12个字符callin_procjcexit;没有输入,结束leadx,prompt3;输入单价movbx,5;零件单价最多5个十进制字符(相当于一个二进制字)callin_proccalldec_bin;将十进制的单价转换为二进制的单价movwordptr[dta+17],0a0dh;在DTA的最后插入回车换行符callwrith;用文件代号法写记录exit:retprochendp;-----------------------------------------------------------------;输入字符串子程序in_procprocnearmovah,09h;显示提示信息int21hpushdileadi,buffer;在buffer中填入空格符movcl,maxlenmovch,0moval,""repstosbpopdimovah,0ah;输入字符串leadx,maxlenint21hcalldisp_crlfcmpactlen,0;实际输入字符数=0,则没有输入,结束jeend_inpushdileadi,buffer;在buffer的后面填入空格符moval,actlenmovah,0adddi,axmovcl,maxlenmovch,0moval,actlensubcl,almoval,""repstosbpopdileasi,buffer;将buffer缓冲区内容送入dta 5162dbd488c339375742f5ffddba7d7a.doc-58-movcx,bxrepmovsb;将输入内容送入dtaclc;有输入字符,返回(cf)=0jmpin_endend_in:stc;没有输入字符,返回(cf)=1in_end:retin_procendp;-----------------------------------------------------------------;将十进制的单价转换为二进制的单价子程序dec_binprocnearmovbx,0movsi,0movcx,5transfer:moval,buffer[si];从十进制的高位到低位取数cmpal,0dh;是回车吗?jedec_bin1cmpal,"";是空格吗?jedec_bin1andal,0fh;将ascii码转换为十进制数movah,0pushcxxchgax,bx;十进制数高位×10+低位=二进制数movcx,10mulcxxchgax,bxaddbx,ax;转换的二进制数在(bx)中popcxincsilooptransferdec_bin1:movwordptr[dta+15],bx;存入单价到dta中的单价位置retdec_binendp;-----------------------------------------------------------------;用文件代号法写记录writhprocnearmovah,40hmovbx,handlemovcx,19leadx,dtaint21hjncddd;写文件错误吗?leadx,wrtmsgcallerrm;显示出错信息movactlen,0ddd:retwrithendp;-----------------------------------------------------------------;用文件代号法关闭文件clsehprocnearmovdta,1ah;写文件结束符1ahcallwrithmovah,3ehmovbx,handleint21hretclsehendp;-------------------------------------------------------------;屏幕上卷screnprocnear;入口参数为axmovbh,1eh;设置颜色movcx,0;屏幕左上角movdx,184fh;屏幕右下角int10hretscrenendp;-------------------------------------------------------------;设置光标cursprocnearmovah,2;设置光标movbh,0movdh,0;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hmoverrcde,01;错误代码置1reterrmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09h 5162dbd488c339375742f5ffddba7d7a.doc-58-int21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin;汇编语言源程序结束编写一个程序使用文件代号式读出并显示11.9题建立的文件。注意,要把二进制数表示的单价转换为ASCII码。答:用文件代号式读出并显示文件,程序如下:TITLEHANDREAD.EXE;利用文件代号式顺序读并显示文件程序;Readdiskrecordscreatedbyhancreat;-------------------------------------------------------------.modelsmall.stack100h.dataendcdedb0;结束处理指示crlfdb0dh,0ah,"$"pathnamedb"filename.lst",0messagedb"Part#DescriptionPrice",0dh,0ah,"$"handledw?tacklinedb"|$"dtadb19DUP("");DTAerrcdedb0;错误处理指示opnmsgdb"***openerror***",0dh,0ahreadmsgdb"***readerror***",0dh,0ahrowdb0;-------------------------------------------------------------.codebeginprocfarmovax,@datamovds,axmoves,axmovax,0600hcallscreen;清屏callcurs;设置光标leadx,message;显示标题movah,09hint21hincrowcallopenh;打开文件,设置DTAcmpendcde,0;打开错误吗?jnza0;错误,转结束contin:callreadh;读磁盘记录cmpendcde,0;读错误吗?jnza0;错误,转结束calldisph;没错,显示记录jmpcontina0:movax,4c00h;退出程序,返回DOSint21hbeginendp;-------------------------------------------------------------;打开文件openhprocnearmovah,3dhmoval,0leadx,pathnameint21hjcbbb;打开错误吗?movhandle,ax;没有错,保存文件代号retbbb:movendcde,01;打开错误,指示结束处理leadx,readmsgcallerrm;显示出错信息retopenhendp;-------------------------------------------------------------;读磁盘记录readhprocnearmovah,3fhmovbx,handlemovcx,19leadx,dtaint21hjcc1;读错误吗?cmpax,0;文件已读完吗?jec2;读完,退出cmpdta,1ah;文件结束符吗?Jec2retc1:leadx,opnmsg;读错误callerrm;显示出错信息c2:movendcde,01;读错误或文件读完,指示结束处理retreadhendp;-------------------------------------------------------------;显示记录disphprocnearleadx,tackline;显示输出“|”movah,09h 5162dbd488c339375742f5ffddba7d7a.doc-58-int21hmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,3leadx,dtaint21hleadx,tackline;显示输出“|”movah,09hint21hmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,12leadx,dta+3int21hleadx,tackline;显示输出“|”movah,09hint21hmovsi,wordptr[dta+15]callbin_dec;转换为十进制数显示leadx,tackline;显示输出“|”movah,09hint21hcalldisp_crlfcmprow,24;已到屏幕底部吗?jaeddd;已到屏幕底部,退出incrowretddd:movax,0601hcallscreen;屏幕上卷一行callcurs;设置光标retdisphendp;-----------------------------------------------------------------;将二进制的单价转换为十进制的单价并显示子程序bin_decprocnearpushcxmovcx,10000dcalldec_div;调除法并显示输出子程序movcx,1000dcalldec_divmovcx,100dcalldec_divmovcx,10dcalldec_divmovcx,1dcalldec_divpopcxretbin_decendp;--------------------------------------------------------------------------;除法并显示输出子程序dec_divprocnearmovax,simovdx,0divcxmovsi,dx;余数保存在(si)中作下一次的除法movdl,al;商(在00h~09h范围内)送(dl)adddl,30h;转换为0~9的ascii码movah,02h;显示输出int21hretdec_divendp;-----------------------------------------------------------------;屏幕上卷screenprocnear;入口参数为axmovbh,1eh;设置颜色movcx,0;屏幕左上角movdx,184fh;屏幕右下角int10hretscreenendp;-------------------------------------------------------------;设置光标cursprocnearmovah,2;设置光标movbh,0movdh,row;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hret 5162dbd488c339375742f5ffddba7d7a.doc-58-errmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin对11.9题建立的文件按下面的要求编写程序:(1)把所有的记录读入内存的数据缓冲区TABLE;(2)显示字符串提示用户输入零(配)件号及其数量;(3)按零件搜索TABLE;(4)如果发现所要求的零件,用它的单价计算出总价(单价×数量);(5)显示零(配)件说明及总价值。答:程序如下:TITLEREAD11.EXE;利用文件代号式读并计算显示程序;Readdiskrecordscreatedbyhancreat;-------------------------------------------------------------.modelsmall.stack100h.dataendcdedb0;结束处理指示pathnamedb"filename.lst",0in_mes1db"请输入3位数的零件号Part#:","$"in_mes2db"请输入该零件的数量:","$"out_mes1db"输入的不是数字!请重新输入数字:’,"$"out_mes2db"输入的零件号不存在!请重新输入3位数的零件号Part#:","$"in_bufferdb6,?,6dup(20h);输入缓冲区messagedb"Part#DescriptionSum_Price",0dh,0ah,"$"tacklinedb"|$"sum_pricedw0,0decimaldb10DUP(0),‘$’crlfdb0dh,0ah,"$"handledw?tabledb19*100DUP("");table,足够大errcdedb0;错误处理指示opnmsgdb"***openerror***",0dh,0ahreadmsgdb"***readerror***",0dh,0ah;-------------------------------------------------------------.codebeginprocfarmovax,@datamovds,axmoves,axmovax,0600hcallscreen;清屏callcurs;设置光标callopenh;打开文件,设置TABLEcmpendcde,0;打开错误吗?jnza0;错误,转结束callreadh;读磁盘记录cmpendcde,0;读错误吗?jnza0;错误,转结束callin_Part;没错,输入零件号和零件数量a0:movax,4c00h;退出程序,返回DOSint21hbeginendp;-------------------------------------------------------------;打开文件openhprocnearmovah,3dhmoval,0leadx,pathnameint21hjcbbb;打开错误吗?movhandle,ax;没有错,保存文件代号retbbb:movendcde,01;打开错误,指示结束处理leadx,opnmsgcallerrm;显示出错信息retopenhendp;-------------------------------------------------------------;读磁盘记录readhprocnearmovah,3fhmovbx,handlemovcx,19*100;准备读入的字节数leadx,tableint21hjcc1;读错误吗?cmpax,0;文件已读完吗?jec2;读完,退出cmptable,1ah;文件结束符吗?Jec2movbp,ax;读成功则在AX中返回实际读入的字节数存入bp 5162dbd488c339375742f5ffddba7d7a.doc-58-retc1:leadx,readmsg;读错误callerrm;显示出错信息c2:movendcde,01;读错误或文件读完,指示结束处理retreadhendp;-------------------------------------------------------------;输入零件号和零件数量in_Partprocnearleadx,in_mes1;显示提示信息,提示输入零件号in_Part1:callinput;输入数据cmpin_buffer+1,3;输入的零件号个数是3位吗?leadx,out_mes2;显示提示信息,提示重新输入零件号jnein_Part1cldmovax,bp;取实际读入文件的字节数movcl,19;每个记录的长度为19个字符divcl;计算实际读取的记录数在al中movbl,almovbh,0;从第0个记录开始顺序查找in_Part2:leasi,in_buffer+2;查找零件号对应的零件leadi,tablemoval,19mulbhadddi,ax;计算某个记录的首地址movwordptrdecimal,di;保存首地址movcx,3repecmpsbjein_Part3;找到对应的零件incbh;找下一个记录cmpbh,bljbin_Part2jmpin_Part1;未找到对应的零件重新输入in_Part3:leadx,in_mes2;显示提示信息,提示输入零件数量callinput;输入数据calldec_bin;将输入数据转换为二进制数,在bx中movdi,wordptrdecima;di指向该记录的首地址movax,[di+15];取单价mulbx;总价格在(dx),(ax)中movsum_price,axmovsum_price+2,dxcalldisp_rec;显示信息retin_Partendp;-------------------------------------------------------------;输入数据inputprocnearinput1:movah,09h;显示字符串int21hmovah,0ah;输入字符串leadx,in_bufferint21hleadx,out_mes1;显示提示信息movcl,in_buffer+1cmpcl,0;输入的数字个数为0吗?jzinput1movch,0movbx,2input2:moval,in_buffer[bx];输入的是数字0~9吗?cmpal,‘0’jbinput1cmpal,‘9’jainput1incbxloopinput2retinputendp;-------------------------------------------------------------;将十进制数转换为二进制数子程序dec_binprocnearmovbx,0movsi,2movcl,in_buffer+1movch,0transfer:moval,in_buffer[si];从十进制的高位到低位取数andal,0fh;将ascii码转换为十进制数movah,0pushcxxchgax,bx;十进制数高位×10+低位=二进制数movcx,10mulcxaddbx,ax;转换的二进制数在(bx)中popcxincsilooptransferretdec_binendp;-----------------------------------------------------------------;显示记录 5162dbd488c339375742f5ffddba7d7a.doc-58-disp_recprocnearcalldisp_crlfleadx,message;显示标题movah,09hint21hleadx,tackline;显示输出“|”movah,09hint21hmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,3;显示3位数的零件号movdx,wordptrdecima;dx指向该记录的首地址int21hleadx,tackline;显示输出“|”movah,09hint21hmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,12;显示12位的零件说明movdx,wordptrdecima;dx指向该记录的首地址adddx,3int21hleadx,tackline;显示输出“|”movah,09hint21hcallbin_dec;总价格转换为十进制数显示leadx,tackline;显示输出“|”movah,09hint21hcalldisp_crlfretdisp_recendp;-----------------------------------------------------------------;4字节二进制数转换为10进制子程序bin_decprocnearmovbx,0;10字节的bcd码单元清0movcx,10bin_dec1:movdecimal[bx],0incbxloopbin_dec1movcx,4*8;4字节二进制数共4*8=32位bin_dec2:movbx,10-1;计算(((a31*2+a30)*2+a29)...)*2+a0shlwordptr[sum_price],1;4字节二进制数左移1位rclwordptr[sum_price+2],1pushcxmovcx,10bin_dec3:moval,decimal[bx];计算(...)*2+ai,ai由进位位带入adcal,alaaa;非压缩bcd码加法调整movdecimal[bx],aldecbxloopbin_dec3popcxloopbin_dec2calldispretbin_decendp;--------------------------------------------------------------------------dispprocnear;显示输出子程序movcx,10movbx,0disp1:adddecimal[bx],30h;变为ascii码incbxloopdisp1movcx,10;下面5条指令是为了不显示数据左边的“0”cldleadi,decimalmoval,30h;30h为“0”的ascii码repescasbdecdimovdx,dimovah,09hint21hretdispendp;disp子程序结束;---------------------------------------------------------------------------;屏幕上卷screenprocnear;入口参数为axmovbh,1eh;设置颜色movcx,0;屏幕左上角movdx,184fh;屏幕右下角int10hretscreenendp;-------------------------------------------------------------;设置光标cursprocnearmovah,2;设置光标movbh,0 5162dbd488c339375742f5ffddba7d7a.doc-58-movdh,0;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin用随机处理记录的方式编写程序,将用户需要的零(配)件记录读取到TABLE,并根据键入的数量,计算出总价值,然后显示出零(配)件说明及总价值。答:程序如下:TITLEREAD_RAN.EXE;利用文件代号式随机读并计算显示程序;Readdiskrecordscreatedbyhancreat;-------------------------------------------------------------.modelsmall.stack100h.dataendcdedb0;结束处理指示pathnamedb"filename.lst",0in_mes1db"请输入3位数的零件号Part#:","$"in_mes2db"请输入该零件的数量:","$"out_mes1db"输入的不是数字!请重新输入数字:’,"$"out_mes2db"输入的零件号不存在!请重新输入3位数的零件号Part#:","$"in_bufferdb6,?,6dup(20h);输入缓冲区messagedb"Part#DescriptionSum_Price",0dh,0ah,"$"tacklinedb"|$"sum_pricedw0,0decimaldb10DUP(0),‘$’crlfdb0dh,0ah,"$"handledw?tabledb19DUP("");tableerrcdedb0;错误处理指示opnmsgdb"***openerror***",0dh,0ahreadmsgdb"***readerror***",0dh,0ahmovmsgdb"***moveerror***",0dh,0ah;-------------------------------------------------------------.codebeginprocfarmovax,@datamovds,axmoves,axmovax,0600hcallscreen;清屏callcurs;设置光标callopenh;打开文件,设置TABLEcmpendcde,0;打开错误吗?jnza0;错误,转结束callin_Part;没错,输入零件号和零件数量a0:movax,4c00h;退出程序,返回DOSint21hbeginendp;-------------------------------------------------------------;打开文件openhprocnearmovah,3dhmoval,0leadx,pathnameint21hjcbbb;打开错误吗?movhandle,ax;没有错,保存文件代号retbbb:movendcde,01;打开错误,指示结束处理leadx,opnmsgcallerrm;显示出错信息retopenhendp;-------------------------------------------------------------;读磁盘记录readhprocnearmovah,3fhmovbx,handlemovcx,19;准备读入的字节数leadx,tableint21h 5162dbd488c339375742f5ffddba7d7a.doc-58-jcc1;读错误吗?cmpax,0;文件已读完吗?jec2;读完,退出cmptable,1ah;文件结束符吗?Jec2movbp,ax;读成功则在AX中返回实际读入的字节数存入bpretc1:movendcde,01;读错误或文件读完,指示结束处理leadx,readmsg;读错误callerrm;显示出错信息jmpc3c2:movendcde,02;读错误或文件读完,指示结束处理c3:retreadhendp;-------------------------------------------------------------;绝对移动文件读写指针mov_pointerprocnearmovah,42hmoval,0movbx,handleint21hjcd1;错误吗?retd1:leadx,movmsg;错误callerrm;显示出错信息movendcde,01;错误,指示结束处理retmov_pointerendp;-------------------------------------------------------------;输入零件号和零件数量in_Partprocnearleadx,in_mes1;显示提示信息,提示输入零件号in_Part1:callinput;输入数据cmpin_buffer+1,3;输入的零件号个数是3位吗?leadx,out_mes2;显示提示信息,提示重新输入零件号jnein_Part1cldmovcx,0;位移量的高位字movdx,0;位移量的低位字callmov_pointer;绝对移动文件读写指针到文件首in_Part2:callreadh;读磁盘记录cmpendcde,2;读文件结束吗?jein_Part1;结束,未找到对应的零件重新输入cmpendcde,1;读错误吗?jein_Part4;错误,转结束leasi,in_buffer+2;查找零件号对应的零件leadi,tablemovcx,3repecmpsbjein_Part3;找到对应的零件jmpin_Part2;找下一个零件in_Part3:leadx,in_mes2;显示提示信息,提示输入零件数量callinput;输入数据calldec_bin;将输入数据转换为二进制数,在bx中leadi,table;di指向该记录的首地址movax,[di+15];取单价mulbx;总价格在(dx),(ax)中movsum_price,axmovsum_price+2,dxcalldisp_rec;显示信息in_Part4:retin_Partendp;-------------------------------------------------------------;输入数据inputprocnearinput1:movah,09h;显示字符串int21hmovah,0ah;输入字符串leadx,in_bufferint21hleadx,out_mes1;显示提示信息movcl,in_buffer+1cmpcl,0;输入的数字个数为0吗?jzinput1movch,0movbx,2input2:moval,in_buffer[bx];输入的是数字0~9吗?cmpal,‘0’jbinput1cmpal,‘9’jainput1incbxloopinput2retinputendp;-------------------------------------------------------------;将十进制数转换为二进制数子程序dec_binprocnear 5162dbd488c339375742f5ffddba7d7a.doc-58-movbx,0movsi,2movcl,in_buffer+1movch,0transfer:moval,in_buffer[si];从十进制的高位到低位取数andal,0fh;将ascii码转换为十进制数movah,0pushcxxchgax,bx;十进制数高位×10+低位=二进制数movcx,10mulcxaddbx,ax;转换的二进制数在(bx)中popcxincsilooptransferretdec_binendp;-----------------------------------------------------------------;显示记录disp_recprocnearcalldisp_crlfleadx,message;显示标题movah,09hint21hleadx,tackline;显示输出“|”movah,09hint21hmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,3;显示3位数的零件号leadx,table;dx指向该记录的首地址int21hleadx,tackline;显示输出“|”movah,09hint21hmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,12;显示12位的零件说明leadx,table;dx指向该记录的首地址adddx,3int21hleadx,tackline;显示输出“|”movah,09hint21hcallbin_dec;总价格转换为十进制数显示leadx,tackline;显示输出“|”movah,09hint21hcalldisp_crlfretdisp_recendp;-----------------------------------------------------------------;4字节二进制数转换为10进制子程序bin_decprocnearmovbx,0;10字节的bcd码单元清0movcx,10bin_dec1:movdecimal[bx],0incbxloopbin_dec1movcx,4*8;4字节二进制数共4*8=32位bin_dec2:movbx,10-1;计算(((a31*2+a30)*2+a29)...)*2+a0shlwordptr[sum_price],1;4字节二进制数左移1位rclwordptr[sum_price+2],1pushcxmovcx,10bin_dec3:moval,decimal[bx];计算(...)*2+ai,ai由进位位带入adcal,alaaa;非压缩bcd码加法调整movdecimal[bx],aldecbxloopbin_dec3popcxloopbin_dec2calldispretbin_decendp;--------------------------------------------------------------------------dispprocnear;显示输出子程序movcx,10movbx,0disp1:adddecimal[bx],30h;变为ascii码incbxloopdisp1movcx,10;下面5条指令是为了不显示数据左边的“0”cldleadi,decimalmoval,30h;30h为“0”的ascii码repescasbdecdi 5162dbd488c339375742f5ffddba7d7a.doc-58-movdx,dimovah,09hint21hretdispendp;disp子程序结束;---------------------------------------------------------------------------;屏幕上卷screenprocnear;入口参数为axmovbh,1eh;设置颜色movcx,0;屏幕左上角movdx,184fh;屏幕右下角int10hretscreenendp;-------------------------------------------------------------;设置光标cursprocnearmovah,2;设置光标movbh,0movdh,0;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin'