• 272.00 KB
  • 2022-04-22 11:51:06 发布

《80x86汇编语言程序设计(第2版)》习题答案.doc

  • 36页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'习题参考答案习题参考答案1第1章1-1汇编的主要功能:输入:汇编语言源文件输出:目标文件处理:对源文件进行语法检查;将符号指令翻译为机器指令。连接的主要功能:输入:1个或多个目标文件与库文件输出:可执行文件处理:浮动地址的重定位;多模块的连接。1-2(1)2EH(2)0D2H(3)0FFH(4)80H(5)7FH(6)0FEH1-3(1)7FH(2)0FF80H(3)0FFFFH(4)0FFD2H(5)8000H(6)0FFH1-4无符号数范围:0~2n-1;带符号数范围:-2n−1~2n−1-11-5(1)压缩BCD码:58H;非压缩BCD码:x5x8H。(2)压缩BCD码:1624H;非压缩BCD码:x1x6x2x4H。1-6(1)字符"1"的ASCII码;十进制数31的压缩BCD码;十进制数1的非压缩BCD码;十进制数49的十六进制表示。(2)十进制数-1的8位二进制补码表示;带符号数255的16位二进制补码表示;无符号数255的8位二进制形式。(3)十进制数-1的16位二进制补码表示;带符号数65535的32位二进制补码表示;无符号数65535的16位二进制形式。1-7(1)作为无符号数为159,等值的16位和32位形式均为9FH;作为带符号数为-97,等值的16位和32位形式分别为0FF9FH与0FFFFFF9FH。319 习题参考答案(2)作为无符号数和带符号数均为104,等值的16位和32位形式均为68H。(3)作为无符号数为192,等值的16位和32位形式均为0C0H;作为带符号数为-64,等值的16位和32位形式分别为0FFC0H与0FFFFFFC0H。1-8(1)AND0FH(2)OR30H(3)右移4位可得高位的值;将原值AND0FH可得低位的值。(4)XOR00101010B(5)AND8000H,若结果为0,则是正数,否则为负数。第2章2-1系统总线是CPU与内存和I/O子系统之间进行数据交换的通道,包括数据总线、地址总线和控制总线,分别负责在CPU与内存和I/O子系统之间传送数据、地址和控制信息。其中,数据总线决定了CPU每次存取数据的最大位数;地址总线决定了系统的最大可编址空间;控制总线用来控制CPU与内存和I/O设备之间的数据传送方式。2-28位通用寄存器8个:AH,AL,BH,BL,CH,CL,DH和DL。16位通用寄存器8个:AX,BX,CX,DX,SI,DI,BP和SP。32位通用寄存器8个:EAX,EBX,ECX,EDX,ESI,EDI,EBP和ESP。段寄存器6个:CS,DS,SS,ES,FS和GS。2-3IP包含要执行的下一条指令的偏移地址;SP包含堆栈段栈顶的偏移地址;段寄存器用来存放16位段地址。通常,CS存放当前代码段的段地址,SS存放当前堆栈段的段地址,DS、ES、FS和GS用来存放数据段的段地址。2-4 因为段内偏移地址是16位,故每个段最大只能216B,即64KB。2-5物理地址=段地址×16+偏移地址。给定逻辑地址,可得到唯一的物理地址;每个物理地址可由不同的逻辑地址描述。例如,逻辑地址0200:1200H对应唯一的物理地址03200H,但该物理地址又可由逻辑地址0320:0000H,0210:1100H和0000:3200H等来描述。2-6实模式的主要特点如下。●与8086兼容,只有低20条地址线有效,只能寻址第一个1MB的内存空间。●采用内存分段方式,程序所使用的逻辑地址为16位段地址:16位偏移地址,每段≤64KB。20位物理地址由段地址左移4位加偏移地址得到。●CPU总是从地址CS:IP处取指令,EIP的高16位为0。●SS:SP表示堆栈段的栈顶地址,ESP的高16位为0。●对于32位80x86CPU,程序可以使用32位寄存器和32位操作数,但采用32位寄存器表示偏移地址时,只使用低16位,高16位为0。2-7首字单元地址:23A10H;末字单元地址:23A1EH2-8这些数在内存的存放情况如下:319 习题参考答案…010006H310005H47H10004H2BH10003H2AH10002H010001H110000H…2-9(1)CF=1OF=0SF=0ZF=1(2)CF=0OF=1SF=1ZF=0(3)CF=1OF=1SF=0ZF=1(4)CF=0OF=0SF=1ZF=02-10(1)CF=0OF=0SF=0ZF=0(2)CF=0OF=1SF=0ZF=0(3)CF=1OF=0SF=1ZF=0(4)CF=1OF=1SF=1ZF=0第3章3-1(1)SS(2)CS(3)DS(4)FS(5)SS(6)DS(7)DS(8)ES3-2(1)正确(2)类型不匹配(3)两个操作数不能同时是内存操作数(4)没有[esp][eax*3]这种操作数形式(5)正确(6)CS不能作为目的操作数(7)类型不确定(8)没有[sp]这种操作数形式(9)条件转移指令的操作数只能是标号(10)正确(11)不能将立即数送段寄存器(12)没有bx+2这种操作数形式3-3(1)27feh(2)2a00h(3)2802h(4)2801h(5)27feh(段内调用)或27fch(段间调用)(6)2802h(段内返回)或2804h(段间返回)(7)27fch(8)2804h3-4DEC不影响CF。3-5不能。转移类指令(如JMP,Jcc,LOOP,CALL及RET等)的执行会改变IP的值。3-6无符号数比较:(1)ZF=1(2)ZF=0(3)CF=1(4)CF=1或ZF=1(5)CF=0且ZF=0(6)CF=0带符号数比较:(1)ZF=1(2)ZF=0(3)SF<>OF(4)SF<>OF或ZF=1(5)SF=OF且ZF=0(6)SF=OF3-7CALL指令执行的操作:(1)返回地址进栈。319 习题参考答案段间调用:CS与IP(下一条指令的地址)依次进栈。段内调用:IP(下一条指令的16位偏移地址)进栈。(2)转移到过程的第1条指令去执行。段间调用:根据操作数,将32位分段地址送CS:IP。段内调用:根据操作数,将16位偏移地址送IP。RET指令执行的操作:返回地址出栈,从而实现转移到返回地址处。段间返回:POP1个双字到CS:IP。段内返回:POP1个字到IP。3-8AX的值将是返回地址的16位偏移地址。3-9(1)除数为0。(2)除数太小,被除数太大,导致商溢出。3-10(1)cbw(2)cwd(3)cdq(4)btax,03-11(1)movah,0addax,bx(2)cbwaddax,bx(3)movsxeax,aladdeax,ebx3-12将DX:AX中的双字数右移4位。3-13指令ALCFOFSFZFxoral,al00001moval,2550ffh0001incal00001notal0ffh0001shlal,10feh1010cmpal,100feh0010subal,7fh7fh0100shlal,10feh01103-14(1)jcxzdonenext:movbl,[si]moves:[di],blincsiincdiloopnextdone:(2)jcxzdonenext:moves:[di],eaxsubdi,4loopnextdone:(3)jcxzdonenext:movax,[si]cmpax,es:[di]pushfaddsi,2319 习题参考答案adddi,2popfloopenextdone:3-15将AX与DX中的4位十进制数对应的压缩BCD码相加,结果存入AX。例如,若AX=1234H,DX=5678H,则结果AX=6912H。3-16(1)movbl,alandbl,0fhmovbh,alshrbh,4(2)shlax,1rclbx,1rclcx,1(3)cmpal,10jgesetcfcmpal,-10jlesetcfclcjmpexitsetcf:stcexit:(4)cmpeax,ebxjbenextxchgeax,ebxnext:cmpeax,ecxjbedonexchgeax,ecxdone:(5)movcx,axxorcx,bxtestcx,1jzexittestbx,1jzexitxchgax,bxexit:(6)movdx,0shlax,1rcldx,1movbx,axmovcx,dxshlax,1rcldx,1shlax,1rcldx,1addax,bxadcdx,cx(7)moval,xcbwshlax,2subax,5movbx,axmoval,xsaral,1cbw319 习题参考答案addax,bx(8)movax,0movcx,100next:addax,cxloopnext第4章4-1指令是程序运行时由CPU执行的,在汇编后由对应的机器代码所取代;而伪指令是不可执行的,只是由汇编器处理的命令。指令与机器密切相关,指令系统是由CPU本身确定的;而伪指令与机器无关,只与汇编器有关。4-2标号表示指令的起始地址,可作为转移类指令的操作数,表示转向地址;变量是用来定义数据的,可作为指令的内存操作数。JMPL;直接转移,转移到标号L所在地址JMPX;段内间接转移,目标的偏移地址为X的值(字)4-3(1)源程序的编辑。输出文件:源程序文件.asm。(2)源程序的汇编。输入文件:源程序文件。输出文件:●无错:目标文件.obj,列表文件等。●有错:错误信息,列表文件。(3)目标文件的连接。输入文件:目标文件与库文件。输出文件:●无错:可执行文件.exe,映像文件等。●有错:错误信息。(4)可执行文件的试运行。(5)可执行文件的调试。4-4(1)AX的值为地址WVar+1处的1个字。(2)AX的值为地址WVar处的字加1。4-5(1)正确。(2)错误。offset后只能是汇编时可求值的地址表达式。(3)正确。(4)错误。两个操作数不能同时为内存操作数。(5)错误。不能将两个地址相加。(6)错误。类型不匹配。(7)正确。(8)错误。JMP指令的操作数不能为字节变量。319 习题参考答案4-6oprdand0feh是一个表达式,在汇编时求值,其中的and为逻辑运算符;第1个and是指令助记符,指令在程序运行时执行。4-7(1)dw3132h(2)db32h,31h(3)db"21"(4)dw"12"4-8(1)24h(2)0ch(3)0ch(4)6(5)10h(6)3103h(7)5(8)7(9)04-9(1)movdx,segblockmovds,dxleabx,block+12movdx,[bx](2)movdx,segblockmovds,dxmovdx,block+12(3)movdx,segblockmovds,dxmovbx,12movdx,block[bx](4)movdx,segblockmovds,dxleabx,blockmovsi,12movdx,[bx][si](5)movdx,segblockmovds,dxmoveax,6movdx,block[eax*2]4-101e00h4-11将buf1中的后10个字节传送到buf2中。4-12将String中的80个字符整体后移1个字节,首字符不变。4-13将两位十进制数对应的压缩BCD码存入AL。4-14dsegsegmentBCDdb69h;已知的BCD码ASCdb?,?;存放ASCII码dsegendscsegsegmentassumecs:cseg,ds:dsegstart:movax,dsegmovds,axmoval,BCDmovcl,4shral,cloral,30hmovASC,almoval,BCDandal,0fhoral,30h319 习题参考答案movASC+1,almovah,4chint21hcsegendsendstart4-15.386dsegsegmentuse16numdd12345678hbufdb8dup(?)dsegendscsegsegmentuse16assumecs:cseg,ds:dsegstart:movax,dsegmovds,axmovcx,8movsi,0moveax,numnext:roleax,4movbuf[si],alandbuf[si],0fhincsiloopnextmovah,4chint21hcsegendsendstart第5章5-1dsegsegmentCrLfdb0dh,0ah,"$"dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovah,1int21hpushaxleadx,CrLfmovah,9int21hpopaxcmpal,"a"jbStopcmpal,"z"jaStopsubal,20hmovdl,almovah,2int21h319 习题参考答案Stop:movah,4chint21hcsegendsendStart5-2CRequ0dhLFequ0ahdsegsegmentMsg1db"Allequal.",CR,LF,"$"Msg2db"Onlytwoequal.",CR,LF,"$"Msg3db"Allthreedifferentfromeachother.",CR,LF,"$"Num1dw?;Num1、Num2与Num3为定义的三个16位数Num2dw?Num3dw?dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovax,Num1cmpax,Num2jeAlready_Two_Equalcmpax,Num3jeTwo_Equalmovax,Num2cmpax,Num3jeTwo_Equalleadx,Msg3jmpDoneAlready_Two_Equal:cmpax,Num3jeAll_EqualTwo_Equal:leadx,Msg2jmpDoneAll_Equal:leadx,Msg1Done:movah,9int21hmovah,4chint21hcsegendsendStart5-3.386dsegsegmentuse16Numdd?,?,?;给定的3个32位带符号数dsegendscsegsegmentuse16assumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovecx,1moveax,NumNext:cmpeax,Num[ecx*4]319 习题参考答案jleSkipxchgeax,Num[ecx*4]movNum,eaxSkip:incecxcmpecx,3jneNextmoveax,Num+4cmpeax,Num+8jleDonexchgeax,Num+8movNum+4,eaxDone:movah,4chint21hcsegendsendStart5-4.386optionsegment:use16dsegsegmentMsg1db"Decimal:","$"Msg2db0dh,0ah,"Binary:","$"ErrMsgdb0dh,0ah,"Invaliddata.","$"dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axleadx,Msg1movah,9int21hmovah,1int21hmovbl,alcmpbl,"0"jbErrorcmpbl,"9"jbeOkError:leadx,ErrMsgmovah,9int21hjmpDoneOk:leadx,Msg2movah,9int21hshlbl,4movcx,4NextBit:shlbl,1setcdladddl,30hmovah,2int21hloopNextBitDone:movah,4chint21hcsegendsendStart319 习题参考答案5-5.386dsegsegmentuse16Datadw100dup(?)dsegendscsegsegmentuse16assumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovax,0movecx,lengthofDataNext:movbx,Data[ecx*2-2]btbx,0jncSkipcmpax,0jzOkcmpax,bxjbeSkipOk:movax,bxSkip:loopNextDone:movah,4chint21hcsegendsendStart5-6dsegsegmentMsg1db"Hex:","$"Msg2db0dh,0ah,"Bin:","$"Bufdb5,?,5dup(?)dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axleadx,Msg1movah,9int21hleadx,Bufmovah,0ahint21hleadx,Msg2movah,9int21hmovcl,Buf+1xorch,chjcxzExitmovsi,2Next:movbl,Buf[si]cmpbl,"9"jbeOksubbl,7Ok:pushcxmovcl,4shlbl,clmovcx,4Output:movdl,"0"shlbl,1319 习题参考答案jncSkipincdlSkip:movah,2int21hloopOutputmovdl,20hmovah,2int21hpopcxincsiloopNextExit:movah,4chint21hcsegendsendStart5-7.386dsegsegmentuse16Arraydw5;元素个数dw-1,2,4,3,4;数组元素Maxdw-32768Mindw32767Sumdw0Averagedw0dsegendscsegsegmentuse16assumecs:cseg,ds:dsegStart:movax,dsegmovds,axxorecx,ecxmovcx,ArrayNext:movax,Array[ecx*2]addSum,axcmpMax,axjgeSkip1movMax,axSkip1:cmpMin,axjleSkip2movMin,axSkip2:loopNextmovax,SumcwdidivArraymovAverage,axDone:movah,4chint21hcsegendsendStart5-8(1)dsegsegmentData1db1,2,3,4,5LEN=$-Data1Data2db1,2,4,3,5Flagdb0Addr1dd?Addr2dd?dsegends319 习题参考答案csegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovsi,0movcx,LENCompare:moval,Data1[si]cmpal,Data2[si]jneDifferentincsiloopComparemovFlag,1jmpDoneDifferent:leaax,Data1[si]movwordptraddr1,axmovwordptraddr1+2,dsegleaax,Data2[si]movwordptraddr2,axmovwordptraddr2+2,dsegDone:movah,4chint21hcsegendsendStart(2)dsegsegmentData1db1,2,3,4,5LEN=$-Data1Data2db1,2,4,3,5Flagdb0Addr1dd?Addr2dd?dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axmoves,axleasi,Data1leadi,Data2movcx,LENcldrepecmpsbjneDifferentmovFlag,1jmpDoneDifferent:leaax,[si-1]movwordptraddr1,axmovwordptraddr1+2,dsleaax,[di-1]movwordptraddr2,axmovwordptraddr2+2,esDone:movah,4chint21hcsegendsendStart5-9dsegsegment319 习题参考答案Scoredw60,90,30,60,90LEN=($-Score)/2RankdwLENdup(1)dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovsi,0movcx,LENLoop1:movax,Score[si]pushcxmovcx,LENmovdi,0Loop2:cmpax,Score[di]jaeSkipincRank[si]Skip:adddi,2loopLoop2popcxaddsi,2loopLoop1movah,4chint21hcsegendsendStart5-10(1)moves,ax(2)xorch,ch(3)cmpbyteptres:[di],"B"(4)repmovsb(5)popcx(6)leadx,Buf+2第6章6-1MASM根据其操作数的类型来确定CALL指令的类型,其中,若操作数为过程名,则根据过程定义时指出的类型来确定是NEAR调用还是FAR调用。RET指令的类型由其所在过程的类型来确定。6-2dsegsegmentStringdb80,0,80dup(?)Msg1db"InputaString:","$"Msg2db0dh,0ah,"Yes","$"Msg3db0dh,0ah,"No","$"dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axleadx,Msg1callDispMsgleadx,Stringmovah,0ahint21hleasi,String+2319 习题参考答案movcl,String+1xorch,chcallDigitscmpal,0jnzYesleadx,Msg3jmpDispYes:leadx,Msg2Disp:callDispMsgmovah,4chint21h;功能:显示DS:DX所指的字符串DispMsgprocpushaxmovah,9int21hpopaxretDispMsgendp;入口参数:DS:SI=字符串首地址;CX=字符串长度;出口参数:AL。若DS:SI所指字符串为数字串,则AL=1;否则,AL=0。Digitsprocpushcxpushsixoral,alNext:cmpbyteptr[si],"0"jbDonecmpbyteptr[si],"9"jaDoneincsiloopNextmoval,1Done:popsipopcxretDigitsendpcsegendsendStart6-3SumOfArrayprocpushcxpushdxpushsimovdx,cxshldx,1adddx,2xorax,axNext:addax,[si]addsi,dxloopNextpopsipopdxpopcxretSumOfArrayendp6-4入口参数:DS:SI=以递增排序的带符号字数组的首地址319 习题参考答案CX=元素个数AX=带符号数功能:采用折半查找算法,在DS:SI所指数组中,查找AX中的带符号数。出口参数:若找到,则CF=0,且BX=该元素在数组中的序号(0,1,2,...);否则,CF=1。6-5MaxAbsprocpushaxpushcxpushsixorax,axNext:testwordptr[si],8000hjzOknegwordptr[si]Ok:cmp[si],axjleSkipmovax,[si]movdi,siSkip:addsi,2loopNextpushdspopespopsipopcxpopaxretMaxAbsendp6-6dsegsegmentNdw100SumNdw?dsegendscsegsegmentassumecs:cseg,ds:dsegStart:movax,dsegmovds,axpushaxpushNcallSumpopSumNmovah,4chint21hSumprocpushbpmovbp,sppushaxpushcxmovcx,4[bp]movax,0Next:addax,cxloopNextmov6[bp],axpopcxpopaxpopbp319 习题参考答案ret2SumendpcsegendsendStart6-7Printprocfarpushbpmovbp,sppushaxpushbxpushdxpusheslesbx,2[bp]PutChar:movdl,es:[bx]cmpdl,0jzEndStringmovah,2int21hincbxjmpPutCharEndString:incbxmov2[bp],bxpopespopdxpopbxpopaxpopbpretPrintendp6-8函数CFunc1对应的汇编语言代码如下:Para_iequ4[bp]Para_jequ6[bp]Para_kequ8[bp]CFunc1procnearpushbpmovbp,sppushaxpushbxmovbx,Para_imovax,Para_jaddax,Para_kmov[bx],axpopbxpopaxpopbpret6CFunc1endp调用语句CFunc1(a,3,4);对应的汇编语言代码如下:movax,4pushaxmovax,3pushaxmovax,offsetapushaxcallCFunc1319 习题参考答案6-9dsegsegmentIdw?Jdw6Kdw2dsegendscseg1segmentassumecs:cseg1,ds:dsegStart:movax,dsegmovds,axcallAdditionddI,J,Kmovah,4chint21hcseg1endscseg2segmentassumecs:cseg2Additionprocfarpushbpmovbp,sppushaxpushbxpushsipushdspushesldssi,[bp+2];取返回地址CS:IP到DS:SIlesbx,[si+4];取J的地址到ES:BXmovax,es:[bx];取J的值lesbx,[si+8];取K的地址到ES:BXaddax,es:[bx]lesbx,[si];取I的地址到ES:BXmoves:[bx],ax;存储结果addsi,12mov[bp+2],si;修改返回地址popespopdspopsipopbxpopaxpopbpretAdditionendpcseg2endsendStart6-10callProcPtr[ebx*4]6-11dsegsegmentNdw100SumNdw?dsegendsssegsegmentstackdw1024dup(?)ssegends319 习题参考答案csegsegmentassumecs:cseg,ds:dseg,ss:ssegStart:movax,dsegmovds,axpushaxpushNcallSummovSumN,axmovah,4chint21h;入口参数:N(16位,调用前进栈);出口参数:AX=Sum(N)Parm_Nequ4[bp]Sumprocpushbpmovbp,spmovax,Parm_Ncmpax,0jzExitdecaxpushax;参数N-1进栈callSumaddax,Parm_N;N+Sum(N-1)Exit:popbpret2SumendpcsegendsendStart第7章7-1CrLfmacropushaxpushdxmovdl,0dhmovah,2int21hmovdl,0ahmovah,2int21hpopaxendm7-2MoveStrmacroFrom,TolocalNext,Donepushaxpushsipushdileasi,Fromleadi,ToNext:moval,[si]mov[di],alcmpal,0jzDone319 习题参考答案incsiincdijmpNextDone:popdipopsipopaxendm7-3(1)movcl,4shrax,cl(2)shlbx,17-4DATA=0repeat100dw0dwDATADATA=DATA+2endm7-5(1)dsegsegmentMsg1db"MessageNo.1$"Msg2db"MessageNo.2$"Msg3db"MessageNo.3$"Msg4db"MessageNo.4$"Msg5db"MessageNo.5$"dsegends(2)dsegsegmentforcNo,<12345>MsgNNoendmdsegends(3)dsegsegmentNo=1repeat5MsgN%NoNo=No+1endmdsegends7-6宏定义:InitSegmacroDsegName,EsegNamepushaxmovax,DsegNamemovds,axifnbmovax,EsegNamemoves,axendifpopaxendm319 习题参考答案宏调用例:(1)将DS与ES的值分别设置为dseg与eseg段的段地址。InitSegdseg,eseg(2)将DS的值设置为dseg段的段地址。InitSegdseg7-7相同之处:都只有1个段。不同之处:TINY模型的段是16位,长度≤64KB;FLAT模型的段是32位,长度≤4GB。7-8段装入内存的顺序如下。段SSEG:由模块#1和模块#3的段SSEG组合而成,类别为"STACK"。段DSEG:由模块#1和模块#3的段DSEG组合而成,类别为"DATA"。段DSEG:模块#2的私有段DSEG,类别为"DATA"。段CSEG1:模块#1的段CSEG,类别为"CODE"。段CSEG2:模块#2的段CSEG,类别为"CODE"。段CSEG3:模块#3的段CSEG,类别为"CODE"。7-9(1)GRADEstructScoredw?;成绩Rankdw?;名次GRADEendsdsegsegmentparapublic"data"Scoresdw60,90,30,60,90LEN=($-Scores)/2GradesGRADELENdup({,1})dsegendscsegsegmentparapublic"code"assumecs:cseg,ds:dsegStart:movax,dsegmovds,ax;设置Grades的初始值movsi,0movdi,0movcx,LENInit:movax,Scores[si]movGrades[di].Score,axaddsi,2adddi,typeGRADEloopInitleasi,Gradesmovcx,LENcallRankingmovah,4chint21h;入口参数:DS:SI=GRADE结构数组的首地址;CX=元素个数319 习题参考答案;功能:求出数组中每个成绩(字段Score)所处的名次,存入相应的Rank字段Rankingproccmpcx,1jbeExitpushaxpushcxpushsipushdideccxLoop1:movax,[si].GRADE.Scorepushcxleadi,[si+typeGRADE]Loop2:cmpax,[di].GRADE.ScorejeNextjaSkipinc[si].GRADE.RankjmpNextSkip:inc[di].GRADE.RankNext:adddi,typeGRADEloopLoop2popcxaddsi,typeGRADEloopLoop1popdipopsipopcxpopaxExit:retRankingendpcsegendsendStart(2).modelsmallGRADEstructScoredw?;成绩Rankdw?;名次GRADEends.dataScoresdw6,9,3,6,9LEN=($-Scores)/2GradesGRADELENdup({,1}).codeStart:…;同(1)endStart(3);Common.incexterndefRanking:farGRADEstructScoredw?;成绩Rankdw?;名次GRADEends;Proc.asmincludecommon.inccseg1segmentparapublic"code"assumecs:cseg1Rankingprocfar…;同(1)319 习题参考答案Rankingendpcseg1endsend;Main.asmincludecommon.incdsegsegmentparapublic"data"…;同(1)dsegendscsegsegmentparapublic"code"assumecs:cseg,ds:dsegStart:…;同(1)callRankingmovah,4chint21hcsegendsendStartmakefile文件的内容如下:rank.exe:main.objproc.objml/Zi/Ferank.exemain.objproc.objmain.obj:main.asmcommon.incml/cmain.asmproc.obj:proc.asmcommon.incml/cproc.asm(4)源文件同(3)。可执行文件的建立过程如下:①将Proc.asm汇编成Proc.obj文件ml/cProc.asm②生成库文件Proc.liblibProc.lib+Proc.obj③建立可执行文件mlMain.asmProc.lib第8章8-1(1)moval,38hout25h,al(2)movdx,1042hinax,dxmovBuf,ax(3)moveax,12345678hout50h,eax8-2PORT_ST1equ25hPORT_IN1equ26hPORT_ST2equ35hPORT_IN2equ36h319 习题参考答案LENequ100dsegsegmentparapublic"data"Buf1dbLENdup(?)Buf2dbLENdup(?)dsegendscsegsegmentparapublic"code"assumecs:cseg,ds:dsegStart:movax,dsegmovds,axmovsi,0movdi,0Next:movax,siaddax,dicmpax,LEN*2jeExitcmpsi,LENjeDev2inal,PORT_ST1testal,1jzDev2inal,PORT_IN1movBuf1[si],alincsiDev2:cmpdi,LENjeDoneinal,PORT_ST2testal,1jzDoneinal,PORT_IN2movBuf2[di],alincdiDone:jmpNextExit:movah,4chint21hcsegendsendStart8-3指令IRET与RET的主要区别:●IRET要恢复标志寄存器FLAGS;●IRET是段间返回。8-4CPU响应可屏蔽中断的条件:●硬件设备发出中断请求;●中断请求未被屏蔽,即相应设备的中断屏蔽位为0;●CPU允许中断,即IF=1;●CPU在现行指令执行完毕后,才响应中断。8-5inal,21horal,02hout21h,al8-6(1)对于.com文件,PSP与程序本身处于同一个段,使用伪指令ORG100H的目的是为PSP预留100H个字节的内存空间。319 习题参考答案(2)由于中断调用时会自动将IF清0,因此,在ISR的执行过程中,只有开中断后,CPU才能再次响应硬件中断。(3)对于硬件中断服务程序,应在返回之前,向中断控制器发送中断结束命令。具体方法如下:moval,20hout20h,al;对于IRQ8~15,使用端口0A0H8-7(1)movax,0moves,axclimovwordptres:[N*4],offsetNewISRmovwordptres:[N*4+2],segNewISRsti(2)movdx,segNewISRmovds,dxleadx,NewISRmoval,Nmovah,25hint21h8-8HeadPtrequds:[1ah]TailPtrequds:[1ch]Bufferequ1ehEndBufequ3ehBufSegequ40h;功能:从键盘缓冲区读一键,若缓冲区为空,则等待。;入口参数:无;出口参数:AX=16位按键信息ReadKeyprocpushdspushbxmovax,BufSegmovds,axWaitKey:movbx,HeadPtrcmpbx,TailPtrjeWaitKey;等待按键;修改键盘缓冲区头指针HeadPtrclimovbx,HeadPtrmovax,[bx]addbx,2cmpbx,EndBufjbNoWrapmovbx,BufferNoWrap:movHeadPtr,bxstipopbxpopdsretReadKeyendp8-9319 习题参考答案.386optionsegment:use16IntNoequ9CRequ0dhLFequ0ahDelScanCodeequ53hEscScanCodeequ01hCtrlBitequ4AltBitequ8KbdFlagsequbyteptrds:[17h]BootFlagequwordptrds:[72h]csegsegmentparapublic"code"assumecs:cseg,ds:csegorg100hStart:jmpInitOldInt9dd?MyInt9procfarstipushdspushaxpushcxmovax,40hmovds,axxorcx,cxWaitData:inal,64htestal,01bloopzWaitDatajzQuitInt9inal,60hcmpal,EscScanCode;是Esc键吗?jneTryDelmovBootFlag,1234h;热启动标志(跳过内存检查)jmpdwordptrcs:RebootAddrRebootAddrdd0ffff0000hTryDel:cmpal,DelScanCode;是Delete键吗?jneOrigInt9moval,KbdFlags;判断Ctrl+Alt是否按下andal,AltBitorCtrlBitcmpal,AltBitorCtrlBitjneOrigInt9callPrintdb"Ctrl-Alt-Deldetected.",CR,LF,0QuitInt9:moval,20hout20h,al;发送中断结束信号popcxpopaxpopdsiretOrigInt9:popcxpopaxpopdspushfcallcs:OldInt9iretMyInt9endp319 习题参考答案Printprocpushbpmovbp,sppushaxpushbxmovbx,2[bp]PrintChar:moval,cs:[bx]cmpal,0jzDonemovah,0ehint10hincbxjmpPrintCharDone:incbxmov2[bp],bxpopbxpopaxpopbpretPrintendpInit:movax,0moves,axclimovax,es:[IntNo*4]movwordptrOldInt9,axmovax,es:[IntNo*4+2]movwordptrOldInt9+2,axmoves:[IntNo*4],offsetMyInt9moves:[IntNo*4+2],cssti;显示安装信息callPrintdb"NewInt9ISRInstalled.",CR,LF,0;终止并驻留movax,offsetInitshrdx,4movax,3100hint21hcsegendsendStart8-10IntNoequ9hEscCodeequ81hLowDigitScanequ02hHighDigitScanequ0bhShiftBitsequ11bKbdFlagsequbyteptrds:[17h]csegsegmentparapublic"code"assumecs:cseg,ds:csegOldInt9dd?ScanCodedb0Mainprocmovax,csegmovds,ax319 习题参考答案movax,0moves,ax;保存原中断向量movax,es:[IntNo*4]movwordptrOldInt9,axmovax,es:[IntNo*4+2]movwordptrOldInt9+2,ax;设置新中断向量climoves:[IntNo*4],offsetMyInt9moves:[IntNo*4+2],csstiWaiting:cmpScanCode,EscCodejneWaiting;恢复原中断向量climovax,wordptrOldInt9moves:[IntNo*4],axmovax,wordptrOldInt9+2moves:[IntNo*4+2],axstimovax,4c00hint21hMainendp;Int9键盘ISR;检测用户按下的键。若是数字键且当前Shift键未按下,则显示相应的数字字符。;然后,调用原INT9ISR。MyInt9procfarstipushdspushaxpushcxmovax,40hmovds,axxorcx,cxWaitData:inal,64htestal,01bloopzWaitDatajzQuitInt9inal,60h;读扫描码movcs:ScanCode,alcmpal,LowDigitScanjbOrigInt9cmpal,HighDigitScanjaOrigInt9movdl,KbdFlags;判断Shift是否按下anddl,ShiftBitsjnzOrigInt9callDispDigit;显示数字字符OrigInt9:popcxpopaxpopdspushfcallcs:OldInt9319 习题参考答案iretQuitInt9:moval,20hout20h,al;发送中断结束信号popcxpopaxpopdsiretMyInt9endp;入口参数:AL=数字字符的扫描码;功能:显示AL中的扫描码所对应的数字字符DispDigitprocpushaxpushcxdecalcmpal,0ahjneSkipmoval,0Skip:addal,30hmovah,0ehint10hpopcxpopaxretDispDigitendpcsegendsendMain8-11IntNoequ9CRequ0dhLFequ0ahLowDigitScanequ02hHighDigitScanequ0bhShiftBitsequ11bKbdFlagsequbyteptrds:[17h]csegsegmentparapublic"code"OldInt9dd?;Int9键盘ISR;检测用户按下的键。若是主键盘上的数字键且当前Shift键未按下,则忽略。;否则,传递给原INT9ISR。MyInt9procfarstipushdspushaxpushcxmovax,40hmovds,axxorcx,cxWaitData:inal,64htestal,01bloopzWaitDatajzQuitInt9inal,60h;读扫描码cmpal,LowDigitScanjbOrigInt9cmpal,HighDigitScan319 习题参考答案jaOrigInt9movdl,KbdFlags;判断Shift是否按下anddl,ShiftBitsjnzOrigInt9QuitInt9:moval,20hout20h,al;发送中断结束信号popcxpopaxpopdsiretOrigInt9:popcxpopaxpopdspushfcallcs:OldInt9iretMyInt9endpcsegendsEndResidentsegmentparapublic"EndRes"EndResidentendscseg1segmentparapublic"code1"assumecs:cseg1,ds:csegPSPdw?Mainprocmovcs:PSP,dsmovax,csegmovds,axmovax,0moves,axclimovax,es:[IntNo*4]movwordptrOldInt9,axmovax,es:[IntNo*4+2]movwordptrOldInt9+2,axmoves:[IntNo*4],offsetMyInt9moves:[IntNo*4+2],dssti;显示安装信息callPrintdb"KeyFilterInstalled.",CR,LF,0;终止并驻留movdx,EndResidentsubdx,cs:PSPmovax,3100hint21hMainendpPrintprocpushbpmovbp,sppushaxpushbxmovbx,2[bp]PrintChar:moval,cs:[bx]319 习题参考答案cmpal,0jzDonemovah,0ehint10hincbxjmpPrintCharDone:incbxmov2[bp],bxpopbxpopaxpopbpretPrintendpcseg1endsssegsegmentparastack"stack"dw512dup(?)ssegendsendMain第9章9-1在32位保护模式下,程序中使用48位逻辑地址(或虚拟地址),包括16位段选择符和32位偏移地址。其中,16位段选择符通常在某个段寄存器中。9-2在实模式下,段寄存器存放的是16位段地址;在保护模式下,段寄存器存放的是16位段选择符。9-3根据程序中的48位逻辑地址,CPU使用其中的16位段选择符检索描述符表。描述符表中的每一项是段描述符,包含了段的基地址。CPU取出描述符中的32位基地址,加上逻辑地址中的32位偏移地址,得到一种中间形式的地址,被称为线性地址。若系统未启用分页机制,则线性地址就是物理地址;否则,由分页部件再转换成物理地址。物理地址才是真正放到总线上并被内存译码的地址。9-4设中断号为n,则在实模式下,中断向量(即中断服务程序入口地址)所在地址为4n~4n+3,其中存放的4个字节就是中断服务程序入口的32位分段地址。在保护模式下,首先根据中断号n与IDTR寄存器,从IDT中定位相应的门描述符,即中断门描述符地址=IDT起始地址+n×88字节中断门描述符中存放的16位段选择符与32位偏移地址就构成了中断服务程序入口的48位逻辑地址。9-5对于运行在低特权级下的应用程序,其操作要受到如下限制:(1)不能使用特权指令,如LGDT,LLDT,LIDT和HLT等;(2)只有当前特权级(CPL)≤I/O特权级(IOPL)时,才能执行I/O敏感指令,包括IN,INS,OUT,OUTS,CLI和STI。9-6(1)采用INVOKE:invokeFunc,param1,param2,param3319 习题参考答案(2)采用CALL:pushparam3pushparam2pushparam1callFunc9-7Win32下的应用程序设计要点:(1)Win32程序运行在32位保护模式下,采用平展(Flat)内存模型,使用32位线性地址,没有分段的概念,一般不需要使用段寄存器;(2)应用程序运行在特权级3,不能使用特权指令,必须经过操作系统的门机制,才能进入核心级;(3)应用程序需要调用大量的Win32API函数;(4)Win32API函数的返回值(如果有)在寄存器EAX中,且采用STDCALL调用约定,即通过堆栈传递参数,参数的传递顺序是从右到左,并由函数本身调整堆栈指针。第10章10-1__cdecl调用约定在函数名前自动加一个下划线,从右到左将实在参数压入堆栈,由函数的调用者进行堆栈的平衡。__stdcall调用约定从右到左将实在参数压入堆栈,由函数本身移去调用者压入堆栈的参数,函数名在编译后被转换为“_函数名@参数长度”的形式,其中,参数长度是指参数表的字节数(用十进制表示)。10-2由于每个模块要单独编译或汇编,因此在连接之前,每个模块都不知道其他模块的任何信息。如果不指出模块中要使用的外部函数的参数个数、类型和返回值类型以及外部变量类型,编译器或汇编器就无法对外部函数或变量的使用进行合法性检查。10-3由于该程序的函数max采用缺省的__cdecl调用约定,由函数的调用者负责堆栈的平衡,因此,在max函数返回时不会将调用者进栈的参数(占8个字节)从栈中弹出。main函数在调用max后,将堆栈指针esp的值加8,目的就是调整堆栈指针,使堆栈保持平衡。10-4输出结果是10。10-5(1)#include#defineN10inta[N]={1,2,3,4,5,6,7,8,9,10};voidmain(void){intsum;__asm{movsum,0movecx,Nleaeax,anext:movedx,[eax]319 习题参考答案addsum,edxaddeax,4loopnext}printf("sum=%dn",sum);}(2)#include#defineN10inta[N]={1,2,3,4,5,6,7,8,9,10};intsum(int*a,intn);voidmain(void){printf("sum=%dn",sum(a,N));}intsum(int*a,intn){__asm{moveax,0movecx,nmovedx,anext:addeax,[edx]addedx,4loopnext}}(3)//C程序#include#defineN10inta[N]={1,2,3,4,5,6,7,8,9,10};extern"C"int__stdcallsum(int*a,intn);voidmain(void){printf("sum=%dn",sum(a,N));};汇编语言程序:sum.asm.386public_sum@8_TEXTsegmentparapublic"code"assumecs:_TEXTParam_aequ8[ebp]Param_nequ12[ebp]_sum@8procpushebpmovebp,espmoveax,0movecx,Param_nmovedx,Param_anext:addeax,[edx]addedx,4loopnextpopebpret8_sum@8endp_TEXTendsEnd319 习题参考答案(4)#include#defineN10inta[N]={1,2,3,4,5,6,7,8,9,10};intsum(int*a,intn);voidmain(void){ints=0;__asm{moveax,Npusheaxleaeax,apusheaxcallsumaddesp,8movs,eax}printf("sum=%dn",s);}intsum(int*a,intn){inti,s=0;for(i=0;i