• 984.00 KB
  • 2022-04-29 14:13:52 发布

《汇编语言程序设计》答案(第二版)-2008.doc

  • 99页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'《汇编语言程序设计》习题参考答案《IBM-PC汇编语言程序设计》(第2版)沈美明、温冬婵编著编写时间:2008年9月18日990ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印第一章.习题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将下列二进制数转换为十六进制数和十进制数:(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.答:46H6FH72H20H65H78H61H6DH70H6CH65H2CH0AH0DH54H68H69H73H20H69H73H20H61H20H6EH75H6DH62H65H99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印72H20H33H36H39H32H2EH0AH0DH第一章.习题E5H000B0H1EH000B1H3CH000B3H2AH000B4H存储器2.2题的信息存放情况…000B2H2.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字单元的内容。34H30021HABH30022HCDH30023HEFH30024H存储器2.3题的信息存放情况12H30020H答: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。10F4010E4020F4020E4021F0031F0031FF041FF0附加段数据段堆栈段代码段2.6题的存储器分段示意图2.6在实模式下,存储器中每一段最多可有10000H个字节。如果用调试程序DEBUG的r命令在终端上显示出当前各寄存器的内容如下,请画出此时存储器分段的示意图,以及条件标志OF、SF、ZF、CF的值。C>debug-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.唯一代表存储空间中每个字节单元的地址。99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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)操作数在指令中,即立即数;(2)EA=D=7237H;(3)无EA,操作数为(BX)=637DH;(4)EA=(BX)=637DH;(5)EA=(BX)+D=0D5B4H;(6)EA=(BX)+(SI)=8E18H;(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(5)ADDAL,0B5H3.3写出把首地址为BLOCK的字数组的第6个字送到DX寄存器的指令。要求使用以下几种寻址方式:(1)寄存器间接寻址(2)寄存器相对寻址(3)基址变址寻址答:(1)MOVBX,OFFSETBLOCK99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印ADDBX,(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]FFH00H80H3.6题的作图表示10H1B00:2000H1B00:2001H1B00:2002H1B00:2003H8000:FF10H8000:FF11H?→(AL)?→(AH)3.1现有(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,BX(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.2给定(IP)=2BC0H,(CS)=0200H,位移量D=5119H,(BX)=1200H,(DS)=212AH,(224A0H)=0600H,(275B9H)=098AH,试为以下的转移指令找出转移的偏移地址。(1)段内直接寻址(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.3设当前数据段寄存器的内容为1B00H,在数据段的偏移地址2000H单元内,含有一个内容为0FF10H和8000H的指针,它们是一个16位变量的偏移地址和段地址,试写出把该变量装入AX的指令序列,并画图表示出来。MOVBX,2000HLESBX,[BX]MOVAX,ES :[BX]答:MOVBX,[2000H];图示如上所示。MOVAX,[2000H+2]MOVES,AXMOVAX,ES:[BX]3.4在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.5假定(DS)=2000H,(ES)=2100H,(SS)=1500H,(SI)=00A0H,(BX)=0100H,(BP)=0010H,数据段中变量名VAL的偏移地址为0050H,试指出下列源操作数字段的寻址方式是什么?其物理地址值是多少?(1)MOVAX,0ABH(2)MOVAX,BX(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]99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印答:(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.1在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],AX0AH00H14H00H1EH00H28H00H32H00HTABLETABLE+33.11题的TABLE存储方式3.2如TABLE为数据段中0032单元的符号名,其中存放的内容为1234H,试问以下两条指令有什么区别?指令执行完后AX寄存器的内容是什么?MOVAX,TABLELEAAX,TABLE答:MOVAX,TABLE是将TABLE单元的内容送到AX,(AX)=1234HLEAAX,TABLE是将TABLE单元的有效地址送到AX,(AX)=0032H3.3执行下列指令后AX寄存器中的内容是什么?TABLEDW10,20,30,40,50;000AH,0014H,001EH,0028H,0032HENTRYDW3┇MOVBX,OFFSETTABLEADDBX,ENTRYMOVAX,[BX]答:(AX)=1E00H(TABLE的存储方式如右图所示)3.4下列ASCII码串(包括空格符)依次存储在起始地址为CSTRING的字节单元中:CSTRINGDB‘BASEDADDRESSING’请编写指令将字符串中的第1个和第7个字符传送给DX寄存器。答:MOVDH,CSTRINGMOVDL,CSTRING+7-13.5已知堆栈段寄存器SS的内容是0FFA0H,堆栈指针寄存器SP的内容是00B0H,先执行两条把8057H和0F79H分别进栈的PUSH指令,再执行一条POP指令。试画出堆栈区和SP的内容变化过程示意图(标出存储单元的物理地址)。答:堆栈区和SP的内容变化过程示意图如下左图所示。8000H1B00:20003.14题的存储区情况2B00HX1B00:20022B00:800079H0FH57H80HFFAACHFFAB0H3.13题的堆栈区和SP的内容变化过程示意图FFAAEH←首次进栈(SP)←(SP)-2←再次进栈(SP)←(SP)-2出栈时(SP)←(SP)+299 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印3.1设(DS)=1B00H,(ES)=2B00H,有关存储单元的内容如上右图所示。请写出两条指令把字变量X装入AX寄存器。答:MOVBX,[2000H]MOVAX,ES:[BX]3.2求出以下各十六进制数与十六进制数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.3求出以下各十六进制数与十六进制数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.4写出执行以下计算的指令序列,其中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.5已知程序段如下: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,其它标志无定义99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印INT20H试问:(1)每条指令执行完后,AX寄存器的内容是什么?(2)每条指令执行完后,进位、符号和零标志的值是什么?(3)程序结束时,AX和DX的内容是什么?答:(1)见注释;(2)见注释;(3)(AX)=8D00H,(DX)=03.1下列程序段中的每条指令执行完后,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.2变量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(2)MOVAX,DATAXADDDATAY,AXMOVAX,DATAX+2ADCDATAY+2,AXMOVDATAY+4,0;用于存放进位位ADCDATAY+4,0(3)DATAX和DATAY两个字数据之和加1,结果存入BX寄存器。(4)RESULT1DW0DW0RESULT2DW0DW099 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印┇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.1写出对存放在DX和AX中的双字长数求补的指令序列。答:NEGDX也可为:NOTDXNEGAXNOTAXSBBDX,0ADDAX,1ADCDX,03.2试编写一程序求出双字长数的绝对值。双字长数在A和A+2单元中,结果存放在B和B+2单元中。答:程序段如下:MOVAX,AMOVDX,A+2CMPDX,0JNSZHENSHU;不是负数则转走NEGDXNEGAXSBBDX,0ZHENSHU:MOVB,AXMOVB+2,DXINT20H3.3假设(BX)=0E3H,变量VALUE中存放的内容为79H,确定下列各条指令单独执行后的结果。(1)XORBX,VALUE;(BX)=9AH,CF、OF都为0,AF无定义,SF=1,ZF=0,PF=199 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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.1试写出执行下列指令序列后BX寄存器的内容。执行前(BX)=6D16H。MOVCL,7SHRBX,CL答:(BX)=00DAH。3.2试用移位指令把十进制数+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.3试分析下面的程序段完成什么功能?MOVCL,04SHLDX,CLMOVBL,AHSHLAX,CLSHRBL,CLORDL,BL答:本程序段将((DX),(AX))的双字同时左移4位,即将此双字乘以10H(16)。3.4假定(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.5下列程序段执行完后,BX寄存器的内容是什么?MOVCL,3MOVBX,0B7HROLBX,1RORBX,CL答:(BX)=0C02DH。3.6假设数据段定义如下:CONAMEDB‘SPACEEXPLORERSINC.’PRLINEDB20DUP(‘’)用串指令编写程序段分别完成以下功能:(1)从左到右把CONAME中的字符串传送到PRLINE。(2)从右到左把CONAME中的字符串传送到PRLINE。(3)把CONAME中的第3和第4个字节装入AX。99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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.1编写程序段,把字符串STRING中的‘&’字符用空格符代替。STRINGDB‘ThedateisFEB&03’答:程序段如下:MOVCX,18MOVAL,‘&’CLDMOVDI,SEGSTRINGMOVES,DILEADI,STRINGREPNESCASBJNENEXTDECDIMOVES:BYTEPTR[DI],‘’;送空格符NEXT:┇3.2假设数据段中数据定义如下: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个字节中。99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印答:公共的程序段如下:MOVDI,DSMOVES,DI(1)MOVCX,132MOVAL.,‘’;空格的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.1编写一程序段:比较两个5字节的字符串OLDS和NEWS,如果OLDS字符串不同于NEWS字符串则执行NEW_LESS;否则顺序执行程序。答:程序段如下:MOVCX,5CLDMOVDI,SEGOLDSMOVDS,DIMOVES,DILEASI,OLDSLEADI,NEWSREPECMPSBJNENEW_LESS99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印┇NEW_LESS:┇3.1假定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.2试分析下列程序段:ADDAX,BXJNOL1JNCL2SUBAX,BXJNCL3JNOL4JMPSHORTL5如果AX和BX的内容给定如下:AXBX(1)147BH80DCH(2)B568H42C8H(3)42C8H608DH(4)D023H9FD0H(5)94B7HB568H问该程序分别在上面5种情况下执行后,程序转向哪里?答:(1)转向L1(2)转向L1(3)转向L2(4)转向L5;因为加法指令后AX中已经是6FF3H(5)转向L5;因为加法指令后AX中已经是4A14H3.3指令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、JLE99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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.1假设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.2要求测试在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.3在下列程序的括号中分别填入如下指令:(1)LOOPL20(2)LOOPEL20(3)LOOPNEL20试说明在三种情况下,当程序执行完后,AX、BX、CX、DX四个寄存器的内容分别是什么?TITLEEXLOOP.COMCODESGSEGMENTASSUMECS:CODESG,DS:CODSEG,SS:CODSEGORG100HBEGIN:MOVAX,01MOVBX,02MOVDX,03MOVCX,0499 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印L20: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.1考虑以下的调用序列:(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;(8)从SUBA返回MAIN;(9)从MAIN调用SUBC(返回的段地址为1000,返回的偏移地址为0600);请画出每次调用及返回时的堆栈状态。答:每次调用及返回时的堆栈状态图如下所示: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调用SUBC3.2假设(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.3假设(EAX)=9823F456H,(ECX)=1F23491H,(BX)=348CH,(SI)=2000H,(DI)=4044H。在DS段中从偏移地址4044H单元开始的4个字节单元中,依次存放的内容为92H,6DH,0A2H和4CH,试问下列各条指令执行完后的目的地址及其中的内容是什么?99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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.1说明下列指令的操作(1)PUSHAX;将(AX)压入堆栈(2)POPESI;将堆栈中的双字弹出到ESI寄存器中(3)PUSH[BX];将((BX))对应存储单元中的字压入堆栈(4)PUSHAD;32位通用寄存器依次进栈(5)POPDS;将堆栈中的字弹出到DS寄存器中(6)PUSH4;将立即数4以字的方式压入堆栈答:见注释。3.2请给出下列各指令序列执行完后目的寄存器的内容。(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.3请给出下列各指令序列执行完后目的寄存器的内容。(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.4请给出下列指令序列执行完后EAX和EBX的内容。MOVECX,307F455HBSFEAX,ECX;(EAX)=0DBSREBX,ECX;(EBX)=25D答:见注释。3.5请给出下列指令序列执行完后AX和DX的内容。MOVBX,98HBSFAX,BX;(AX)=3DBSRDX,BX;(DX)=7D答:见注释。3.6请编写一程序段,要求把ECX、EDX和ESI的内容相加,其和存入EDI寄存器中(不考虑溢出)。答:MOVEDI,0也可为:MOVEDI,ECXADDEDI,ECXADDEDI,EDXADDEDI,EDXADDEDI,ESIADDEDI,ESI3.7请说明IMULBX,DX,100H指令的操作。99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印答:(BX)←(DX)*100H3.1试编写一程序段,要求把BL中的数除以CL中的数,并把其商乘以2,最后的结果存入DX寄存器中。答:MOVAL,BLMOVAH,0;假定为无符号数,否则用CBW指令即可DIVCLMOVAH,0SHLAX,1MOVDX,AX3.2请说明JMPDI和JMP[DI]指令的区别。答:JMPDI是转移到以(DI)内容为偏移地址的单元去执行指令;JMP[DI]是转移到以(DI)间接寻址的内存单元内容为偏移地址的单元去执行指令。3.3试编写一程序段,要求在长度为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.4请用图表示ENTER16,0所生成的堆栈帧的情况。答:答案见右图。第一章.习题4.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定义的变量)99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(1)CMP15,BX;错,立即数不能作为目的操作数(2)CMPOP1,25(3)CMPOP1,OP2;错,不能都是存储器操作数(4)CMPAX,OP1;错,类型不匹配,应为CMPax,wordptrop1答:见注释。4.1假设下列指令中的所有标识符均为类型属性为字的变量,请指出下列哪些指令是非法的?它们的错误是什么?(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.2假设VAR1和VAR2为字变量,LAB为标号,试指出下列指令的错误之处:(1)ADDVAR1,VAR2;不能都是存储器操作数(2)SUBAL,VAR1;数据类型不匹配(3)JMPLAB[SI];LAB是标号而不是变量名,后面不能加[SI](4)JNZVAR1;VAR1是变量而不是标号(5)JMPNEARLAB;应使用NEARPTR答:见注释。4.3画图说明下列语句所分配的存储空间及初始化的数据值。(1)BYTE_VARDB‘BYTE’,12,-12H,3DUP(0,?,2DUP(1,2),?)(2)WORD_VARDW5DUP(0,1,2),?,-5,‘BY’,‘TE’,256H答:答案如下图所示。4.4试列出各种方法,使汇编程序把5150H存入一个存储器字中(如:DW5150H)。4.5题答案42H59H54H45H0DHEEH00H-01H02H01H02H-00H-01H02H01H02H-BYTE_VAR00H00H01H00H02H00H┇┇┇--FBHFFH00H59H42H45H54H56H02HWORD_VAR将上面内容再重复4次答:DW5150HDB50H,51HDB‘PQ’DW‘QP’ORG5150HDW$4.5请设置一个数据段DATASG,其中定义以下字符变量或数据变量。(1)FLD1B为字符串变量:‘personalcomputer’;(2)FLD2B为十进制数字节变量:32;(3)FLD3B为十六进制数字节变量:20;(4)FLD4B为二进制数字节变量:01011001;(5)FLD5B为数字的ASCII字符字节变量:32654;(6)FLD6B为10个零的字节变量;(7)FLD7B为零件名(ASCII码)及其数量(十进制数)的表格:PART120PART250PART314(8)FLD1W为十六进制数字变量:FFF0;(9)FLD2W为二进制数的字变量:01011001;99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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.1假设程序中的数据定义如下:PARTNODW?PNAMEDB16DUP(?)COUNTDD?PLENTHEQU$-PARTNO问PLENTH的值为多少?它表示什么意义?答:PLENTH=22=16H,它表示变量PARTNO、PNAME、COUNT总共占用的存储单元数(字节数)。4.2有符号定义语句如下:BUFFDB1,2,3,‘123’EBUFFDB0LEQUEBUFF-BUFF问L的值是多少?答:L=6。4.3假设程序中的数据定义如下: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.4试写出一个完整的数据段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_SEGENDS99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;----------------------------------------------------------------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.1给出等值语句如下:ALPHAEQU100BETAEQU25GAMMAEQU2下列表达式的值是多少?(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.2对于下面的数据定义,三条MOV指令分别汇编成什么?(可用立即数方式表示)TABLEADW10DUP(?)TABLEBDB10DUP(?)TABLECDB‘1234’┇MOVAX,LENGTHTABLEA;汇编成MOVAX,000AHMOVBL,LENGTHTABLEB;汇编成MOVBL,000AHMOVCL,LENGTHTABLEC;汇编成MOVCL,0001H答:见注释。4.3对于下面的数据定义,各条MOV指令单独执行后,有关寄存器的内容是什么?FLDBDB?TABLEADW20DUP(?)99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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.1指出下列伪操作表达方式的错误,并改正之。(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.2按下面的要求写出程序的框架(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.399 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印写一个完整的程序放在代码段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;以上定义附加段;----------------------------------------------------------------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.1请说明表示程序结束的微操作和结束程序执行的语句之间的差别。它们在源程序中应如何表示?答:表示程序结束的微操作是指示汇编程序MASM结束汇编的标志,在源程序中用END表示;结束程序执行的语句是结束程序运行而返回操作系统的指令,在源程序中有多种表示方法,比如INT20H或MOVAX,4C00HINT21H以及RET等。4.2试说明下述指令中哪些需要加上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.1试编写一个汇编语言程序,要求对键盘输入的小写字母用大写字母显示出来。答:程序段如下:99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印BEGIN:MOVAH,1;从键盘输入一个字符的DOS调用INT21HCMPAL,‘a’;输入字符<‘a’吗?JBSTOPCMPAL,‘z’;输入字符>‘z’吗?JASTOPSUBAL,20H;转换为大写字母,用ANDAL,11011111B也可MOVDL,AL;显示一个字符的DOS调用MOVAH,2INT21HJMPBEGINSTOP:RET5.1编写程序,从键盘接收一个小写字母,然后找出它的前导字符和后续字符,再按顺序显示这三个字符。答:程序段如下:BEGIN:MOVAH,1;从键盘输入一个字符的DOS调用INT21HCMPAL,‘a’;输入字符<‘a’吗?JBSTOPCMPAL,‘z’;输入字符>‘z’吗?JASTOPDECAL;得到前导字符MOVDL,AL;准备显示三个字符MOVCX,3DISPLAY:MOVAH,2;显示一个字符的DOS调用INT21HINCDLLOOPDISPLAYSTOP:RET5.2将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:RET5.3试编写一程序,要求比较两个字符串STRING1和STRING2所含字符是否完全相同,若相同则显示‘MATCH’,若不相同则显示‘NOMATCH’。答:程序如下:DSEGSEGMENTSTRING1DB‘Iamastudent.’99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1试编写一程序,要求能从键盘接收一个个位数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:RET5.2编写程序,将一个包含有20个数据的数组M分成两个数组:正数数组P和负数数组N,并分别把这两个数组中数据的个数显示出来。答:程序如下:DSEGSEGMENTCOUNTEQU20ARRAYDW20DUP(?);存放数组COUNT1DB0;存放正数的个数99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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,2LOOPBEGIN1LEADX,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调用99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印INT21HRETDISPLAYENDP;显示子程序结束CSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1试编写一个汇编语言程序,求出首地址为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:RET5.2把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:RET5.3试编写一个汇编语言程序,要求从键盘接收一个四位的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’的处理99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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,1RCLDL,1ORDL,30HMOVAH,2;进行显示INT21HLOOPDISPSTOP:RET5.1设有一段英文,其字符变量名为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单元中99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印DONE1:ROLAX,CLMOVDX,AXANDDL,0FH;取一位16进制数ADDDL,30HCMPDL,39HJLESTOREADDDL,07H;是“A~F”所以要加7STORE:MOV[BX],DL;转换结果存入DAT单元中INCBXDECCHJNZDONE1DISPLAY:LEADX,DISP;显示字符串程序(将DISP和DAT一起显示)MOVAH,09HINT21HRETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1从键盘输入一系列以$为结束符的字符串,然后对其中的非数字字符计数,并显示出计数结果。答:程序段如下: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进制数显示程序段(省略)5.2有一个首地址为MEM的100D字数组,试编制程序删除数组中所有为0的项,并将后续项向前压缩,最后将数组的剩余部分补上0。答:程序如下:DSEGSEGMENTMEMDW100DUP(?)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEG99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印START: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;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1在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:RET99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1在首地址为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;计算一个数的出现次数JNEADDRINCDXADDSI,2LOOPCOMPADDR:CMPDX,COUNT;此数出现的次数最多吗?JLEDONEMOVCOUNT,DX;目前此数出现的次数最多,记下次数MOVDATA,AX;记下此数DONE:LOOPNEXT;准备取下一个数MOVCX,COUNT;出现最多的次数存入(CX)MOVAX,DATA;出现最多的数存入(AX)RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.2数据段中已定义了一个有n个字数据的数组M,试编写一程序求出M中绝对值最大的数,把它放在数据段的M+2n单元中,并将该数的偏移地址存放在M+2(n+1)单元中。答:程序如下:DSEGSEGMENTnEQU100H;假设n=100HMDWnDUP(?)DATADW?;M+2n单元ADDRDW?;M+2(n+1)单元DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEG99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印START: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;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1在首地址为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))中99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVAX,BXMOVCX,100HIDIVCX;带符号数求平均值,放入(AX)中MOVBX,0MOVSI,0COMP:CMPAX,DATA[SI];寻找小于平均值的数JLENOINCBX;小于平均值数的个数+1NO:ADDSI,2LOOPCOMPRETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1试编制一个程序把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;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.299 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印把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;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1已知数组A包含15个互不相等的整数,数组B包含20个互不相等的整数。试编制一程序把既在A中又在B中出现的整数存放于数组C中。答:程序如下:DSEGSEGMENTADW15DUP(?)BDW20DUP(?)CDW15DUP(‘’)DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEGSTART:PUSHDS;设置返回DOSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AX;给DS赋值BEGIN:MOVSI,0MOVBX,099 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVCX,15;外循环计数器LOOP1:PUSHCXMOVCX,20;内循环计数器MOVDI,0MOVAX,A[SI];取A数组中的一个数LOOP2:CMPB[DI],AX;和B数组中的数相等吗?JNENOMOVC[BX],AX;相等存入C数组中ADDBX,2NO:ADDDI,2LOOPLOOP2ADDSI,2POPCXLOOPLOOP1RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1设在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;以上定义代码段;--------------------------------------------------------------------------ENDSTART99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印5.1试编写一程序,要求比较数组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)用于存放所求的结果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;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.2从键盘输入一系列字符(以回车符结束),并按字母、数字、及其它字符分类计数,最后显示出这三类的计数结果。答:程序如下:DSEGSEGMENTALPHABETDB‘输入的字母字符个数为:’,‘$’NUMBERDB‘输入的数字字符个数为:’,‘$’OTHERDB‘输入的其它字符个数为:’,‘$’CRLFDB0DH,0AH,‘$’DSEGENDS;--------------------------------------------------------------------------CSEGSEGMENTMAINPROCFARASSUMECS:CSEG,DS:DSEG99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印START: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;显示回车换行INT21HRETDISPLAYENDP;--------------------------------------------------------------------------99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印BINIHEXPROCNEAR;将BX中二进制数转换为16进制数显示子程序MOVCH,4ROTATE:MOVCL,4ROLBX,CLMOVDL,BLANDDL,0FHADDDL,30HCMPDL,3AH;是A~F吗?JLPRINT_ITADDDL,07HPRINT_IT:MOVAH,02H;显示一个字符INT21HDECCHJNZROTATERETBINIHEXENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.1已定义了两个整数变量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;以上定义代码段;--------------------------------------------------------------------------99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印ENDSTART5.1假设已编制好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个字节ADDBX,AXJMPDWORDPTR[BX];转去执行歌曲程序ERROR:MOVDX,OFFSETERRMSGMOVAH,09HINT21H;显示错误信息JMPBEGINSING1:┇JMPBEGINSING2:┇JMPBEGINSING3:┇JMPBEGINSING4:┇JMPBEGINSING5:┇JMPBEGINEXIT:RETMAINENDPCSEGENDS;以上定义代码段;--------------------------------------------------------------------------ENDSTART5.2试用8086的乘法指令编制一个32位数和16位数相乘的程序;再用80386的乘法指令编制一个32位数和16位数相乘的程序,并定性比较两个程序的效率。答:8086的程序如下(假设为无符号数):99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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;以上定义代码段;--------------------------------------------------------------------------ENDSTART99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印80386作32位乘法运算用一条指令即可完成,而8086则需用部分积作两次完成。5.1如数据段中在首地址为MESS1的数据区内存放着一个长度为35的字符串,要求把它们传送到附加段中的缓冲区MESS2中去。为提高程序执行效率,希望主要采用MOVSD指令来实现。试编写这一程序。答:80386的程序如下:.386.MODELSMALL.STACK100H.DATAMESS1DB‘123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ’,?;长度为35的字符串.FARDATAMESS2DB36DUP(?).CODESTART:MOVAX,@DATAMOVDS,AX;给DS赋值MOVAX,@FARDATAMOVES,AX;给ES赋值ASSUMEES:@FARDATABEGIN:LEAESI,MESS1LEAEDI,MESS2CLDMOVECX,(35+1)/4;取传送的次数REPMOVSD;--------------------------------------------------------------------------MOVAX,4C00H;返回DOSINT21HENDSTART5.2试用比例变址寻址方式编写一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第一章.习题6.1下面的程序段有错吗?若有,请指出错误。CRAYPROC99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印PUSHAXADDAX,BXRETENDPCRAY答:程序有错。改正如下:CRAYPROCADDAX,BXRETCRAYENDP;CRAY是过程名,应放在ENDP的前面9BHF7H57H80HF0A0:00B0H先PUSH,SP-2再PUSH,SP-2POP,SP+26.2题堆栈及SP内容的变化过程6.1已知堆栈寄存器SS的内容是0F0A0H,堆栈指示器SP的内容是00B0H,先执行两条把8057H和0F79BH分别入栈的PUSH指令,然后执行一条POP指令。试画出示意图说明堆栈及SP内容的变化过程。答:变化过程如右图所示:6.2分析下面的程序,画出堆栈最满时各单元的地址及内容。;********************************************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;程序结束答:堆栈最满时各单元的地址及内容如右图所示:6.3分析下面的程序,写出堆栈最满时各单元的地址及内容。;********************************************STACKSEGMENTAT500H;定义堆栈段DW128DUP(?)TOSLABELWORDSTACKENDS;********************************************CODESEGMENT;定义代码段MAINPROCFAR;主程序部分ASSUMECS:CODE,SS:STACKSTART:MOVAX,STACKMOVSS,AX99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVSP,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;程序结束答:堆栈最满时各单元的地址及内容如右上图所示:6.1下面是一个程序清单,请在下面的图中填入此程序执行过程中的堆栈变化。;*************************0000STACKSGSEGMENT000020[.DW32DUP(?)????]0040STACKSGENDS;*************************0000CODESGSEGMENTPARA‘CODE’;--------------------------------------0000BEGINPROCFARASSUMECS:CODESG,SS:STACKSG00001EPUSHDS00012BC0SUBAX,AX000350PUSHAX0004E80008RCALLB10;--------------------------------------0007CBRET0008BEGINENDP99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;--------------------------------------0008B10PROC0008E8000CRCALLC10;--------------------------------------000BC3RET000CB10ENDP;--------------------------------------000CC10PROC;--------------------------------------000CC3RET000DC10ENDP;--------------------------------------000DCODESGENDS;*************************ENDBEGIN答:程序执行过程中的堆栈变化如下图所示。(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偏移地址堆栈6.1写一段子程序SKIPLINES,完成输出空行的功能。空出的行数在AX寄存器中。答:程序如下:CSEGSEGMENTSKIPLINESPROCFARASSUMECS:CSEGBEGIN:PUSHCXPUSHDXMOVCX,AXDISP:MOVDL,0DH;显示回车换行,即输出空行MOVAH,2;显示一个字符的DOS调用INT21HMOVDL,0AHMOVAH,2;显示一个字符的DOS调用INT21HLOOPDISPPOPDXPOPCXRETSKIPLINESENDPEND6.299 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印设有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;以上定义代码段;******************************************ENDSTART6.1编写一个有主程序和子程序结构的程序模块。子程序的参数是一个N字节数组的首地址TABLE,数N及字符CHAR。要求在N字节数组中查找字符CHAR,并记录该字符出现的次数。主程序则要求从键盘接收一串字符以建立字节数组TABLE,并逐个显示从键盘输入的每个字符CHAR以及它在TABLE数组中出现的次数。(为简化起见,假设出现次数≤15,可以用16进制形式把它显示出来。)答:程序如下:DSEGSEGMENTTABLEDB255DUP(?)NDW255CHARDB?CHAR_NDB0;用于记录CHAR出现的次数CRLFDB0DH,0AH,‘$’DSEGENDS;以上定义数据段99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;******************************************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]99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印JNZROTATE1INCCHAR_N;搜索到字符,则出现次数+1ROTATE1:INCSILOOPROTATERETSEARCHENDP;SEARCH子程序结束;--------------------------------------------------------------------------DISP_CRLFPROCNEAR;显示回车换行符子程序LEADX,CRLFMOVAH,09HINT21HRETDISP_CRLFENDP;DISP_CRLF子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART6.1编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名及8个字符的电话号码,并以一定的格式显示出来。主程序TELIST:·显示提示符“INPUTNAME:”;·调用子程序INPUT_NAME输入姓名;·显示提示符“INPUTATELEPHONENUMBER:”;·调用子程序INPHONE输入电话号码;·调用子程序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,STACK99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVSS,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_CRLF99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印RETGETCHARENDP;GETCHAR子程序结束;--------------------------------------------------------------------------PRINTLINEPROCNEAR;显示姓名及电话号码子程序LEADX,MESG3MOVAH,09H;显示字符串功能调用INT21HLEADX,OUTNAME;显示姓名及电话号码MOVAH,09H;显示字符串功能调用INT21HRETPRINTLINEENDP;PRINTLINE子程序结束;--------------------------------------------------------------------------DISP_CRLFPROCNEAR;显示回车换行符子程序LEADX,CRLFMOVAH,09HINT21HRETDISP_CRLFENDP;DISP_CRLF子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART6.1编写子程序嵌套结构的程序,把整数分别用二进制和八进制形式显示出来。主程序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,‘’99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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,07HORDL,30H;转换为ASCII码MOVAH,2INT21HPOPCXLOOPNEXTRETOUTOCTENDP;OUTOCT子程序结束;--------------------------------------------------------------------------DISP_CRLFPROCNEAR;显示回车换行符子程序LEADX,CRLFMOVAH,09HINT21HRETDISP_CRLFENDP;DISP_CRLF子程序结束;--------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART6.1假定一个名为MAINPRO的程序要调用子程序SUBPRO,试问:(1)MAINPRO中的什么指令告诉汇编程序SUBPRO是在外部定义的?99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(2)SUBPRO怎么知道MAINPRO要调用它?答:(1)EXTRNSUBPRO:FAR(2)PUBLICSUBPRO6.1假定程序MAINPRO和SUBPRO不在同一模块中,MAINPRO中定义字节变量QTY和字变量VALUE和PRICE。SUBPRO程序要把VALUE除以QTY,并把商存在PRICE中。试问:(1)MAINPRO怎么告诉汇编程序外部子程序要调用这三个变量?(2)SUBPRO怎么告诉汇编程序这三个变量是在另一个汇编语言程序定义的?答:(1)PUBLICQTY,VALUE,PRICE(2)EXTRNQTY:BYTE,VALUE:WORD,PRICE:WORD6.2假设:(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:FARPUBLICLAB36.3主程序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,AX99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVAX,PRICEMOVBX,QTYCALLSUBMULRETCALLMULENDPCODESGENDS;-----------------------------------------------------------------ENDCALLMUL;***************************************************************TITLESUBMUL;子程序PUBLICSUBMUL;-----------------------------------------------------------------CODESG1SEGMENTPARA‘CODE’ASSUMECS:CODESG1SUBMULPROCFARASSUMECS:CODESG1MULBXRETSUBMULENDPCODESG1ENDS;-----------------------------------------------------------------END6.1试编写一个执行以下计算的子程序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;同一段的求和子程序99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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;********************************************ENDSTART(3)主程序和COMPUTE不在同一程序模块中的程序如下:TITLEADDITION;主程序EXTRNCOMPUTE:FAR99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印PUBLICCOUNT,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第一章.习题7.1编写一条宏指令CLRB,完成用空格符将一字符区中的字符取代的工作。字符区首地址及其长度为变元。答:宏定义如下:CLRBMACRON,CFILMOVCX,N99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印CLDMOVAL,‘’;;取空格符的ASCII码LEADI,CFILREPSTOSBENDM7.1某工厂计算周工资的方法是每小时的工资率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,421MOVAH,01MOVBL,101DIVBL1MOVBL,31MULBL1ADDSUM,AX7.2给定宏定义如下:(注意:此宏指令的功能是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,AX99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印答:(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,AX1POPAX7.1试编制宏定义,要求把存储器中的一个用EOT(ASCII码04H)字符结尾的字符串传送到另一个存储区去。答:宏定义如下:SENDMACROSCHARS,DCHARSLOCALNEXT,EXITPUSHAXPUSHSIMOVSI,0NEXT:MOVAL,SCHARS[SI]MOVDCHARS[SI],ALCMPAL,04H;;是EOT字符吗?JZEXITINCSIJMPNEXTEXIT:POPSIPOPAXENDM7.2宏指令BIN_SUB完成多个字节数据连减的功能:99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印RESULT←(A-B-C-D-…)要相减的字节数据顺序存放在首地址为OPERAND的数据区中,减数的个数存放在COUNT单元中,最后结果存入RESULT单元。请编写此宏指令。答:宏定义如下:BIN_SUBMACRORESULT,A,OPERAND,COUNTLOCALNEXT_SUBPUSHCXPUSHBXPUSHAXMOVCX,COUNTMOVAL,ALEABX,OPERANDCLCNEXT_SUB:SBBAL,[BX]INCBXLOOPNEXT_SUBMOVRESULT,ALPOPAXPOPBXPOPCXENDM7.1请用宏指令定义一个可显示字符串GOOD:‘GOODSTUDENTS:CLASSXNAME’,其中X和NAME在宏调用时给出。答:宏定义如下:DISP_GOODMACROX,NAMEGOODDB‘GOODSTUDENTS:CLASS&X&NAME’,0DH,0AH,‘$’ENDM7.2下面的宏指令CNT和INC1完成相继字存储。CNTMACROA,BA&BDW?ENDMINC1MACROA,BCNTA,%BB=B+1ENDM请展开下列宏调用:C=0INC1DATA,CINC1DATA,C答:宏展开如下:C=0INC1DATA,C1DATA0DW?INC1DATA,C1DATA0DW?(注意:C为0没有变)7.3定义宏指令并展开宏调用。宏指令JOE把一串信息‘MESSAGENO.K’存入数据存储区XK中。宏调用为:I=0JOETEXT,I┇JOETEXT,I┇JOETEXT,I┇答:宏定义如下:MARYMACROX,K99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印X&KDB‘MESSAGENO.&K’ENDMJOEMACROA,IMARYA,%II=I+1ENDM宏调用和宏展开:I=0JOETEXT,I1TEXT0DB‘MESSAGENO.0’┇JOETEXT,I1TEXT1DB‘MESSAGENO.1’┇JOETEXT,I1TEXT2DB‘MESSAGENO.2’7.1宏指令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,67.2试编写非递归的宏指令,使其完成的工作与7.9题的STORE相同。答:宏定义如下:STOREMACROKMOVTAB+K,KENDM宏调用:I=0REPT7STORE%II=I+1ENDM7.3试编写一段程序完成以下功能,如给定名为X的字符串长度大于5时,下列指令将汇编10次。ADDAX,AX答:程序段如下:XDB‘ABCDEFG’IF($-X)GT5REPT10ADDAX,AXENDMENDIF99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印7.1定义宏指令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,SUMENDIFENDM7.2试编写一段程序完成以下功能:如变元X=‘VT55’,则汇编MOVTERMINAL,0;否则汇编MOVTERMINAL,1。答:宏定义如下:BRANCHMACROXIFIDN,MOVTERMINAL,0ELSEMOVTERMINAL,1ENDIFENDM7.3对于DOS功能调用,所有的功能调用都需要在AH寄存器中存放功能码,而其中有一些功能需要在DX中放一个值。试定义宏指令DOS21,要求只有在程序中定义了缓冲区时,汇编为:MOVAH,DOSFUNCMOVDX,OFFSETBUFFINT21H否则,无MOVDX,OFFSETBUFF指令。并展开以下宏调用:DOS2101DOS210AH,IPFIELD答:宏定义如下:DOS21MACRODOSFUNC,BUFFMOVAH,DOSFUNCIFDEFBUFFMOVDX,OFFSETBUFFENDIFINT21HENDM宏展开:DOS21011MOVAH,011INT21HDOS210AH,IPFIELD1MOVAH,0AH1MOVDX,OFFSETIPFIELD1INT21H7.4编写一段程序,使汇编程序根据SIGN中的内容分别产生不同的指令。如果(SIGN)=0,则用字节变量DIVD中的无符号数除以字节变量SCALE;如果(SIGN)=1,则用字节变量DIVD中的带符号数除以字节变量SCALE,结果都存放在字节变量RESULT中。答:程序段如下:MOVAL,DIVDIFSIGN99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVAH,0DIVSCALEELSECBWIDIVSCALEENDIFMOVRESULT,AL7.1试编写宏定义SUMMING,要求求出双字数组中所有元素之和,并把结果保存下来。该宏定义的哑元应为数组首址ARRAY,数组长度COUNT和结果存放单元RESULT。答:宏定义如下:SUMMINGMACROARRAY,COUNT,RESULTLOCALADDITIONMOVESI,0MOVECX,COUNTADDITION:MOVEAX,ARRAY[ESI*4];;双字为4字节ADDRESULT,EAXADCRESULT+4,0;;将进位加到结果的高位双字中INCESILOOPADDITIONENDM7.2为下列数据段中的数组编制一程序,调用题7.16的宏定义SUMMING,求出该数组中各元素之和。DATADD101246,274365,843250,475536SUMDQ?答:程序如下: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,4C00HINT21HENDSTART7.3如把题7.16中的宏定义存放在一个宏库中,则题7.17的程序应如何修改?答:程序修改如下:INCLUDEMACRO.MAC;假设存放的宏库名为MACRO.MAC.MODELSMALL.386.DATADATADD101246,274365,843250,475536SUMDQ?.CODE99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印START:MOVAX,@DATAMOVDS,AXSUMMINGDATA,4,SUMMOVAX,4C00HINT21HENDSTART第一章.习题8.1写出分配给下列中断类型号在中断向量表中的物理地址。(1)INT12H(2)INT8答:(1)中断类型号12H在中断向量表中的物理地址为00048H、00049H、0004AH、0004BH;(2)中断类型号8在中断向量表中的物理地址为00020H、00021H、00022H、00023H。8.2用CALL指令来模拟实现INT21H显示字符T的功能。答:MOVAH,2MOVDL,‘T’PUSHDSPUSHF;因中断服务程序的返回指令是IRET,而不是RETMOVBX,0MOVDS,BXCALLDWORDPTR[21H*4];用CALL指令调用21H的中断服务程序POPDS8.3写出指令将一个字节数据输出到端口25H。答:指令为:OUT25H,AL8.4写出指令将一个字数据从端口1000H输入。答:指令为:MOVDX,1000HINAX,DX8.5假定串行通讯口的输入数据寄存器的端口地址为50H,状态寄存器的端口地址为51H,状态寄存器各位为1时含义如右图所示,请编写一程序:输入一串字符并存入缓冲区BUFF,同时检验输入的正确性,如有错则转出错处理程序ERROR_OUT。输入数据准备好76543210输出寄存器空奇偶校验错溢出错格式错8.3状态寄存器各位含义答:程序段如下:MOVDI,0MOVCX,80;最多输入80个字符BEGIN:INAL,51H;查询输入是否准备好?TESTAL,02HJZBEGININAL,50H;输入数据并存入缓冲区BUFFMOVBUFF[DI],ALINCDIINAL,51H;判断是否有错?TESTAL,00111000BJNZERROR_OUTLOOPBEGIN┇8.6试编写程序,它轮流测试两个设备的状态寄存器,只要一个状态寄存器的第0位为1,则就与其相应的设备输入一个字符;如果其中任一状态寄存器的第3位为1,则整个输入过程结束。两个状态寄存器的端口地址分别是0024H和0036H,与其相应的数据输入寄存器的端口地址则为0026H和0038H,输入字符分别存入首地址为BUFF1和BUFF2的存储区中。答:程序段如下:MOVDI,0MOVSI,0BEGIN:INAL,24H99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印TESTAL,08H;查询第一个设备的输入是否结束?JNZEXITTESTAL,01H;查询第一个设备的输入是否准备好?JZBEGIN1INAL,26H;输入数据并存入缓冲区BUFF1MOVBUFF1[DI],ALINCDIBEGIN1:INAL,36HTESTAL,08H;查询第二个设备的输入是否结束JNZEXITTESTAL,01H;查询第二个设备的输入是否准备好?JZBEGININAL,38H;输入数据并存入缓冲区BUFF2MOVBUFF2[SI],ALINCSIJMPBEGINEXIT:┇8.1假定外部设备有一台硬币兑换器,其状态寄存器的端口地址为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,ALJMPBEGIN8.2给定(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)=0240H8.3类型14H的中断向量在存储器的哪些单元里?答:在0000:0050H,0000:0051H,0000:0052H,0000:0053H四个字节中。8.4假定中断类型9H的中断处理程序的首地址为INT_ROUT,试写出主程序中为建立这一中断向量而编制的程序段。99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印答:程序段如下:┇MOVAL,1CH;取原中断向量,并保护起来MOVAH,35HINT21HPUSHESPUSHBXPUSHDSMOVAX,SEGINT_ROUTMOVDS,AXMOVDX,OFFSETINT_ROUTMOVAL,09HMOVAH,25H;设置中断向量功能调用INT21HPOPDS┇POPDX;还原原中断向量POPDSMOVAL,1CHMOVAH,25HINT21H8.1编写指令序列,使类型1CH的中断向量指向中断处理程序SHOW_CLOCK。答:程序段如下:┇MOVAL,1CHMOVAH,35H;取中断向量功能调用,取原中断向量INT21HPUSHESPUSHBXPUSHDSMOVAX,SEGSHOW_CLOCKMOVDS,AXMOVDX,OFFSETSHOW_CLOCKMOVAL,1CHMOVAH,25H;设置中断向量功能调用INT21HPOPDS┇POPDXPOPDSMOVAL,1CHMOVAH,25H;设置中断向量功能调用,还原原中断向量INT21H┇8.2如设备D1,D2,D3,D4,D5是按优先级次序排列的,设备D1的优先级最高。而中断请求的次序如下所示,试给出各设备的中断处理程序的运行次序。假设所有的中断处理程序开始后就有STI指令。(1)设备D3和D4同时发出中断请求。(2)在设备D3的中断处理程序完成之前,设备D2发出中断请求。(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.399 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印在8.12题中假设所有的中断处理程序中都没有STI指令,而它们的IRET指令都可以由于FLAGS出栈而使IF置1,则各设备的中断处理程序的运行次序应是怎样的?答:各设备的中断处理程序的运行次序是:INT_D3,INT_D2,INT_D4,INT_D5;INT_D1,INT_D3,INT_D5。8.1试编制一程序,要求测出任一程序的运行时间,并把结果打印出来。答:程序段如下: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;返回DOSMAINENDP99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;----------------------------------------------------------------------------------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]MOVAH,05HINT21HINCBXLOOPROTATEMOVBX,HOURS;打印时间的小时数CALLBINIDEC;调二进制转换为10进制并打印输出子程序MOVDL,‘:’;打印输出冒号‘:’MOVAH,05HINT21HMOVBX,MIN;打印时间的分钟数CALLBINIDECMOVDL,‘:’MOVAH,05HINT21HMOVBX,SEC;打印时间的秒钟数CALLBINIDECRETPRINTENDP;PRINT子程序结束;----------------------------------------------------------------------------------BINIDECPROCNEAR;二进制转换为10进制子程序MOVCX,10000D99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印CALLDEC_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;汇编语言源程序结束第一章.习题9.1INT21H的键盘输入功能1和功能8有什么区别?答:键盘输入功能1:输入字符并回显(回送显示器显示)(检测Ctrl_Break);键盘输入功能8:输入字符但不回显(也检测Ctrl_Break)。9.2编写一个程序,接受从键盘输入的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;保存密码INCSI99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印LOOPINPUTEXIT:RET9.1对应黑白显示器屏幕上40列最下边一个象素的存储单元地址是什么?答:对应黑白显示器屏幕上40列最下边一个象素的存储单元地址是:B000:0F78H9.2写出把光标置在第12行,第8列的指令。答:指令如下:MOVDH,0BH;0BH=12-1MOVDL,07H;07H=8-1MOVBH,0MOVAH,2;置光标功能调用INT10H9.3编写指令把12行0列到22行79列的屏幕清除。答:指令如下:MOVAL,0;清除屏幕MOVBH,07MOVCH,12;左上角行号MOVCL,0;左上角列号MOVDH,22;右下角行号MOVDL,79;右下角列号MOVAH,6;屏幕上滚功能调用INT10H9.4编写指令使其完成下列要求。(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,1INT10H9.5写一段程序,显示如下格式的信息:Tryagain,youhavenstarfightersleft.其中n为CX寄存器中的1~9之间的二进制数。答:程序段如下:MESSAGEDB‘Tryagain,youhave’CONTDBnDB‘starfightersleft.$’;┇ADDCL,30HMOVCONT,CL;保存ASCII码99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印LEADX,MESSAGEMOVAH,9;显示一个字符串的DOS调用INT21H9.1从键盘上输入一行字符,如果这行字符比前一次输入的一行字符长度长,则保存该行字符,然后继续输入另一行字符;如果它比前一次输入的行短,则不保存这行字符。按下‘$’输入结束,最后将最长的一行字符显示出来。答:程序段如下: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调用INT21H9.2编写程序,让屏幕上显示出信息“Whatisthedate(mm/dd/yy)?”并响铃(响铃符为07),然后从键盘接收数据,并按要求的格式保存在date存储区中。答:程序段如下:MESSAGEDB‘Whatisthedate(mm/dd/yy)?’,07H,‘$’DATAFLDDB10,0DATEDB10DUP(‘’);┇MOVAH,9;显示一个字符串的DOS调用LEADX,MESSAGE;显示字符串INT21HMOVAH,0AH;输入字符串的DOS调用LEADX,DATAFLDINT21H9.3用户从键盘输入一文件并在屏幕上回显出来。每输入一行(≤80字符),用户检查一遍,如果用户认为无需修改,则键入回车键,此时这行字符存入BUFFER缓冲区保存,同时打印机把这行字符打印出来并回车换行。答:程序段如下:INAREADB80;输入字符串的缓冲区,最多输入80个字符ACTLENDB?BUFFERDB80DUP(?);┇INPUT:LEADX,INAREA;输入字符串MOVAH,0AH;输入字符串的DOS调用99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印INT21HCMPACTLEN,0JEEXITMOVBX,0MOVCH,0MOVCL,ACTLENPRINT:MOVAH,5;打印输出MOVDL,BUFFER[BX]INT21HINCBXLOOPPRINTMOVAH,5;打印输出回车换行MOVDL,0AHINT21HMOVDL,0DHINT21HJMPINPUTEXIT:RET9.1使用MODE命令,设置COM2端口的通信数据格式为:每字8位,无校验,1位终止位,波特率为1200b/s。答:命令格式如下:MODECOM2:12,N,8,1第一章.习题10.1写出指令,选择显示方式10H,并将背景设为绿色。答:MOVAH,00HMOVAL,10H;选择显示方式10H(16色图形)INT10HMOVAH,10HMOVAL,00HMOVBH,10H;背景设为绿色(02H也可以,是用DEBUG调试出来的)MOVBL,0;选择0号调色板INT10H设置背景色也可用:MOVAH,0BH;设置背景色和调色板MOVBH,0;设置背景色功能MOVBL,8;绿色背景INT10H10.2如何使用INT10H的功能调用改变显示方式?答:在AH中设置功能号00H,在AL中设置显示方式值,调用INT10H即可。10.3VGA独有的一种显示方式是什么?答:像素值为640×480,可同时显示16种颜色,这种显示方式(12H)是VGA独有的。10.4对于EGA和VGA显示适配器,使用显示方式13H时(只有VGA有),显示数据存在哪里?答:显示数据存在显示存储器里。10.5对于VGA的显示方式13H时存放一屏信息需要多少字节的显存?答:需要64000个字节。10.6利用BIOS功能编写图形程序:设置图形方式10H,选择背景色为蓝色,然后每行(水平方向)显示一种颜色,每4行重复一次,一直到整个屏幕都显示出彩条。99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印答:程序如下: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,350jnelineint20hmainendpcodesegendsendmain10.1修改10.6题的程序,使整个屏幕都显示出纵向的彩条。答:程序如下: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行99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印line:movah,0ch;写像素点moval,blint10hincdxcmpdx,350jnelinemovdx,0;起始行号为0行incblandbl,03h;只显示四种颜色(因此保留最低两位)inccxcmpcx,640jnelineint20hmainendpcodesegendsendmain10.1按动键盘上的光标控制键,在屏幕上下左右任一方向上绘图,每画一点之前,由数字键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,escapejzexit99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印cmpal,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,leftjnzwritedeccx;useROMroutinetowritedot,reguiresrow#inDX,colinCX,colorinALwrite:moval,blmovah,0chint10hjmpget_charexit:int20hmainendpcodesegendsendstart10.1位屏蔽寄存器的作用是什么?在16色,640×480显示方式中如何使用位屏蔽寄存器?答:位屏蔽寄存器的作用是决定了新的像素值产生的方法。当位屏蔽寄存器的某位设为0时,相对应的像素值直接由锁存器写入显存;位屏蔽寄存器的某位为1时,所对应的像素值由锁存器中的像素值与CPU数据或置位/重置寄存器中相应位合并之后产生。10.2读映像选择寄存器的作用是什么?如果4个位面的内容都需要读取,读映像选择寄存器应如何设置?答:读映像选择寄存器的作用是用于选择哪一个位面的字节读入CPU。读映像选择寄存器的0和1位,用来指定哪个位面的锁存器内容读到CPU。如果4个位面的内容都需要读取,则必须对同一地址执行4次读操作,在每次读之前,用指令分别设置读映像选择寄存器。10.3编写程序使一只“鸟”飞过屏幕。飞鸟的动作可由小写字母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,AX99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印PUSHAXMOVAX,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;汇编语言源程序结束99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印ASCII码为0DDHASCII码为0DCHASCII码为0DFHASCII码为0DBHASCII码为0DEH10.1用图形文本的方法设计“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;以上定义数据段;******************************************99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;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;Page0INT10HJMPCHAR_WRITEMAINENDP;----------------------------------------------------------------------------------;DisplaycharacterinALandusingthecolorcodeinBLShow_charPROCNEAR;显示字符子程序MOVAH,9;BIOSservicerequestnumberMOVBH,0;Page0MOVCX,1;NorepeatINT10H;BumpcursorINCDLMOVAH,2;SetcursorpositionMOVBH,0;Page0INT10HRETShow_charENDP;SHOW_CHAR子程序结束;----------------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART;汇编语言源程序结束10.199 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印游戏程序常常用随机数来控制其图形在屏幕上移动。请编写一程序,用随机数来控制笑脸符(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:JMPBEGIN99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印EXIT:POPAX;恢复当前显示方式(AL)MOVAH,0INT10HRET;返回DOSMAINENDP;----------------------------------------------------------------------------------DELAYPROCNEAR;延时0.25s子程序PUSHCXPUSHDXMOVDX,25;延时0.25sDEL1:MOVCX,2801;延时10msDEL2:LOOPDEL2DECDXJNZDEL1POPDXPOPCXRETDELAYENDP;DELAY子程序结束;----------------------------------------------------------------------------------CSEGENDS;以上定义代码段;******************************************ENDSTART;汇编语言源程序结束10.1分配给PC机主板上的8253/54定时器的端口地址是什么?答:8253/54定时器的3个独立计数器Counter0、Counter1和Counter2的端口地址分别为40H、41H和42H。8253/54内部还有一个公用的控制寄存器,端口地址为43H。10.28253/54定时器的三个计数器,哪一个用于扬声器?它的端口地址是什么?答:8253/54定时器的计数器Counter2用于扬声器,它的端口地址为42H。10.3下面的代码是利用监控端口61H的PB4来产生延迟时间的,它适用于所有的286、386、PentiumPC及兼容机。请指出该程序的延迟时间是多少?MOVDL,200BACK:MOVCX,16572WAIT:INAL,61HANDAL,10HCMPAL,AHJEWAITMOVAH,ALLOOPWAITDECDLJNZBACK答:该程序的延迟时间是200×16572×15.08μs=49981152μs≈50s。10.4在PC机上编写乐曲程序“HappyBirthday”,乐曲的音符及音频如下:歌词音符音频节拍歌词音符音频节拍歌词音符音频节拍hapC2621/2dayC2621soD2943pyC2621/2toG3921hapBb4661/2birthD2941youF3492pyBb4661/2dayC2621hapC2621/2birthA4401toF3491pyC2621/2dayC2621youE3302birthD2941toG3921hapC2621/2dayA4401youF3492pyC2621/2dearF3491birthD2941soE3301答:程序如下:TITLEMUSIC—Amusicof‘HappyBirthday’;连接时需加上GENSOUND程序EXTRNSOUNDF:FAR;SOUNDF是外部过程——通用发声程序99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;******************************************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的工作方式OUT43H,ALMOVDX,12H;根据频率求8253的计数值,即533H*896/freq99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印MOVAX,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;以上定义代码段;******************************************END10.1编写用键盘选择计算机演奏歌曲的程序。首先在屏幕上显示出歌曲名单如下: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吗?99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印JNZB0CALLMUSIC1;去演奏歌曲AJMPINPUTB0:CMPAL,‘b’;演奏歌曲b吗?JNZC0CALLMUSIC2;去演奏歌曲BJMPINPUTC0:CMPAL,‘c’;演奏歌曲c吗?JNZINPUTCALLMUSIC3;去演奏歌曲CJMPINPUTEXIT:RET;返回第一章.习题11.1写出文件代号式磁盘存取操作的错误代码:(1)非法文件代号(2)路径未发现(3)写保护磁盘答:错误代码为:(1)06(2)03(4)1911.2使用3CH功能建立一文件,而该文件已经存在,这时会发生什么情况?答:此操作将文件长度置为0,写新文件,原文件内容被清除。11.3从缓冲区写信息到一个文件,如果没有关闭文件,可能会出现什么问题?答:文件结尾的部分信息就没有被写入磁盘,从而造成写入的文件不完整。11.4下面的ASCIZ串有什么错误?PATH_NAMEDB‘C:PROGRAMSTEST.DAT’答:此ASCIZ串的最后少了一个全0字节,应改为:PATH_NAMEDB‘C:PROGRAMSTEST.DAT’,011.5下面为保存文件代号定义的变量有什么错误?FILE_HNDLDB?答:文件代号是字类型,因此应改为:FILE_HNDLDW?11.6在ASCPATH字节变量中为驱动器D的文件PATIENT.LST,请定义ASCIZ串。答:ASCPATHDB‘D:PATIENT.LST’,011.7对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;记录长度99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印(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.1对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;退出程序,返回DOSint21h99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印beginendp;-------------------------------------------------------------;打开文件openhprocnearmovah,3dhmoval,0leadx,ascpathint21hjcb1;打开错误吗?movfhandle,ax;没有错,保存文件代号retb1:movendcde,01;打开错误,指示结束处理leadx,openmsgcallerrm;显示出错信息retopenhendp;-------------------------------------------------------------;读磁盘记录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;屏幕右下角99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印int10hretscreenendp;-------------------------------------------------------------;设置光标cursprocnearmovah,2;设置光标movbh,0movdh,row;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------endbegin11.1编写建立并写入磁盘文件的程序。允许用户从键盘键入零件号(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("");DTAerrcdedb0;错误处理指示opnmsgdb"***openerror***",0dh,0ahwrtmsgdb"***writeerror***",0dh,0ah;-------------------------------------------------------------.codebeginprocfar99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印movax,@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;显示提示信息99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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缓冲区内容送入dtamovcx,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中的单价位置ret99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印dec_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,crlf99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印movah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin;汇编语言源程序结束11.1编写一个程序使用文件代号式读出并显示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,099 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印leadx,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,09hint21hmovah,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_crlf99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印cmprow,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;列号int10hret99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印cursendp;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin11.1对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,0600h99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印callscreen;清屏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中返回实际读入的字节数存入bpretc1:leadx,readmsg;读错误callerrm;显示出错信息c2:movendcde,01;读错误或文件读完,指示结束处理retreadhendp;-------------------------------------------------------------;输入零件号和零件数量in_Partprocnearleadx,in_mes1;显示提示信息,提示输入零件号in_Part1:callinput;输入数据cmpin_buffer+1,3;输入的零件号个数是3位吗?leadx,out_mes2;显示提示信息,提示重新输入零件号jnein_Part1cld99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印movax,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,299 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印movcl,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位数的零件号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_dec199 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印movcx,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,0movdh,0;行号movdl,0;列号int10hretcursendp;-------------------------------------------------------------;显示出错信息errmprocnear99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印movah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin11.1用随机处理记录的方式编写程序,将用户需要的零(配)件记录读取到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;退出程序,返回DOS99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印int21hbeginendp;-------------------------------------------------------------;打开文件openhprocnearmovah,3dhmoval,0leadx,pathnameint21hjcbbb;打开错误吗?movhandle,ax;没有错,保存文件代号retbbb:movendcde,01;打开错误,指示结束处理leadx,opnmsgcallerrm;显示出错信息retopenhendp;-------------------------------------------------------------;读磁盘记录readhprocnearmovah,3fhmovbx,handlemovcx,19;准备读入的字节数leadx,tableint21hjcc1;读错误吗?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;显示提示信息,提示输入零件号99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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;-------------------------------------------------------------;将十进制数转换为二进制数子程序99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印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;-----------------------------------------------------------------;显示记录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,1099 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印bin_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,0movdh,0;行号movdl,0;列号int10hretcursendp99 0ac7096d13a9fcffb8ab3b31ab55517f.doc-99-作者:张兆印;-------------------------------------------------------------;显示出错信息errmprocnearmovah,40h;向标准输出设备(文件代号=01)写文件movbx,01;标准输出设备的文件代号=01movcx,20int21hreterrmendp;-------------------------------------------------------------disp_crlfprocnear;显示回车换行符子程序leadx,crlfmovah,09hint21hretdisp_crlfendp;disp_crlf子程序结束;-----------------------------------------------------------endbegin99'