• 2.19 MB
  • 2022-04-22 11:38:11 发布

《汇编语言》第二版习题答案(全) 王爽编写.doc

  • 144页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'检测点1.1(1)1个CPU的寻址能力为8KB,那么它的地址总线的宽度为13位。(2)1KB的存储器有1024个存储单元,存储单元的编号从0到1023。(3)1KB的存储器可以存储8192(2^13)个bit,1024个Byte。(4)1GB是1073741824(2^30)个Byte、1MB是1048576(2^20)个Byte、1KB是1024(2^10)个Byte。(5)8080、8088、80296、80386的地址总线宽度分别为16根、20根、24根、32根,则它们的寻址能力分别为:64(KB)、1(MB)、16(MB)、4(GB)。(6)8080、8088、8086、80286、80386的数据总线宽度分别为8根、8根、16根、16根、32根。则它们一次可以传送的数据为:1(B)、1(B)、2(B)、2(B)、4(B)。(7)从内存中读取1024字节的数据,8086至少要读512次,80386至少要读256次。(8)在存储器中,数据和程序以二进制形式存放。解题过程:(1)1KB=1024B,8KB=1024B*8=2^N,N=13。(2)存储器的容量是以字节为最小单位来计算的,1KB=1024B。(3)8Bit=1Byte,1024Byte=1KB(1KB=1024B=1024B*8Bit)。(4)1GB=1073741824B(即2^30)1MB=1048576B(即2^20)1KB=1024B(即2^10)。(5)一个CPU有N根地址线,则可以说这个CPU的地址总线的宽度为N。这样的CPU最多可以寻找2的N次方个内存单元。(一个内存单元=1Byte)。(6)8根数据总线一次可以传送8位二进制数据(即一个字节)。(7)8086的数据总线宽度为16根(即一次传送的数据为2B)1024B/2B=512,同理1024B/4B=256。(8)在存储器中指令和数据没有任何区别,都是二进制信息。检测点2.1(1)写出每条汇编指令执行后相关寄存器中的值。movax,62627AX=F4A3Hmovah,31HAX=31A3Hmoval,23HAX=3123Haddax,axAX=6246Hmovbx,826CHBX=826CHmovcx,axCX=6246Hmovax,bxAX=826CHaddax,bxAX=04D8Hmoval,bhAX=0482Hmovah,blAX=6C82Haddah,ahAX=D882Haddal,6AX=D888Haddal,alAX=D810Hmovax,cxAX=6246HMicrosoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debug -a0C1C:0100movax,f4a30C1C:0103movah,310C1C:0105moval,230C1C:0107addax,ax0C1C:0109movbx,826c0C1C:010Cmovcx,ax0C1C:010Emovax,bx0C1C:0110addax,bx0C1C:0112moval,bh0C1C:0114movah,bl0C1C:0116addah,ah0C1C:0118addal,60C1C:011Aaddal,al0C1C:011Cmovax,cx0C1C:011E-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0100NVUPEIPLNZNAPONC0C1C:0100B8A3F4MOVAX,F4A3-tAX=F4A3BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0103NVUPEIPLNZNAPONC0C1C:0103B431MOVAH,31-tAX=31A3BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0105NVUPEIPLNZNAPONC0C1C:0105B023MOVAL,23-tAX=3123BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0107NVUPEIPLNZNAPONC0C1C:010701C0ADDAX,AX-tAX=6246BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0109NVUPEIPLNZNAPONC0C1C:0109BB6C82MOVBX,826C-tAX=6246BX=826CCX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010CNVUPEIPLNZNAPONC0C1C:010C89C1MOVCX,AX-tAX=6246BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010ENVUPEIPLNZNAPONC0C1C:010E89D8MOVAX,BX -tAX=826CBX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0110NVUPEIPLNZNAPONC0C1C:011001D8ADDAX,BX-tAX=04D8BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0112OVUPEIPLNZACPECY0C1C:011288F8MOVAL,BH-tAX=0482BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0114OVUPEIPLNZACPECY0C1C:011488DCMOVAH,BL-tAX=6C82BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0116OVUPEIPLNZACPECY0C1C:011600E4ADDAH,AH-tAX=D882BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0118OVUPEINGNZACPENC0C1C:01180406ADDAL,06-tAX=D888BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=011ANVUPEINGNZNAPENC0C1C:011A00C0ADDAL,AL-tAX=D810BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=011COVUPEIPLNZACPOCY0C1C:011C89C8MOVAX,CX-tAX=6246BX=826CCX=6246DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=011EOVUPEIPLNZACPOCY0C1C:011E0B0CORCX,[SI]DS:0000=20CD-q检测点2.1(2)只能使用目前学过的汇编指令,最多使用4条指令,编程计算2的4次方。movax,2AX=2addax,axAX=4addax,axAX=8addax,axAX=16Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001. C:DOCUME~1ADMINI~1>debug-a0C1C:0100movax,20C1C:0103addax,ax0C1C:0105addax,ax0C1C:0107addax,ax0C1C:0109-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0100NVUPEIPLNZNAPONC0C1C:0100B80200MOVAX,0002-tAX=0002BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0103NVUPEIPLNZNAPONC0C1C:010301C0ADDAX,AX-tAX=0004BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0105NVUPEIPLNZNAPONC0C1C:010501C0ADDAX,AX-tAX=0008BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0107NVUPEIPLNZNAPONC0C1C:010701C0ADDAX,AX-tAX=0010BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0109NVUPEIPLNZACPONC0C1C:010920881615AND[BX+SI+1516],CLDS:1516=00-q检测点2.2(1)给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为0010H到1000FH。解题过程:物理地址=SA*16+EAEA的变化范围为0h~ffffh物理地址范围为(SA*16+0h)~(SA*16+ffffh)现在SA=0001h,那么寻址范围为(0001h*16+0h)~(0001h*16+ffffh)=0010h~1000fh检测点2.2(2)有一数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为1001H,最大为2000H。当段地址给定为 1001H以下和2000H以上,CPU无论怎么变化偏移地址都无法寻到20000H单元。 解题过程:物理地址=SA*16+EA20000h=SA*16+EASA=(20000h-EA)/16=2000h-EA/16EA取最大值时,SA=2000h-ffffh/16=1001h,SA为最小值EA取最小值时,SA=2000h-0h/16=2000h,SA为最大值这里的ffffH/16=fffh是通过WIN自带计算器算的按位移来算确实应该为fff.fh,这里小数点后的f应该是省略了单就除法来说,应有商和余数,但此题要求的是地址最大和最小,所以余数忽略了如果根据位移的算法(段地址*16=16进制左移一位),小数点后应该是不能省略的我们可以反过来再思考下,如果SA为1000h的话,小数点后省略SA=1000h,EA取最大ffffh,物理地址为1ffffh,将无法寻到20000H单元这道题不应看成是单纯的计算题检测点2.3下面的3条指令执行后,cpu几次修改IP?都是在什么时候?最后IP中的值是多少?movax,bxsubax,axjmpax答:一共修改四次第一次:读取movax,bx之后第二次:读取subax,ax之后第三次:读取jmpax之后第四次:执行jmpax修改IP最后IP的值为0000H,因为最后ax中的值为0000H,所以IP中的值也为0000H实验一查看CPU和内存,用机器指令和汇编指令编程2实验任务(1)使用Debug,将下面的程序段写入内存,逐条执行,观察每条指令执行后,CPU中相关寄存器中内容的变化。机器码汇编指令寄存器b8204emovax,4E20Hax=4E20H051614addax,1416Hax=6236Hbb0020movBX,2000Hbx=2000H01d8addax,bxax=8236H89c3movbx,axbx=8236H01d8addax,bxax=046CHb81a00movax,001AHax=001AHbb2600movbx,0026Hbx=0026H00d8addal,blax=0040H00dcaddah,blax=2640H00c7addbh,albx=4026Hb400movah,0ax=0040H 00d8addal,blax=0066H049caddal,9CHax=0002HMicrosoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debug-a0C1C:0100movax,4e200C1C:0103addax,14160C1C:0106movbx,20000C1C:0109addax,bx0C1C:010Bmovbx,ax0C1C:010Daddax,bx0C1C:010Fmovax,001a0C1C:0112movbx,00260C1C:0115addal,bl0C1C:0117addah,bl0C1C:0119addbh,al0C1C:011Bmovah,00C1C:011Daddal,bl0C1C:011Faddal,9c0C1C:0121-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0100NVUPEIPLNZNAPONC0C1C:0100B8204EMOVAX,4E20-tAX=4E20BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0103NVUPEIPLNZNAPONC0C1C:0103051614ADDAX,1416-tAX=6236BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0106NVUPEIPLNZNAPENC0C1C:0106BB0020MOVBX,2000-tAX=6236BX=2000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0109NVUPEIPLNZNAPENC0C1C:010901D8ADDAX,BX-tAX=8236BX=2000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010BOVUPEINGNZNAPENC0C1C:010B89C3MOVBX,AX-tAX=8236BX=8236CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000 DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010DOVUPEINGNZNAPENC0C1C:010D01D8ADDAX,BX-tAX=046CBX=8236CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010FOVUPEIPLNZNAPECY0C1C:010FB81A00MOVAX,001A-tAX=001ABX=8236CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0112OVUPEIPLNZNAPECY0C1C:0112BB2600MOVBX,0026-tAX=001ABX=0026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0115OVUPEIPLNZNAPECY0C1C:011500D8ADDAL,BL-tAX=0040BX=0026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0117NVUPEIPLNZACPONC0C1C:011700DCADDAH,BL-tAX=2640BX=0026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0119NVUPEIPLNZNAPONC0C1C:011900C7ADDBH,AL-tAX=2640BX=4026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=011BNVUPEIPLNZNAPONC0C1C:011BB400MOVAH,00-tAX=0040BX=4026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=011DNVUPEIPLNZNAPONC0C1C:011D00D8ADDAL,BL-tAX=0066BX=4026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=011FNVUPEIPLNZNAPENC0C1C:011F049CADDAL,9C-tAX=0002BX=4026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0121NVUPEIPLNZACPOCY0C1C:0121D3990075RCRWORDPTR[BX+DI+7500],CLDS:B526=0000-q实验一查看CPU和内存,用机器指令和汇编指令编程(2)将下面的3条指令写入从2000:0开始的内存单元中,利用这3条指令计算2的8次方。movax,1addax,axjmp2000:0003 Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debug-a2000:02000:0000movax,12000:0003addax,ax2000:0005jmp2000:00032000:0007-rcsCS0C1C:2000-ripIP0100:0000-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0000NVUPEIPLNZNAPONC2000:0000B80100MOVAX,0001-tAX=0001BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0003NVUPEIPLNZNAPONC2000:000301C0ADDAX,AX-tAX=0002BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0005NVUPEIPLNZNAPONC2000:0005EBFCJMP0003-tAX=0002BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0003NVUPEIPLNZNAPONC2000:000301C0ADDAX,AX-tAX=0002BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0003NVUPEIPLNZNAPONC2000:000301C0ADDAX,AX-tAX=0004BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0005NVUPEIPLNZNAPONC2000:0005EBFCJMP0003-tAX=0004BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0003NVUPEIPLNZNAPONC2000:000301C0ADDAX,AX-t AX=0008BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0005NVUPEIPLNZNAPONC2000:0005EBFCJMP0003-tAX=0008BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=2000IP=0003NVUPEIPLNZNAPONC2000:000301C0ADDAX,AX-q实验一查看CPU和内存,用机器指令和汇编指令编程(3)查看内存中的内容PC主板上的ROM中有个一出产日期,在内存FFF00H-FFFFFH的某几个单元中,请找到这个出产日期并试图改变它。Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debug-dffff:0fFFFF:0000EA5BE000F031322F-32352F303700FC59.[...12/25/07..Y-q地址C0000~FFFFF的内存单元为只读存储器,写入数据操作是无效的。因此出产日期无法改变。下面内容摘自于网上还有另一种情况,如果你发现你能修改ROM中的生产日期,那么原因如下:每个计算机的结构都不一样,教材考虑的是普通8086PC机上的效果,个别计算机的效果可能不同。也就是说在你的计算机中这个内存是可修改的所以,认为所有的计算机某些地址的内存不能修改是片面的。书上说rom是只读的你就不去验证了吗?如何验证呢?我觉得这个实验最大的好处不是让我们验证了这个知识点,而是提醒我们要有怀疑的精神,怀疑之后再去验证才能跟深刻的理解知识,提升自己的能力,甚至还会发现有些书上描述的不准确甚至错误的地方。--引用这几本书综合研究的三个问题:都再用,我们就非得用吗?规定了,我们就只知道遵守吗?司空见惯,我们就不怀疑了吗?尽信书不如无书大概也有这个道理吧^_^检测点3.1(1)在DEBUG中,用"D0:0lf"查看内存,结果如下:0000:00007080F030EF6030E2-00808012662022600000:00106226E6D6CC2E3C3B-ABBA000026066688下面的程序执行前,AX=0,BX=0,写出每条汇编指令执行完后相关寄存器中的值movax,1 movds,axmovax,[0000]ax=2662Hmovbx,[0001]bx=E626Hmovax,bxax=E626Hmovax,[0000]ax=2662Hmovbx,[0002]bx=D6E6Haddax,bxax=FD48Haddax,[0004]ax=2C14Hmovax,0ax=0moval,[0002]ax=00e6Hmovbx,0bx=0movbl,[000c]bx=0026Haddal,blax=000CH用DEBUG进行验证:Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~100>debug-e0000:00000:000068.7010.80A7.f000.308B.ef01.6070.3000.e20000:000816.0000.80AF.8003.128B.6601.2070.2200.600000:00108B.6201.2670.e600.d6B9.cc06.2e14.3c02.3b0000:001840.ab07.ba14.0002.00FF.2603.0614.6602.88-d0000:01f0000:00007080F030EF6030E2-0080801266202260p..0.`0.....f"`0000:00106226E6D6CC2E3C3B-ABBA000026066688b&....<;....&.f.-a0DB4:0100movax,10DB4:0103movds,ax0DB4:0105movax,[0000]0DB4:0108movbx,[0001]0DB4:010Cmovax,bx0DB4:010Emovax,[0000]0DB4:0111movbx,[0002]0DB4:0115addax,bx0DB4:0117addax,[0004]0DB4:011Bmovax,00DB4:011Emoval,[0002]0DB4:0121movbx,00DB4:0124movbl,[000c]0DB4:0128addal,bl0DB4:012A-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0DB4ES=0DB4SS=0DB4CS=0DB4IP=0100NVUPEIPLNZNAPONC0DB4:0100B80100MOVAX,0001-tAX=0001BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0DB4ES=0DB4SS=0DB4CS=0DB4IP=0103NVUPEIPLNZNAPONC0DB4:01038ED8MOVDS,AX-tAX=0001BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0105NVUPEIPLNZNAPONC0DB4:0105A10000MOVAX,[0000]DS:0000=2662-tAX=2662BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0108NVUPEIPLNZNAPONC0DB4:01088B1E0100MOVBX,[0001]DS:0001=E626-t AX=2662BX=E626CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=010CNVUPEIPLNZNAPONC0DB4:010C89D8MOVAX,BX-tAX=E626BX=E626CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=010ENVUPEIPLNZNAPONC0DB4:010EA10000MOVAX,[0000]DS:0000=2662-tAX=2662BX=E626CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0111NVUPEIPLNZNAPONC0DB4:01118B1E0200MOVBX,[0002]DS:0002=D6E6-tAX=2662BX=D6E6CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0115NVUPEIPLNZNAPONC0DB4:011501D8ADDAX,BX-tAX=FD48BX=D6E6CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0117NVUPEINGNZNAPENC0DB4:011703060400ADDAX,[0004]DS:0004=2ECC-tAX=2C14BX=D6E6CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=011BNVUPEIPLNZACPECY0DB4:011BB80000MOVAX,0000-tAX=0000BX=D6E6CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=011ENVUPEIPLNZACPECY0DB4:011EA00200MOVAL,[0002]DS:0002=E6-tAX=00E6BX=D6E6CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0121NVUPEIPLNZACPECY0DB4:0121BB0000MOVBX,0000-tAX=00E6BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0124NVUPEIPLNZACPECY0DB4:01248A1E0C00MOVBL,[000C]DS:000C=26-tAX=00E6BX=0026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=0128NVUPEIPLNZACPECY0DB4:012800D8ADDAL,BL-tAX=000CBX=0026CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0001ES=0DB4SS=0DB4CS=0DB4IP=012ANVUPEIPLNZNAPECY0DB4:012AC6061799FFMOVBYTEPTR[9917],FFDS:9917=9A-q检测点3.1(2)内存中的情况如图3.6所示各寄存器的初始值:cs=2000h,ip=0,ds=1000h,ax=0,bx=0;①写出CPU执行的指令序列(用汇编指令写出)。②写出CPU执行每条指令后,CS、IP和相关寄存器的数值。③再次体会:数据和程序有区别吗?如何确定内存中的信息哪些是数据,哪些是程序? 图3.6内存情况示意指令序列CSIPDSAXBX初始值2000h00001movax,6622h2000h3h06622h02jmp0ff0:0100ff0h100h06622h03movax,2000hff0h103h02000h04movds,axff0h105h2000h2000h05movax,[8]ff0h108h2000hc389h06movax,[2]ff0h10bh2000hea66h0检测点3.2(1)补全下面的程序,使其可以将10000H-1000FH中的8个字,逆序拷贝到20000H-2000FH中。movax,1000Hmovds,axmovax,2000Hmovss,axmovsp,10hpush[0]push[2]push[4]push[6]push[8]push[A]push[C]push[E]检测点3.2(2)补全下面的程序,使其可以将10000H-1000FH中的8个字,逆序拷贝到20000H-2000FH中。movax,2000H movds,axmovax,1000Hmovss,axmovsp,0pop[e]pop[c]pop[a]pop[8]pop[6]pop[4]pop[2]pop[0]实验2用机器指令和汇编指令编程(1)使用DEBUG,将上面的程序段写入内存,逐条执行,根据指令执行后的实际运行情况填空。movax,ffffmovds,axmovax,2200movss,axmovsp,0100movax,[0];ax=5BEAHaddax,[2];ax=5CCAHmovbx,[4];bx=31F0Haddbx,[6];bx=6122Hpushax;sp=00FEH,修改的内存单元地址是2200:00FE内容为5CCAHpushbx;sp=00FCH,修改的内存单元地址是2200:00FC内容为6122Hpopax;sp=00FCH,ax=6122Hpopbx;sp=00FEH,bx=5CCAHpush[4];sp=00FEH,修改的内存单元地址是2200:00FE内容为31F0push[6];sp=00FCH,修改的内存单元地址是2200:00FC内容为2F32此实验答案不定,需根据每台机器的实际运行情况。Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debug-a0C1C:0100movax,ffff0C1C:0103movds,ax0C1C:0105movax,22000C1C:0108movss,ax0C1C:010Amovsp,0100 0C1C:010Dmovax,[0]0C1C:0110addax,[2]0C1C:0114movbx,[4]0C1C:0118addbx,[6]0C1C:011Cpushax0C1C:011Dpushbx0C1C:011Epopax0C1C:011Fpopbx0C1C:0120push[4]0C1C:0124push[6]0C1C:0128-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0100NVUPEIPLNZNAPONC0C1C:0100B8FFFFMOVAX,FFFF-tAX=FFFFBX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0103NVUPEIPLNZNAPONC0C1C:01038ED8MOVDS,AX-tAX=FFFFBX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=0C1CCS=0C1CIP=0105NVUPEIPLNZNAPONC0C1C:0105B80022MOVAX,2200-tAX=2200BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=0C1CCS=0C1CIP=0108NVUPEIPLNZNAPONC0C1C:01088ED0MOVSS,AX-tAX=2200BX=0000CX=0000DX=0000SP=0100BP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=010DNVUPEIPLNZNAPONC0C1C:010DA10000MOVAX,[0000]DS:0000=5BEA-dffff:0fFFFF:0000EA5BE000F031322F-32352F303700FC59.[...12/25/07..Y-tAX=5BEABX=0000CX=0000DX=0000SP=0100BP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=0110NVUPEIPLNZNAPONC0C1C:011003060200ADDAX,[0002]DS:0002=00E0-tAX=5CCABX=0000CX=0000DX=0000SP=0100BP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=0114NVUPEIPLNZNAPENC0C1C:01148B1E0400MOVBX,[0004]DS:0004=31F0-tAX=5CCABX=31F0CX=0000DX=0000SP=0100BP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=0118NVUPEIPLNZNAPENC 0C1C:0118031E0600ADDBX,[0006]DS:0006=2F32-tAX=5CCABX=6122CX=0000DX=0000SP=0100BP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=011CNVUPEIPLNZNAPENC0C1C:011C50PUSHAX-tAX=5CCABX=6122CX=0000DX=0000SP=00FEBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=011DNVUPEIPLNZNAPENC0C1C:011D53PUSHBX-tAX=5CCABX=6122CX=0000DX=0000SP=00FCBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=011ENVUPEIPLNZNAPENC0C1C:011E58POPAX-tAX=6122BX=6122CX=0000DX=0000SP=00FEBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=011FNVUPEIPLNZNAPENC0C1C:011F5BPOPBX-tAX=6122BX=5CCACX=0000DX=0000SP=0100BP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=0120NVUPEIPLNZNAPENC0C1C:0120FF360400PUSH[0004]DS:0004=31F0-tAX=6122BX=5CCACX=0000DX=0000SP=00FEBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=0124NVUPEIPLNZNAPENC0C1C:0124FF360600PUSH[0006]DS:0006=2F32-tAX=6122BX=5CCACX=0000DX=0000SP=00FCBP=0000SI=0000DI=0000DS=FFFFES=0C1CSS=2200CS=0C1CIP=0128NVUPEIPLNZNAPENC0C1C:012816PUSHSS-q实验2用机器指令和汇编指令编程(2)仔细观察图3.19中的实验过程,然后分析:为什么2000:0~2000:F中的内容会发生改变? 图3.19用Debug进行实验的示例答:因为在debug使用T等指令引发了中断造成的,中断过程使用当前栈空间存放cpu关键数据,所以,你的栈里就有些不是你操作的数据了。这个问题后面会学到,不过这里也要有个印象,因为如果是在中断过程中压栈是栈越界的话,在windows下的命令窗口会强制关闭的。这个可能在你跟踪一些程序的时候会遇到,到时候有个思考方向。实验3编程、编译、连接、跟踪(1)将下面的程序保存为t1.asm文件,将其生成可执行文件t1.exe。assumecs:codesgcodesgsegmentmovax,2000Hmovss,axmovsp,0addsp,10popaxpopbxpushaxpushbxpopaxpopbxmovax,4c00hint21Hcodesgendsend按书中所示,从DOS进入EDIT 完成后保存文件为t1.asm 退出EDIT,进行编译,连接生成可执行文件t1.exe 实验3编程、编译、连接、跟踪(2)用DEBUG跟踪t1.exe的执行过程,写出第一步执行后,相关寄存器的内容和栈顶内容。Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debugt1.exe-rAX=0000BX=0000CX=0016DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C69ES=0C69SS=0C79CS=0C79IP=0000NVUPEIPLNZNAPONC0C79:0000B80020MOVAX,2000-tAX=2000BX=0000CX=0016DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C69ES=0C69SS=0C79CS=0C79IP=0003NVUPEIPLNZNAPONC0C79:00038ED0MOVSS,AX-tAX=2000BX=0000CX=0016DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=0008NVUPEIPLNZNAPONC0C79:000883C40AADDSP,+0A-tAX=2000BX=0000CX=0016DX=0000SP=000ABP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=000BNVUPEIPLNZNAPENC0C79:000B58POPAX-d2000:0f2000:0000002000000B00790C-8006790C8006001F.....y...y.....-tAX=0C79BX=0000CX=0016DX=0000SP=000CBP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=000CNVUPEIPLNZNAPENC0C79:000C5BPOPBX-d2000:0f 2000:00000020790C00000C00-790C80068006001F.y.....y.......-tAX=0C79BX=0680CX=0016DX=0000SP=000EBP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=000DNVUPEIPLNZNAPENC0C79:000D50PUSHAX-d2000:0f2000:00000020790C790C0000-0D00790C8006001F.y.y.....y.....-tAX=0C79BX=0680CX=0016DX=0000SP=000CBP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=000ENVUPEIPLNZNAPENC0C79:000E53PUSHBX-d2000:0f2000:00000020790C00000E00-790C8006790C001F.y.....y...y...-tAX=0C79BX=0680CX=0016DX=0000SP=000ABP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=000FNVUPEIPLNZNAPENC0C79:000F58POPAX-d2000:0f2000:0000790C00000F00790C-80068006790C001Fy.....y.....y...-tAX=0680BX=0680CX=0016DX=0000SP=000CBP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=0010NVUPEIPLNZNAPENC0C79:00105BPOPBX-d2000:0f2000:0000790C800600001000-790C8006790C001Fy.......y...y...-tAX=0680BX=0C79CX=0016DX=0000SP=000EBP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=0011NVUPEIPLNZNAPENC0C79:0011B8004CMOVAX,4C00-tAX=4C00BX=0C79CX=0016DX=0000SP=000EBP=0000SI=0000DI=0000DS=0C69ES=0C69SS=2000CS=0C79IP=0014NVUPEIPLNZNAPENC0C79:0014CD21INT21-pProgramterminatednormally-q实验3编程、编译、连接、跟踪(3)PSP的头两个字节是CD20,用DEBUG加载t1.exe,查看PSP的内容。Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1ADMINI~1>debugt1.exe -rAX=0000BX=0000CX=0016DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C69ES=0C69SS=0C79CS=0C79IP=0000NVUPEIPLNZNAPONC0C79:0000B80020MOVAX,2000-d0c69:00C69:0000CD20FF9F009AF0FE-1DF04F0380068A03.........O.....0C69:00108006170380066F06-0101010002FFFFFF......o.........0C69:0020FFFFFFFFFFFFFFFF-FFFFFFFF2D0C4C01............-.L.0C69:0030400B14001800690C-FFFFFFFF00000000@.....i.........0C69:00400500000000000000-0000000000000000................0C69:0050CD21CB0000000000-0000000000202020.!...........0C69:00602020202020202020-0000000000202020.....0C69:00702020202020202020-0000000000000000........-q检测点6.1(1)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,完成程序:assumecs:codesgcodesgsegmentdw0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hstart:movax,0movds,axmovbx,0movcx,8s:movax,[bx]movcs:[bx],axaddbx,2loopsmovax,4c00hint21hcodesgendsendstartC:DOCUME~1ADMINI~1>debugjc6-1.exe-u0C79:0010B80000MOVAX,00000C79:00138ED8MOVDS,AX0C79:0015BB0000MOVBX,00000C79:0018B90800MOVCX,00080C79:001B8B07MOVAX,[BX]0C79:001D2ECS:0C79:001E8907MOV[BX],AX0C79:002083C302ADDBX,+020C79:0023E2F6LOOP001B0C79:0025B8004CMOVAX,4C00 0C79:0028CD21INT210C79:002A7503JNZ002F0C79:002CE97BFFJMPFFAA0C79:002F5EPOPSI-g0025AX=0680BX=0010CX=0000DX=0000SP=0000BP=0000SI=0000DI=0000DS=0000ES=0C69SS=0C79CS=0C79IP=0025NVUPEIPLNZACPONC0C79:0025B8004CMOVAX,4C00-d0:0f0000:00006810A700BB138006-1600A503B1138006h...............-d0c79:0f0C79:00006810A700BB138006-1600A503B1138006h...............-tAX=4C00BX=0010CX=0000DX=0000SP=0000BP=0000SI=0000DI=0000DS=0000ES=0C69SS=0C79CS=0C79IP=0028NVUPEIPLNZACPONC0C79:0028CD21INT21-pProgramterminatednormally-qC:DOCUME~1ADMINI~1>检测点6.1(2)下面的程序实现依次用内存0:0~0:15单元中的内容改写程序中的数据,数据的传送用栈来进行。栈空间设置在程序内。完成程序:assumecs:codesgcodesgsegmentdw0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdw0,0,0,0,0,0,0,0,0,0start:movax,codesg;或movax,csmovss,axmovsp,24h;或movsp,36;(第一版填1ah或26)movax,0movds,axmovbx,0movcx,8s:push[bx]popcs:[bx];或popss:[bx]addbx,2loopsmovax,4c00hint21hcodesgendsendstart C:DOCUME~1ADMINI~1>debugjc6-1-2.exe-u0C86:0024B8860CMOVAX,0C860C86:00278ED0MOVSS,AX0C86:0029BC2400MOVSP,00240C86:002CB80000MOVAX,00000C86:002F8ED8MOVDS,AX0C86:0031BB0000MOVBX,00000C86:0034B90800MOVCX,00080C86:0037FF37PUSH[BX]0C86:00392ECS:0C86:003A8F07POP[BX]0C86:003C83C302ADDBX,+020C86:003FE2F6LOOP00370C86:0041B8004CMOVAX,4C00-g0041AX=0000BX=0010CX=0000DX=0000SP=0024BP=0000SI=0000DI=0000DS=0000ES=0C76SS=0C86CS=0C86IP=0041NVUPEIPLNZACPONC0C86:0041B8004CMOVAX,4C00-d0:0f0000:00006810A700BB138D06-1600B203B1138D06h...............-d0c86:0f0C86:00006810A700BB138D06-1600B203B1138D06h...............-q实验5编写、调试具有多个段的程序(1)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。assumecs:code,ds:data,ss:stackdatasegmentdw0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hdataendsstacksegmentdw0,0,0,0,0,0,0,0stackendscodesegmentstart:movax,stackmovss,axmovsp,16movax,datamovds,axpushds:[0]pushds:[2]popds:[2]popds:[0]movax,4c00h int21hcodeendsendstart①CPU执行程序,程序返回前,data段中的数据不变。②CPU执行程序,程序返回前,CS=0C88H,SS=0C87H,DS=0C86H。③设程序加载后,CODE段的段地址为X,则DATA段的段地址为X-2,STACK段的段地址为X-1。C:DOCUME~1ADMINI~1>debugsy5-1.exe-rAX=0000BX=0000CX=0042DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C76ES=0C76SS=0C86CS=0C88IP=0000NVUPEIPLNZNAPONC0C88:0000B8870CMOVAX,0C87-d0c86:0f0C86:0000230156048907BC0A-EF0DED0FBA0C8709#.V.............-u0C88:0000B8870CMOVAX,0C870C88:00038ED0MOVSS,AX0C88:0005BC1000MOVSP,00100C88:0008B8860CMOVAX,0C860C88:000B8ED8MOVDS,AX0C88:000DFF360000PUSH[0000]0C88:0011FF360200PUSH[0002]0C88:00158F060200POP[0002]0C88:00198F060000POP[0000]0C88:001DB8004CMOVAX,4C00-g001dAX=0C86BX=0000CX=0042DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C86ES=0C76SS=0C87CS=0C88IP=001DNVUPEIPLNZNAPONC0C88:001DB8004CMOVAX,4C00-d0c86:0f0C86:0000230156048907BC0A-EF0DED0FBA0C8709#.V.............-q实验5编写、调试具有多个段的程序(2)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。assumecs:code,ds:data,ss:stackdatasegmentdw0123h,0456hdataendsstacksegmentdw0,0stackendscodesegmentstart:movax,stack movss,axmovsp,16movax,datamovds,axpushds:[0]pushds:[2]popds:[2]popds:[0]movax,4c00hint21hcodeendsendstart①CPU执行程序,程序返回前,data段中的数据不变。②CPU执行程序,程序返回前,CS=0C88H,SS=0C87H,DS=0C86H。③设程序加载后,CODE段的段地址为X,则DATA段的段地址为X-2,STACK段的段地址为X-1。④对于如下定义的段:namesegment……nameends如果段中的数据占N个字节,则程序加载后,该段实际占有的空间为((N+15)/16)*16 。④解析:N分为被16整除和不被16整除。当N被16整除时:占有的空间为(N/16)*16当N不被16整除时:占有的空间为(N/16+1)*16,N/16得出的是可以整除的部分,还有一个余数,余数肯定小于16,加上一个16。程序加载后分配空间是以16个字节为单位的,也就是说如果不足16个字节的也分配16个字节。两种情况总结成一个通用的公式:((N+15)/16)*16 C:DOCUME~1ADMINI~1>debugsy5-2.exe-rAX=0000BX=0000CX=0042DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C76ES=0C76SS=0C86CS=0C88IP=0000NVUPEIPLNZNAPONC0C88:0000B8870CMOVAX,0C87-d0c86:030C86:000023015604#.V.-u0C88:0000B8870CMOVAX,0C870C88:00038ED0MOVSS,AX0C88:0005BC1000MOVSP,00100C88:0008B8860CMOVAX,0C860C88:000B8ED8MOVDS,AX0C88:000DFF360000PUSH[0000] 0C88:0011FF360200PUSH[0002]0C88:00158F060200POP[0002]0C88:00198F060000POP[0000]0C88:001DB8004CMOVAX,4C00-g001dAX=0C86BX=0000CX=0042DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C86ES=0C76SS=0C87CS=0C88IP=001DNVUPEIPLNZNAPONC0C88:001DB8004CMOVAX,4C00-d0c86:030C86:000023015604#.V.-q实验5编写、调试具有多个段的程序(3)将下面的程序编译连接,用Debug加载、跟踪,然后回答问题。assumecs:code,ds:data,ss:stackcodesegmentstart:movax,stackmovss,axmovsp,16movax,datamovds,axpushds:[0]pushds:[2]popds:[2]popds:[0]movax,4c00hint21hcodeendsdatasegmentdw0123h,0456hdataendsstacksegmentdw0,0stackendsendstart①CPU执行程序,程序返回前,data段中的数据不变。②CPU执行程序,程序返回前,CS=0C86H,SS=0C8AH,DS=0C89H。③设程序加载后,CODE段的段地址为X,则DATA段的段地址为X+3,STACK段的段地址为X+4。C:DOCUME~1ADMINI~1>debugsj5-3.exe-rAX=0000BX=0000CX=0044DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C76ES=0C76SS=0C86CS=0C86IP=0000NVUPEIPLNZNAPONC0C86:0000B88A0CMOVAX,0C8A -u0C86:0000B88A0CMOVAX,0C8A0C86:00038ED0MOVSS,AX0C86:0005BC1000MOVSP,00100C86:0008B8890CMOVAX,0C890C86:000B8ED8MOVDS,AX0C86:000DFF360000PUSH[0000]0C86:0011FF360200PUSH[0002]0C86:00158F060200POP[0002]0C86:00198F060000POP[0000]0C86:001DB8004CMOVAX,4C00-g001dAX=0C89BX=0000CX=0044DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C89ES=0C76SS=0C8ACS=0C86IP=001DNVUPEIPLNZNAPONC0C86:001DB8004CMOVAX,4C00-d0c89:030C89:000023015604#.V.-q实验5编写、调试具有多个段的程序(4)如果将(1)、(2)、(3)题中的最后一条伪指令“endstart”改为“end”(也就是说,不指明程序的入口),则哪个程序仍然可以正确执行?请说明原因。答:第三条程序仍然可以正确执行,如果不指明入口位置,则程序从所分配的空间开始执行,前2个是数据段,只有从第3条开始是指令代码。实验5编写、调试具有多个段的程序(5)程序如下,编写code段中代码,将a段和b段中的数据依次相加,将结果存到C段中。(三个程序)程序一:两次循环assumecs:codeasegmentdb1,2,3,4,5,6,7,8aendsbsegmentdb1,2,3,4,5,6,7,8bendscsegmentdb0,0,0,0,0,0,0,0cendscodesegmentstart:movax,amovds,axmovax,b moves,axmovbx,0movcx,8s:moval,[bx]addes:[bx],alincbxloopsmovax,cmovds,axmovbx,0movcx,8s0:moval,es:[bx]mov[bx],alincbxloops0movax,4c00hint21hcodeendsendstart=======================华丽的分割线===============================程序二:一次循环assumecs:codeasegmentdb1,2,3,4,5,6,7,8aendsbsegmentdb1,2,3,4,5,6,7,8bendscsegmentdb0,0,0,0,0,0,0,0cendscodesegmentstart:movax,amovds,ax;ds指向a段地址movax,bmoves,ax;es指向b段地址movbx,0movcx,8s:moval,[bx]addal,es:[bx]movdx,cmovds,dx;ds指向c段地址 mov[bx],almovax,amovds,ax;重新将ds指向a段(好像此处还能改进)incbxloopsmovax,4c00hint21hcodeendsendstart=======================华丽的分割线===============================程序三:程序二的改进版assumecs:codeasegmentdb1,2,3,4,5,6,7,8aendsbsegmentdb1,2,3,4,5,6,7,8bendscsegmentdb0,0,0,0,0,0,0,0cendscodesegmentstart:movax,amovds,axmovax,bmoves,axmovax,cmovss,axmovbx,0movcx,8s:movax,[bx]movss:[bx],axmovax,es:[bx]addss:[bx],axincbxloopsmovax,4c00hint21hcodeendsendstart实验5编写、调试具有多个段的程序 (6)程序如下,编写code段中代码,用PUSH指令将A段中的前8个字型数据,逆序存储到B段中。assumecs:codeasegmentdw1,2,3,4,5,6,7,8aendsbsegmentdw0,0,0,0,0,0,0,0bendscodesegmentstart:movax,amovds,ax;ds指向a段movax,bmovbx,0;ds:bx指向a段的第1个单元movss,axmovsp,16;设置栈顶指向b:16movcx,8s:push[bx]addbx,2loops;将a段中0~16个单元逆次入栈codeendsendstart实验6实践课程中的程序(1)将课程中所有讲解过的程序上机调试,用DEBUG跟踪其执行过程,并在过程中进一步理解所讲内容。略实验6实践课程中的程序(2)编程,完成问题7.9中的程序。(编程,将datasg段中每个单词的前4个字母改为大写字母。)assumecs:codesg,ds:datasg,ss:stacksgdatasgsegmentdb"1.display"db"2.brows"db"3.replace"db"4.modify"datasgendsstacksgsegmentdw0,0,0,0,0,0,0,0stacksgendscodesgsegmentstart:movax,datasgmovds,axmovbx,0movax,stacksgmovss,axmovsp,16 movcx,4s0:pushcxmovsi,0movcx,4s:moval,[bx+3][si]andal,11011111bmov[bx+3][si],alincsiloopsaddbx,16popcxloops0movax,4c00hint21hcodesgendsendstartC:DOCUME~1SNUSER>debugsy7-9.exe-d0c4e:03f0C4E:0000312E20646973706C-61792020202020201.display0C4E:0010322E2062726F7773-20202020202020202.brows0C4E:0020332E207265706C61-63652020202020203.replace0C4E:0030342E206D6F646966-79202020202020204.modify-gProgramterminatednormally-d0c4e:03f0C4E:0000312E20444953506C-61792020202020201.DISPlay0C4E:0010322E2042524F5773-20202020202020202.BROWs0C4E:0020332E205245504C61-63652020202020203.REPLace0C4E:0030342E204D4F444966-79202020202020204.MODIfy-实验七寻址方式在结构化访问中的应用(两个程序)程序一:四个循环assumecs:codesg,ds:data,es:tabledatasegmentdb"1975","1976","1977","1978","1979","1980","1981","1982","1983"db"1984","1985","1986","1987","1988","1989","1990","1991","1992"db"1993","1994","1995"dd16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000dw3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw11452,14430,15257,17800 dataendstablesegmentdb21dup("yearsummne??")tableendscodesgsegmentstart:movax,datamovds,axmovax,tablemovss,axmovbx,0movsi,0movbp,0movcx,21s0:movax,[bx+si]mov[bp+0],axaddsi,2movax,[bx+si]mov[bp+2],axaddsi,2addbp,10hloops0movcx,21movbp,0movsi,0s1:movax,[bx+si+84]mov[bp+5],axaddsi,2movax,[bx+si+84]mov[bp+7],axaddsi,2addbp,10hloops1movcx,21movbp,0movsi,0s2:movax,[bx+si+168]mov[bp+10],axaddsi,2addbp,10hloops2movcx,21 movbp,0s3:movax,[bp+5]movdx,[bp+7]divwordptr[bp+10]mov[bp+13],axaddbp,10hloops3movax,4c00hint21hcodesgendsendstart----------------------------------华丽的分割线---------------------------------程序二:一个循环assumecs:code,ds:data,es:tabledatasegmentdb"1975","1976","1977","1978","1979","1980","1981","1982","1983"db"1984","1985","1986","1987","1988","1989","1990","1991","1992"db"1993","1994","1995"dd16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000dw3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw11452,14430,15257,17800dataendstablesegmentdb21dup("yearsummne??")tableendscodesegmentstart:movax,datamovds,axmovax,tablemoves,axmovbx,0movsi,0movdi,0movcx,21s:movax,[bx]moves:[si],axmovax,[bx].2moves:[si].2,axmovax,[bx].84moves:[si].5,axmovdx,[bx].86 moves:[si].7,dxdivwordptrds:[di].168moves:[si].13,axmovax,[di].168moves:[si].10,axadddi,2addbx,4addsi,16loopsmovax,4c00hint21hcodeendsendstart----------------------------------华丽的分割线---------------------------------程序执行前内存数据0B80:0000313937352073756D-6D206E65203F3F201975summne??0B80:0010313937362073756D-6D206E65203F3F201976summne??0B80:0020313937372073756D-6D206E65203F3F201977summne??0B80:0030313937382073756D-6D206E65203F3F201978summne??0B80:0040313937392073756D-6D206E65203F3F201979summne??0B80:0050313938302073756D-6D206E65203F3F201980summne??0B80:0060313938312073756D-6D206E65203F3F201981summne??0B80:0070313938322073756D-6D206E65203F3F201982summne??0B80:0080313938332073756D-6D206E65203F3F201983summne??0B80:0090313938342073756D-6D206E65203F3F201984summne??0B80:00A0313938352073756D-6D206E65203F3F201985summne??0B80:00B0313938362073756D-6D206E65203F3F201986summne??0B80:00C0313938372073756D-6D206E65203F3F201987summne??0B80:00D0313938382073756D-6D206E65203F3F201988summne??0B80:00E0313938392073756D-6D206E65203F3F201989summne??0B80:00F0313939302073756D-6D206E65203F3F201990summne??0B80:0100313939312073756D-6D206E65203F3F201991summne??0B80:0110313939322073756D-6D206E65203F3F201992summne??0B80:0120313939332073756D-6D206E65203F3F201993summne??0B80:0130313939342073756D-6D206E65203F3F201994summne??0B80:0140313939352073756D-6D206E65203F3F201995summne??程序执行后内存数据0B80:00003139373520100000-00200300200500201975........0B80:00103139373620160000-00200700200300201976........0B80:002031393737207E0100-00200900202A00201977~.....*. 0B80:003031393738204C0500-00200D00206800201978L.....h.0B80:00403139373920560900-00201C00205500201979V.....U.0B80:00503139383020401F00-0020260020D200201980@...&...0B80:00603139383120803E00-00208200207B00201981.>....{.0B80:00703139383220A65F00-0020DC00206F00201982._....o.0B80:0080313938332091C300-0020DC01206900201983......i.0B80:00903139383420C77C01-00200A03207D00201984.|....}.0B80:00A03139383520812402-0020E903208C00201985.$......0B80:00B031393836208A0303-0020A205208800201986........0B80:00C031393837207C4705-0020D208209900201987|G......0B80:00D03139383820EB0309-0020E90A20D300201988........0B80:00E03139383920CA420C-0020C50F20C700201989.B......0B80:00F03139393020180D12-0020031620D100201990........0B80:01003139393120381F1C-0020222020E0002019918..."..0B80:0110313939322058192A-0020162D20EF00201992X.*..-..0B80:01203139393320284439-00205E38200401201993(D9.^8..0B80:0130313939342028F046-0020993B203001201994(.F..;0.0B80:0140313939352068975A-00208845204D01201995h.Z..EM.检测点10.1补全程序,实现从内存1000:0000处开始执行指令。assumecs:codestacksegmentdb16dup(0)stackendscodesegmentstart:movax,stackmovss,axmovsp,16movax,1000hpushaxmovax,0pushaxretfcodeendsendstart执行reft指令时,相当于进行:popippopcs根据栈先进后出原则,应先将段地址cs入栈,再将偏移地址ip入栈。C:DOCUME~1SNUSER>debugjc10-1.exe -u0C50:0000B84F0CMOVAX,0C4F0C50:00038ED0MOVSS,AX0C50:0005BC1000MOVSP,00100C50:0008B80010MOVAX,10000C50:000B50PUSHAX0C50:000CB80000MOVAX,00000C50:000F50PUSHAX0C50:0010CBRETF0C50:00113986FEFECMP[BP+FEFE],AX0C50:0015737DJNB0094-g0010AX=0000BX=0000CX=0021DX=0000SP=000CBP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C50IP=0010NVUPEIPLNZNAPONC0C50:0010CBRETF-tAX=0000BX=0000CX=0021DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=1000IP=0000NVUPEIPLNZNAPONC1000:00006EDB6E-检测点10.2下面的程序执行后,ax中的数值为多少?内存地址机器码汇编指令执行后情况1000:0b80000movax,0ax=0ip指向1000:31000:3e80100callspopipip指向1000:71000:640incax1000:758s:popaxax=6用debug进行跟踪确认,“call标号”是将该指令后的第一个字节偏移地址入栈,再转到标号处执行指令。assumecs:codecodesegmentstart:movax,0callsincaxs:popaxmovax,4c00hint21hcodeendsendstartC:DOCUME~1SNUSER>debugjc10-2.exe-u0C4F:0000B80000MOVAX,0000 0C4F:0003E80100CALL00070C4F:000640INCAX0C4F:000758POPAX0C4F:0008B8004CMOVAX,4C000C4F:000BCD21INT21-rAX=0000BX=0000CX=000DDX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C4FIP=0000NVUPEIPLNZNAPONC0C4F:0000B80000MOVAX,0000-tAX=0000BX=0000CX=000DDX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C4FIP=0003NVUPEIPLNZNAPONC0C4F:0003E80100CALL0007-tAX=0000BX=0000CX=000DDX=0000SP=FFFEBP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C4FIP=0007NVUPEIPLNZNAPONC0C4F:000758POPAX-tAX=0006BX=0000CX=000DDX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C4FIP=0008NVUPEIPLNZNAPONC0C4F:0008B8004CMOVAX,4C00-tAX=4C00BX=0000CX=000DDX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C4FIP=000BNVUPEIPLNZNAPONC0C4F:000BCD21INT21-pProgramterminatednormally检测点10.3下面的程序执行后,ax中的数值为多少?内存地址机器码汇编指令执行后情况1000:0b80000movax,0ax=0,ip指向1000:31000:39a09000010callfarptrspopcs,popip,ip指向1000:91000:840incax1000:958s:popaxax=8haddax,axax=10hpopbxbx=1000haddax,bxax=1010h用debug进行跟踪确认,“callfarptrs”是先将该指令后的第一个字节段地址cs=1000h入栈,再将偏移地址ip=8h入栈,最后转到标号处执行指令。出栈时,根据栈先进后出的原则,先出的为ip=8h,后出的为cs=1000h检测点10.4下面的程序执行后,ax中的数值为多少?内存地址机器码汇编指令执行后情况 1000:0b80600movax,6ax=6,ip指向1000:31000:3ffd0callaxpopip,ip指向1000:61000:540incax1000:658movbp,spbp=sp=fffehaddax,[bp]ax=[6+ds:(fffeh)]=6+5=0bh用debug进行跟踪确认,“callax(16位reg)”是先将该指令后的第一个字节偏移地址ip入栈,再转到偏移地址为ax(16位reg)处执行指令。检测点10.5(1)下面的程序执行后,ax中的数值为多少?assumecs:codestacksegmentdw8dup(0)stackendscodesegmentstart:movax,stackmovss,axmovsp,16movds,axmovax,0callwordptrds:[0eh]incaxincaxincaxmovax,4c00hint21hcodeendsendstart推算:执行callwordptrds:[0eh]指令时,先cs入栈,再ip=11入栈,最后ip转移到(ds:[0eh])。(ds:[0eh])=11h,执行incax……最终ax=3题中特别关照别用debug跟踪,跟踪结果不一定正确,但还是忍不住去试试,看是什么结果。根据单步跟踪发现,执行callwordptrds:[0eh]指令时,显示ds:[0eh]=065D。ds:0000~ds:0010不是已设置成stack数据段了嘛,不是应该全都是0的嘛。于是进行了更详细的单步跟踪,发现初始数据段中数据确实为0,但执行完movss,ax;movsp,16这两条指令后,数据段中数据发生改变。这是为什么呢?中断呗~~~~C:DOCUME~1SNUSER>debugjc10-5.exe-u0C50:0000B84F0CMOVAX,0C4F0C50:00038ED0MOVSS,AX 0C50:0005BC1000MOVSP,00100C50:00088ED8MOVDS,AX0C50:000AB80000MOVAX,00000C50:000DFF160E00CALL[000E]0C50:001140INCAX0C50:001240INCAX0C50:001340INCAX0C50:0014B8004CMOVAX,4C000C50:0017CD21INT21-rAX=0000BX=0000CX=0029DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C50IP=0000NVUPEIPLNZNAPONC0C50:0000B84F0CMOVAX,0C4F-d0c4f:0f0C4F:00000000000000000000-0000000000000000................-tAX=0C4FBX=0000CX=0029DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C50IP=0003NVUPEIPLNZNAPONC0C50:00038ED0MOVSS,AX-d0c4f:0f0C4F:00000000000000000000-0000000000000000................-tAX=0C4FBX=0000CX=0029DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C3FES=0C3FSS=0C4FCS=0C50IP=0008NVUPEIPLNZNAPONC0C50:00088ED8MOVDS,AX-d0c4f:0f0C4F:00000000000000004F0C-00000800500C5D06......O.....P.].-tAX=0C4FBX=0000CX=0029DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C4FES=0C3FSS=0C4FCS=0C50IP=000ANVUPEIPLNZNAPONC0C50:000AB80000MOVAX,0000-d0c4f:0f0C4F:00000000000000004F0C-00000A00500C5D06......O.....P.].-tAX=0000BX=0000CX=0029DX=0000SP=0010BP=0000SI=0000DI=0000DS=0C4FES=0C3FSS=0C4FCS=0C50IP=000DNVUPEIPLNZNAPONC0C50:000DFF160E00CALL[000E]DS:000E=065D-d0c4f:0f0C4F:00000000000000000000-00000D00500C5D06............P.].-检测点10.5(2)下面的程序执行后,ax和bx中的数值为多少?assumecs:codesgstacksegment dw8dup(0)stackendscodesgsegmentstart:movax,stackmovss,axmovsp,10hmovwordptrss:[0],offsets;(ss:[0])=1ahmovss:[2],cs;(ss:[2])=cscalldwordptrss:[0];cs入栈,ip=19h入栈,转到cs:1ah处执行指令;(ss:[4])=cs,(ss:[6])=ipnops:movax,offsets;ax=1ahsubax,ss:[0ch];ax=1ah-(ss:[0ch])=1ah-19h=1movbx,cs;bx=cs=0c5bhsubbx,ss:[0eh];bx=cs-cs=0movax,4c00hint21hcodesgendsendstartC:DOCUME~1ADMINI~1>debugjc10-5.exe-u0C5B:0000B85A0CMOVAX,0C5A0C5B:00038ED0MOVSS,AX0C5B:0005BC1000MOVSP,00100C5B:000836SS:0C5B:0009C70600001A00MOVWORDPTR[0000],001A0C5B:000F36SS:0C5B:00108C0E0200MOV[0002],CS0C5B:001436SS:0C5B:0015FF1E0000CALLFAR[0000]0C5B:001990NOP0C5B:001AB81A00MOVAX,001A0C5B:001D36SS:0C5B:001E2B060C00SUBAX,[000C]-u0C5B:00228CCBMOVBX,CS0C5B:002436SS:0C5B:00252B1E0E00SUBBX,[000E]0C5B:0029B8004CMOVAX,4C00课程设计一将实验7中的Poweridea公司的数据按照图所示的格式在屏幕上显示现来。 效果图assumecs:code,ds:data,es:tabletablesegmentdb"1975","1976","1977","1978","1979","1980","1981","1982","1983"db"1984","1985","1986","1987","1988","1989","1990","1991","1992"db"1993","1994","1995"dd16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514dd345980,590827,803530,1183000,1843000,2795000,3753000,4649000,5937000dw3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226dw11542,14430,15257,17800dw5,3,42,104,85,210,123,111,105,125,140,136,153,211,199,209,224,239dw260,304,333tableendsdatasegmentdb32dup(0)dataendscodesegmentstart:movax,datamovds,axmovax,tablemoves,axmovbx,0movsi,0movdi,0movcx,21movdh,2movdl,30g:pushcxpushdxmovax,es:[bx]mov[si],ax movax,es:[bx].2mov[si].2,ax;年份入ds:siaddsi,6movax,es:[bx].84movdx,es:[bx].86calldtoc2;收入转成十进制字符入ds:siaddsi,10movax,es:[di].168movdx,0calldtoc2;人员数转成十进制字符入ds:siaddsi,6movax,es:[di].210movdx,0calldtoc2;人均收入转成十进制字符入ds:simovsi,0;设置ds:si指向需显示字符首地址b:movcx,29c:pushcxmovcl,[si]jcxzf;(ds:si)=0转到f执行d:incsipopcxloopcincsimoval,0mov[si],al;设置结尾符0movsi,0;设置ds:si指向需显示字符首地址popdxmovcl,2callshow_straddbx,4;dword数据指向下一数据单元adddi,2;word数据指向下一数据单元adddh,1;指向显存下一行popcxloopgmovax,4c00hint21hf:moval,20hmov[si],al;(ds:si)=0的数据改成空格jmpd;名称:dtoc2;功能:将dword型数据转变为表示十进制的字符串,字符串以0为结尾符。;参数:(ax)=dword型数据的低16位;;(dx)=dword型数据的高16位; ;ds:si指向字符串首地址。;返回:无。dtoc2:pushaxpushbxpushcxpushdxpushsipushdimovdi,0d20:movcx,10;除数为10calldivdwaddcx,30h;余数+30h,转为字符pushcx;字符入栈incdi;记录字符个数movcx,axjcxzd21;低位商=0时,转到d21检测高位商jmpd20d21:movcx,dxjcxzd22;高低位商全=0时,转到d22执行jmpd20d22:movcx,did23:popax;字符出栈mov[si],alincsi;ds:si指向下一单元loopd23moval,0mov[si],al;设置结尾符0popdipopsipopdxpopcxpopbxpopaxret;名称:divdw;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。;参数:(ax)=dword型数据的低16位;;(dx)=dword型数据的高16位;;(cx)=除数。;返回:(dx)=结果的高16位;;(ax)=结果的低16位;;(cx)=余数。 divdw:pushsipushbxpushaxmovax,dxmovdx,0divcx;被除数的高位/cxmovsi,axpopaxdivcx;(被除数高位的商+低位)/cxmovcx,dx;余数入cxmovdx,si;高位的商入dxpopbxpopsiret;名称:show_str;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。;参数:(dh)=行号(取值范围0~24);;(dl)=列号(取值范围0~79);;(cl)=颜色;;ds:si指向字符串的首地址。;返回:无。show_str:pushaxpushbxpushespushsimovax,0b800hmoves,axmovax,160muldhmovbx,ax;bx=160*dhmovax,2muldl;ax=dl*2addbx,ax;movbx,(160*dh+dl*2)设置es:bx指向显存首地址moval,cl;把颜色cl赋值almovcl,0show0:movch,[si]jcxzshow1;(ds:si)=0时,转到show1执行moves:[bx],chmoves:[bx].1,alincsi;ds:si指向下一个字符地址 addbx,2;es:bx指向下一个显存地址jmpshow0show1:popsipopespopbxpopaxretcodeendsendstart实验10(1)show_str子程序效果图;在屏幕的8行3例,用绿色显示data段中的字符串。assumecs:code,ds:datadatasegmentdb"welcometomasm!",0dataendscodesegmentstart:movdh,8movdl,3movcl,2movax,datamovds,axmovsi,0callshow_strmovax,4c00hint21h;名称:show_str ;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。;参数:(dh)=行号(取值范围0~24);;(dl)=列号(取值范围0~79);;(cl)=颜色;;ds:si指向字符串的首地址。;返回:无。show_str:pushaxpushbxpushespushsimovax,0b800hmoves,axmovax,160muldhmovbx,ax;bx=160*dhmovax,2muldl;ax=dl*2addbx,ax;movbx,(160*dh+dl*2)设置es:bx指向显存首地址moval,cl;把颜色cl赋值almovcl,0show0:movch,[si]jcxzshow1;(ds:si)=0时,转到show1执行moves:[bx],chmoves:[bx].1,alincsi;ds:si指向下一个字符地址addbx,2;es:bx指向下一个显存地址jmpshow0show1:popsipopespopbxpopaxretcodeendsendstart实验10(2)divdw子程序 效果图;应用举例:计算1000000/10(f4240h/0ah)assumecs:codecodesegmentstart:movax,4240hmovdx,000fhmovcx,0ahcalldivdwmovax,4c00hint21h;名称:divdw;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。;参数:(ax)=dword型数据的低16位;;(dx)=dword型数据的高16位;;(cx)=除数。;返回:(dx)=结果的高16位;;(ax)=结果的低16位;;(cx)=余数。divdw:pushsipushbxpushaxmovax,dxmovdx,0divcx;被除数的高位/cx,高位在ax,余数在dxmovsi,axpopaxdivcx;(被除数高位的商+低位)/cx,高位在ax,余数在dxmovcx,dx;余数入cx movdx,si;高位的商入dxpopbxpopsiretcodeendsendstart公式x/n=int(h/n)*65536+[rem(h/n)*65536+l]/n解析:把一个会溢出的除法变成几个除法来做!如果高位除法有商,那么商就是结果的高位值,如果会有余数,那么余数自然不能丢弃,余数就作为低位除法的dx(也就是高位的被除数,因为他是从高位除法中余下的)做低位除法的时候,就拿余下的dx+低位数的ax除以除数,会得到一个低位的商和余数高位的商+低位数的商+余数就是结果这个程序的理解和完成,应该是这章比较重要的一个点。咱得多注意这种变通和分解的方式来处理问题的思维方式。实验10(3)dtoc1子程序效果图;应用举例:将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。;在显示时调用子程序show_str。assumecs:code,ds:datadatasegmentdb10dup(0)dataendscodesegmentstart:movax,12666movbx,datamovds,bxmovsi,0;ds:si指向data首地址 calldtoc1movdh,8movdl,3movcl,2callshow_strmovax,4c00hint21h;名称:dtoc1;功能:将word型数据转变为表示十进制的字符串,字符串以0为结尾符。;参数:(ax)=word型数据;;ds:si指向字符串首地址。;返回:无。dtoc1:pushaxpushbxpushcxpushdxpushsipushdimovdi,0d10:movdx,0;设置被除数高位为0movbx,10;除数为10divbxadddx,30h;ax/10的余数+30h,转为字符pushdx;字符入栈incdi;记录字符个数movcx,axjcxzd11;当ax/10的商=0时,转到d11执行jmpd10d11:movcx,did12:popdx;字符出栈mov[si],dlincsi;ds:si指向下一单元loopd12movdl,0mov[si],dl;设置结尾符0popsipopdipopdxpopcxpopbxpopax ret;名称:show_str;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。;参数:(dh)=行号(取值范围0~24);;(dl)=列号(取值范围0~79);;(cl)=颜色;;ds:si指向字符串的首地址。;返回:无。show_str:pushaxpushbxmovax,0b800hmoves,axmovax,160muldhmovbx,ax;bx=160*dhmovax,2muldl;ax=dl*2addbx,ax;movbx,(160*dh+dl*2)设置es:bx指向显存首地址moval,cl;把颜色cl赋值almovcl,0show0:movch,[si]jcxzshow1;(ds:si)=0时,转到show1执行moves:[bx],chmoves:[bx].1,alincsi;ds:si指向下一个字符地址addbx,2;es:bx指向下一个显存地址jmpshow0show1:popbxpopaxretcodeendsendstart实验10(4)dtoc2子程序 效果图;应用举例:将数据2494967295以十进制的形式在屏幕的8行3列,用绿色显示出来。assumecs:code,ds:datadatasegmentdb10dup(0)dataendscodesegmentstart:movax,0ffffhmovdx,0ffffhmovbx,datamovds,bxmovsi,0;ds:si指向字符串首地址calldtoc2movdh,8movdl,3movcl,2callshow_strmovax,4c00hint21h;名称:dtoc2;功能:将dword型数据转变为表示十进制的字符串,字符串以0为结尾符。;参数:(ax)=dword型数据的低16位;;(dx)=dword型数据的高16位;;ds:si指向字符串首地址。;返回:无。dtoc2:pushaxpushbx pushcxpushdxpushsipushdimovdi,0d20:movcx,10;除数为10calldivdwaddcx,30h;余数+30h,转为字符pushcx;字符入栈incdi;记录字符个数movcx,axjcxzd21;低位商=0时,转到d21检测高位商jmpd20d21:movcx,dxjcxzd22;高低位商全=0时,转到d22执行jmpd20d22:movcx,did23:popax;字符出栈mov[si],alincsi;ds:si指向下一单元loopd23moval,0mov[si],al;设置结尾符0popdipopsipopdxpopcxpopbxpopaxret;名称:show_str;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。;参数:(dh)=行号(取值范围0~24);;(dl)=列号(取值范围0~79);;(cl)=颜色;;ds:si指向字符串的首地址。;返回:无。show_str:pushaxpushbxmovax,0b800hmoves,axmovax,160 muldhmovbx,ax;bx=160*dhmovax,2muldl;ax=dl*2addbx,ax;movbx,(160*dh+dl*2)设置es:bx指向显存首地址moval,cl;把颜色cl赋值almovcl,0show0:movch,[si]jcxzshow1;(ds:si)=0时,转到show1执行moves:[bx],chmoves:[bx].1,alincsi;ds:si指向下一个字符地址addbx,2;es:bx指向下一个显存地址jmpshow0show1:popbxpopaxret;名称:divdw;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型。;参数:(ax)=dword型数据的低16位;;(dx)=dword型数据的高16位;;(cx)=除数。;返回:(dx)=结果的高16位;;(ax)=结果的低16位;;(cx)=余数。divdw:pushsipushbxpushaxmovax,dxmovdx,0divcx;被除数的高位/cxmovsi,axpopaxdivcx;(被除数高位的商+低位)/cxmovcx,dx;余数入cxmovdx,si;高位的商入dxpopbxpopsiretcodeends endstart检测点11.1写出下面每条指令执行后,ZF、PF、SF、等标志位的值。subal,alal=0hZF=1PF=1SF=0moval,1al=1hZF=1PF=1SF=0pushaxax=1hZF=1PF=1SF=0popbxbx=1hZF=1PF=1SF=0addal,blal=2hZF=0PF=0SF=0addal,10al=12hZF=0PF=1SF=0mulalax=144hZF=0PF=1SF=0检测点涉及的相关内容:ZF是flag的第6位,零标志位,记录指令执行后结果是否为0,结果为0时,ZF=1PF是flag的第2位,奇偶标志位,记录指令执行后结果二进制中1的个数是否为偶数,结果为偶数时,PF=1SF是flag的第7位,符号标志位,记录有符号运算结果是否为负数,结果为负数时,SF=1add、sub、mul、div、inc、or、and等运算指令影响标志寄存器mov、push、pop等传送指令对标志寄存器没影响。C:DOCUME~1ADMINI~1>debug-a0C1C:0100subal,al0C1C:0102moval,10C1C:0104pushax0C1C:0105popbx0C1C:0106addal,bl0C1C:0108addal,100C1C:010Amulal0C1C:010C-tAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0102NVUPEIPLZRNAPENC0C1C:0102B001MOVAL,01-tAX=0001BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0104NVUPEIPLZRNAPENC0C1C:010450PUSHAX-tAX=0001BX=0000CX=0000DX=0000SP=FFECBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0105NVUPEIPLZRNAPENC0C1C:01055BPOPBX-tAX=0001BX=0001CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0106NVUPEIPLZRNAPENC0C1C:010600D8ADDAL,BL -tAX=0002BX=0001CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=0108NVUPEIPLNZNAPONC0C1C:01080410ADDAL,10-tAX=0012BX=0001CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010ANVUPEIPLNZNAPENC0C1C:010AF6E0MULAL-tAX=0144BX=0001CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0C1CES=0C1CSS=0C1CCS=0C1CIP=010COVUPEIPLNZNAPECY0C1C:010C1599CDADCAX,CD99-检测点11.2写出下面每条指令执行后,ZF、PF、SF、CF、OF等标志位的值。alCFOFSFZFPFsubal,al0h/00000000b00011moval,10h10h/00100000b00011addal,90ha0h/10100000b00101moval,80h80h/10000000b00101addal,80h0h/00000000b11011moval,0fch0fch/11111100b11011addal,05h1h/00000001b10000moval,7dh7dh/11111101b10000addal,0bh88h/10001000b01101检测点涉及的相关内容:ZF是flag的第6位,零标志位,记录指令执行后结果是否为0,结果为0时,ZF=1PF是flag的第2位,奇偶标志位,记录指令执行后结果二进制数中1的个数是否为偶数,结果为偶数时,PF=1SF是flag的第7位,符号标志位,记录有符号运算结果是否为负数,结果为负数时,SF=1CF是flag的第0位,进位标志位,记录无符号运算结果是否有进/借位,结果有进/借位时,SF=1OF是flag的第11位,溢出标志位,记录有符号运算结果是否溢出,结果溢出时,OF=1add、sub、mul、div、inc、or、and等运算指令影响flagmov、push、pop等传送指令对flag没影响Microsoft(R)WindowsDOS(C)CopyrightMicrosoftCorp1990-2001.C:DOCUME~1SNUSER>debug-a0BF9:0100subal,al0BF9:0102moval,100BF9:0104addal,900BF9:0106moval,80 0BF9:0108moval,fc0BF9:010Aaddal,50BF9:010Cmoval,7d0BF9:010Eaddal,b0BF9:0110-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0100NVUPEIPLNZNAPONC0BF9:010028C0SUBAL,AL-tAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0102NVUPEIPLZRNAPENC0BF9:0102B010MOVAL,10-tAX=0010BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0104NVUPEIPLZRNAPENC0BF9:01040490ADDAL,90-tAX=00A0BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0106NVUPEINGNZNAPENC0BF9:0106B080MOVAL,80-tAX=0080BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0108NVUPEINGNZNAPENC0BF9:0108B0FCMOVAL,FC-tAX=00FCBX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010ANVUPEINGNZNAPENC0BF9:010A0405ADDAL,05-tAX=0001BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010CNVUPEIPLNZACPOCY0BF9:010CB07DMOVAL,7D-tAX=007DBX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010ENVUPEIPLNZACPOCY0BF9:010E040BADDAL,0B-tAX=0088BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0110OVUPEINGNZACPENC0BF9:0110C6BF1F9903MOVBYTEPTR[BX+991F],03DS:991F=00-检测点11.3(1)补全下面的程序,统计F000:0处32个字节中,大小在[32,128]的数据个数。 movax,0f000hmovds,axmovbx,0;ds:bx指向第一个字节movdx,0;初始化累加器movcx,32s:moval,[bx]cmpal,32;和32进行比较jbs0;如果低于al转到s0,继续循环cmpal,128;和128进行比较jas0;如果高于al转到s0,继续循环incdxs0:incbxloops[32,128]是闭区间,包括两端点的值(32,128)是开区间,不包括两端点的值检测点11.3(2)补全下面的程序,统计F000:0处32个字节中,大小在(32,128)的数据个数。movax,0f000hmovds,axmovbx,0;ds:bx指向第一个字节movdx,0;初始化累加器movcx,32s:moval,[bx]cmpal,32;和32进行比较jnas0;如果不高于al转到s0,继续循环cmpal,128;和128进行比较jnbs0;如果不低于al转到s0,继续循环incdxs0:incbxloops[32,128]是闭区间,包括两端点的值(32,128)是开区间,不包括两端点的值检测点11.4下面指令执行后,(ax)=45hmovax,0pushaxpopfmovax,0fff0haddax,0010hpushfpopax andal,11000101Bandah,00001000B推算过程:popf后,标志寄存器中,本章节介绍的那些标志位都为0(但是此时标志寄存器并不是所有位置都为0,这个不用关心,没学过的位置用*先代替),向下进行,那么pushf将计算后的当时状态的标志寄存器入栈,然后pop给ax,这是ax是寄存器的值(这个值中包含了我们的*号),接下来就是对那些没有学过的标志位的屏蔽操作,这就是最后两条指令的意义所在,将不确定的位置都归0,那么只剩下我们能够确定的位置了,所以,结果就可以推理出来了。movax,0pushaxpopfmovax,0fff0haddax,0010hpushfpopax0000ofdfiftfsfzf0af0pf0cf000000**010*0101ax=flag=000000**010*0101bandal,11000101Bal=01000101b=45handah,00001000Bah=00000000b=0hC:DOCUME~1SNUSER>debug-a0BF9:0100movax,00BF9:0103pushax0BF9:0104popf0BF9:0105movax,fff00BF9:0108addax,100BF9:010Bpushf0BF9:010Cpopax0BF9:010Dandal,c50BF9:010Fandah,80BF9:0112-rAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0100NVUPEIPLNZNAPONC0BF9:0100B80000MOVAX,0000-tAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0103NVUPEIPLNZNAPONC0BF9:010350PUSHAX-tAX=0000BX=0000CX=0000DX=0000SP=FFECBP=0000SI=0000DI=0000 DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0104NVUPEIPLNZNAPONC0BF9:01049DPOPF-tAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0105NVUPDIPLNZNAPONC0BF9:0105B8F0FFMOVAX,FFF0-tAX=FFF0BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0108NVUPDIPLNZNAPONC0BF9:0108051000ADDAX,0010-tAX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010BNVUPDIPLZRNAPECY0BF9:010B9CPUSHF-tAX=0000BX=0000CX=0000DX=0000SP=FFECBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010CNVUPDIPLZRNAPECY0BF9:010C58POPAX-tAX=3047BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010DNVUPDIPLZRNAPECY0BF9:010D24C5ANDAL,C5-tAX=3045BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=010FNVUPDIPLNZNAPONC0BF9:010F80E408ANDAH,08-tAX=0045BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000DS=0BF9ES=0BF9SS=0BF9CS=0BF9IP=0112NVUPDIPLZRNAPENC0BF9:01124CDECSP实验11(letterc子程序)小写改成大写编写一个子程序,将包含任意字符,以0结尾的字符串的小写字母转变成大写字母。 效果图程序一:此题为小写改成大写,根据书P141页介绍,小写字母"a"-"z"对应ASCII码为61h-86h,只要[61,86]这段区间里的ASCII减去20h,就改成了大写字母。assumecs:codesgdatasgsegmentdb"Seginner"sAll-purposeSymbolicInstructionCode.","0"datasgendscodesgsegmentbegin:movax,datasgmovds,axmovsi,0;ds:si指向第一个字节calllettercmovax,4c00hint21h;名称:letterc;功能:将以0结尾的字符中的小写字母转变成大写字母;参数:ds:si指向字符串首地址letterc:pushaxpushsilet:cmpbyteptr[si],0;和0进行比较jelet0;如果等于0则转到let0,结束cmpbyteptr[si],61h;和61h进行比较jblet1;如果低于60h则转到let1,继续循环cmpbyteptr[si],86h;和86h进行比较jalet1;如果高于86h则转到let1,继续循环moval,[si]subal,20h;转为大写字母mov[si],allet1:incsijmpletlet0:popsipopaxretcodesgendsendbegin------------------------华丽的分割线----------------------------程序二:参考书中P143页内容,有更好的办法,无需用到寄存器。 可以用and直接修改内存,将ASCII码的第5位置为0,变为大写字母。assumecs:codesgdatasgsegmentdb"Seginner"sAll-purposeSymbolicInstructionCode.","0"datasgendscodesgsegmentbegin:movax,datasgmovds,axmovsi,0;ds:si指向第一个字节calllettercmovax,4c00hint21h;名称:letterc;功能:将以0结尾的字符中的小写字母转变成大写字母;参数:ds:si指向字符串首地址letterc:pushsilet:cmpbyteptr[si],0;和0进行比较jelet0;如果等于0则转到let0,结束cmpbyteptr[si],61h;和61h进行比较jblet1;如果低于60h则转到let1,继续循环cmpbyteptr[si],86h;和86h进行比较jalet1;如果高于86h则转到let1,继续循环andbyteptr[si],11011111b;ASCII码的第5位置为0,转为大写let1:incsijmpletlet0:popsiretcodesgendsendbegin检测点12.1(1)用debug查看内存,情况如下:0000:00006810A7008B017000-16009D038B017000则3号中断源对应的中断处理程序入口的偏移地址的内存单位的地址为:0070:018b检测点涉及相关内容:一个表项存放一个中断向量,也就是一个中断处理程序的入口地址,这个入口地址包括段地址和偏移地址,一个表项占两个字,高地址存放段地址,低地址存放偏移地址检测点12.1 (2)存储N号中断源对应的中断处理程序入口的偏移地址的内存单元的地址为:4N存储N号中断源对应的中断处理程序入口的段地址的内存单元的地址为:4N+2检测点涉及相关内容:一个表项存放一个中断向量,也就是一个中断处理程序的入口地址,这个入口地址包括段地址和偏移地址,一个表项占两个字,高地址存放段地址,低地址存放偏移地址实验12编写0号中断处理程序编写0号中断处理程序,使得在除法溢出发生时,在屏幕中间显示字符串“divideerror!”,然后返回DOS;名称:0号中断处理程序;功能:使得除法溢出发生时,在屏幕中间显示字符串"divideerror!",然后返回DOSassumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsetdo0;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetdo0end-offsetdo0;设置cx为传输长度cld;设置传输方向为正repmovsbmovax,0moves,axmovwordptres:[0*4],200hmovwordptres:[0*4+2],0;设置中断向量表movax,4c00hint21hdo0:jmpshortdo0startdb"divideerror!"do0start:movax,csmovds,axmovsi,202h;设置ds:si指向字符串movax,0b800h moves,axmovdi,12*160+34*2;设置es:di指向显存空间的中间位置movcx,13;设置cx为字符串长度s:moval,[si]moves:[di],alincsiadddi,2loopsmovax,4c00hint21hdo0end:nopcodeendsendstart检测点13.17ch中断例程如下:lp:pushbpmovbp,spdeccxjcxzlpretadd[bp+2],bxlpret:popbpiret(1)在上面的内容中,我们用7ch中断例程实现loop的功能,则上面的7ch中断例程所能进行的最大转移位移是多少?最大位移是FFFFH检测点13.1(2)用7ch中断例程完成jmpnearptrs指令功能,用bx向中断例程传送转移位移。应用举例:在屏幕的第12行,显示data段中以0结尾的字符串。assumecs:codedatasegmentdb"conversation",0dataendscodesegmentstart:movax,datamovds,axmovsi,0movax,0b800h moves,axmovdi,12*160s:cmpbyteptr[si],0jeokmoval,[si]moves:[di],alincsiadddi,2movbx,offsets-offsetokint7chok:movax,4c00hint21hcodeendsendstartjmpnearptrs指令的功能为:(ip)=(ip)+16位移,实现段内近转移assumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsetdo0;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetdo0end-offsetdo0;设置cx为传输长度cld;设置传输方向为正repmovsbmovax,0moves,axmovwordptres:[7ch*4],200hmovwordptres:[7ch*4+2],0;设置中断向量表movax,4c00hint21hdo0:pushbpmovbp,spadd[bp+2],bx;ok的偏移地址+bx得到s的偏移地址popbpiretmovax,4c00hint21hdo0end: nopcodeendsendstart检测点13.2判断下面说法的正误:(1)我们可以编程改变FFFF:0处的指令,使得CPU不去执行BIOS中的硬件系统检测和初始化程序。答:错误,FFFF:0处的内容无法改变。检测点13.2判断下面说法的正误:(2)int19h中断例程,可以由DOS提供。答:错误,先调用int19h,后启动DOS。实验13(1)编写并安装int7ch中断例程,功能为显示一个用0结束的字符串,中断例程安装在0:200处。效果图;名称:int7ch中断例程;功能:显示一个0结束的字符串,中断例程安装在0:200处;参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si指向字符串首地址assumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsetshow_str;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetshow_strend-offsetshow_str;设置cx为传输长度cld;设置传输方向为正repmovsbmovax,0moves,axmovwordptres:[7ch*4],200hmovwordptres:[7ch*4+2],0;设置中断向量表movax,4c00hint21h;名称:show_str;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。 ;参数:(dh)=行号(取值范围0~24);;(dl)=列号(取值范围0~79);;(cl)=颜色;;ds:si指向字符串的首地址。;返回:无。show_str:pushaxpushbxpushespushsimovax,0b800hmoves,axmovax,160muldhmovbx,ax;bx=160*dhmovax,2muldl;ax=dl*2addbx,ax;movbx,(160*dh+dl*2)设置es:bx指向显存首地址moval,cl;把颜色cl赋值almovcl,0show0:movch,[si]jcxzshow1;(ds:si)=0时,转到show1执行moves:[bx],chmoves:[bx].1,alincsi;ds:si指向下一个字符地址addbx,2;es:bx指向下一个显存地址jmpshow0show1:popsipopespopbxpopaxiretmovax,4c00hint21hshow_strend:nopcodeendsendstart;实验13(1)应用举例assumecs:codedatasegmentdb"welcometomasm!",0dataendscodesegmentstart:movdh,10movdl,10movcl,2movax,datamovds,axmovsi,0int7chmovax,4c00hint21hcodeendsendstart实验13(2)编写并安装int7ch中断例程,功能为完成loop指令功能 效果图;名称:int7ch中断例程;功能:完成loop指令功能,中断例程安装在0:200处;参数:(cx)=循环次数,(bx)=位移assumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsetlp;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetlpend-offsetlp;设置cx为传输长度cld;设置传输方向为正repmovsbmovax,0moves,axmovwordptres:[7ch*4],200hmovwordptres:[7ch*4+2],0;设置中断向量表movax,4c00hint21hlp:pushbpmovbp,spdeccxjcxzlpretadd[bp+2],bxlpret:popbpiretmovax,4c00hint21hlpend:nopcodeendsendstart;实验13(2)应用举例assumecs:codecodesegmentstart:movax,0b800hmoves,axmovdi,160*12movbx,offsets-offsetse;设置从标号se到标号s的转移位移movcx,80s:movbyteptres:[di],"!"adddi,2 int7ch;(cx)≠0,转移到标号s处se:nopmovax,4c00hint21hcodeendsendstart实验13(3)下面的程序,分别在屏幕的第2、4、6、8行显示4句英文诗,补全代码。效果图assumecs:codecodesegments1:db"Good,better,best,","$"s2:db"Neverletitrest,","$"s3:db"Tillgoodisbetter,","$"s4:db"Andbetter,best.","$"s:dwoffsets1,offsets2,offsets3,offsets4row:db2,4,6,8start:movax,csmovds,axmovbx,offsetsmovsi,offsetrowmovcx,4ok:movbh,0;第0页movdh,[si];dh中放行号movdl,0;dl中放列号movah,2;置光标int10hmovdx,[bx];ds:dx指向字符串首地址movah,9;在光标位置显示字符int21hincsi;行号递增addbx,2;指向下一字符串loopokmovax,4c00hint21hcodeendsendstart检测点14.1读取写入CMOSRAM单元内容(1)编程,读取CMOSRAM的2号单元内容。 assumecs:codecodesegmentstart:moval,2;赋值alout70h,al;将al送入端口70hinal,71h;从端口71h处读出单元内容movax,4c00hint21hcodeendsendstart检测点14.1(2)编程,向CMOSRAM的2号单元写入0。assumecs:codecodesegmentstart:moval,2;赋值alout70h,al;将al送入端口70hmoval,0;赋值alout71h,al;向端口71h写入数据almovax,4c00hint21hcodeendsendstart检测点14.2用加法和移位指令计算效果图编程,用加法和移位指令计算(ax)=(ax)*10提示:(ax)*10=(ax)*2+(ax)*8assumecs:codecodesegmentstart:movbx,axshlax,1;左移1位(ax)=(ax)*2 movcl,3shlbx,cl;左移3位(bx)=(ax)*8addax,bx;(ax)=(ax)*2+(ax)*8movax,4c00hint21hcodeendsendstart;应用举例:计算ffh*10assumecs:codecodesegmentstart:movax,0ffhmovbx,axshlax,1;左移1位(ax)=(ax)*2movcl,3shlbx,cl;左移3位(bx)=(ax)*8addax,bx;(ax)=(ax)*2+(ax)*8movax,4c00hint21hcodeendsendstartPS:左移1位,N=(N)*2左移2位,N=(N)*4左移3位,N=(N)*8左移4位,N=(N)*16左移5位,N=(N)*32实验14访问CMOSRAM编程,以“年/月/日时:分:秒”的格式,显示当前的日期、时间。(两个程序)效果图 程序一:assumecs:codecodesegmentstart:movax,0moval,9movsi,0movcx,6s:pushcxpushaxout70h,al;将al送入端口70hinal,71h;从端口71h处读出单元内容movah,almovcl,4shrah,clandal,00001111b;al分成两个表示BCD码值的数据addah,30haddal,30h;BCD码+30h=10进制数对应的ASCII码movbx,0b800hmoves,bxmovbyteptres:[160*12+40*2][si],ah;显示十位数码movbyteptres:[160*12+40*2+2][si],al;显示个位数码popaxdecax;指向前一数据单元jmps1s0:popcxaddsi,6loopsmovax,4c00hint21hs1:cmpax,10jas0cmpax,0jes0cmpax,6jas2;ax>6,为年/月/日jes3;ax=6,为日结尾jbs4;ax<6,为时:分:秒s2:movbyteptres:[160*12+40*2+4][si],"/";添加"/"jmps0s3:subax,2jmps0s4:subax,1movbyteptres:[160*12+40*2+4][si],":";添加":"jmps0 codeendsendstart==============================华丽的分割线===============================程序二:assumecs:codecodesegmenttimedb"yy/mm/ddhh:mm:ss","$"cmosdb9,8,7,4,2,0start:movax,csmovds,axmovbx,0movsi,0movcx,6a:pushcxmoval,cmos[bx]out70h,al;将al送入地址端口70hinal,71h;从数据端口71h处读出单元内容movah,almovcl,4shral,cl;右移4位andah,0fh;al分成两个表示BCD码值的数据addax,3030h;BCD码+30h=10进制数对应的ASCII码movcs:[si],ax;ASCII码写入time段incbxaddsi,3popcxloopa;名称:BIOS中断(int10h);功能:(ah)=2置光标到屏幕指定位置、(ah)=9在光标位置显示字符;参数:(al)=字符、(bh)=页数、(dh)=行号、(dl)=例号;(bl)=颜色属性、(cx)=字符重复个数movah,2;置光标movbh,0;第0页movdh,13;dh中放行号movdl,32;dl中放例号int10h;名称:DOS中断(int21h);功能:(ah)=9显示用"$"结束的字符串、(ah)=4ch程序返回;参数:ds:dx指向字符串、(al)=返回值movdx,0movah,9int21h ;结束movax,4c00hint21hcodeendsendstart检测点15.1(1)仔细分析一下书中的in9中断例程,看看是否可以精简一下?其实在我们的int9中断例程中,模拟int指令调用原int9中断例程的程序段是可以精简的,因为在进入中断例程后,IF和TF都已置0,没有必要再进行设置了,对于程序段:pushf;标志寄存器入栈pushfpopbxandbh,11111100b;IF和TF为flag的第9位和第8位pushbxpopf;TF=0,IF=0calldwordptrds:[0];CS、IP入栈;(IP)=ds:[0],(CS)=ds:[2]可以精简为:pushf;标志寄存器入栈calldwordptrds:[0];CS、IP入栈;(IP)=ds:[0],(CS)=ds:[2]两条指令。检测点15.1(2)仔细分析程序中的主程序,看看有什么潜在的问题?在主程序中,如果在设置执行设置int9中断例程的段地址和偏移地址的指令之间发生了键盘中段,则CPU将转去一个错误的地址执行,将发生错误。找出这样的程序段,改写他们,排除潜在的问题。;在中断向量表中设置新的int9中断例程的入口地址cli;设置IF=0屏蔽中断movwordptres:[9*4],offsetint9moves:[9*4+2],cssti;设置IF=1不屏蔽中断============更改后的int9中断例程================;功能:在屏幕中间依次显示"a"~"z",并让人看清。在显示过程中按下Esc键后,改变显示的颜色。assumecs:codestacksegmentdb128dup(0)stackendsdatasegmentdw0,0dataends codesegmentstart:movax,stackmovss,axmovsp,128;将原来的int9中断例程的入口地址保存在ds:0、ds:2单元中movax,datamovds,axmovax,0moves,axpushes:[9*4]popds:[0]pushes:[9*4+2]popds:[2];在中断向量表中设置新的int9中断例程的入口地址cli;设置IF=0屏蔽中断movwordptres:[9*4],offsetint9movwordptres:[9*4+2],cssti;设置IF=1不屏蔽中断;依次显示"a"~"z"movax,0b800hmoves,axmovah,"a"s:moves:[160*12+40*2],ah;第12行第40列incahcmpah,"z"jnbs;将中断向量表中int9中断例程的入口恢复为原来的地址movax,0moves,axpushds:[0]popss:[9*4]pushds:[2]popes:[9*4+2];结束movax,4c00hint21h ;循环延时,循环100000h次delay:pushaxpushdxmovdx,1000hmovax,0delay1:subax,1sbbdx,0;(dx)=(dx)-0-CFcmpax,0jnedelay1cmpdx,0jnedelay1popdxpopaxret;以下为新的int9中断例程int9:pushaxpushbxpushesinal,60h;从端口60h读出键盘输入;对int指令进行模拟,调用原来的int9中断例程pushf;标志寄存器入栈calldwordptrds:[0];CS、IP入栈;(IP)=ds:[0],(CS)=ds:[2];如果是ESC扫描码,改变显示颜色cmpal,1;和esc的扫描码01比较jneint9ret;不等于esc时转移movax,0b800hmoves,axincbyteptres:[160*12+40*2+1];将属性值+1,改变颜色int9ret:popespopbxpopaxiretcodeendsendstart实验15安装新的int9中断例程(按"A"键后显示满屏幕的"A") 效果图;任务:安装一个新的int9中断例程;功能:在DOS下,按"A"键后除非不再松开,如果松开,就显示满屏幕的"A",其他键照常处理assumecs:codestacksegmentdb128dup(0)stackendscodesegmentstart:movax,stackmovss,axmovsp,128pushcspopdsmovax,0moves,axmovsi,offsetint9;设置ds:si指向源地址movdi,204h;设置es:di指向目标地址movcx,offsetint9end-offsetint9;设置cx为传输长度cld;设置传输方向为正repmovsb;将原来的int9中断例程的入口地址保存在ds:200、ds:202单元中pushes:[9*4]popes:[200h]pushes:[9*4+2]popes:[202h];在中断向量表中设置新的int9中断例程的入口地址cli;设置IF=0屏蔽中断movwordptres:[9*4],204hmovwordptres:[9*4+2],0sti;设置IF=1不屏蔽中断;结束 movax,4c00hint21h;新的int9中断例程int9:pushaxpushbxpushcxpushesinal,60h;从端口60h读出键盘输入;对int指令进行模拟,调用原来的int9中断例程pushf;标志寄存器入栈calldwordptrcs:[200h];CS,IP入栈,(IP)=cs:[200h],(CS)=0;如果是A断码,改变当前屏幕的显示字符cmpal,9eh;和A的断码(1eh+80h)比较jneint9ret;不等于A时转移movax,0b800hmoves,axmovbx,0movcx,2000s:movbyteptres:[bx],41h;将A的ASCII码写入,改变字符addbx,2loopsint9ret:popespopcxpopbxpopaxiretint9end:nopcodeendsendstart检测点16.1(两个程序)下面的程序将code段中a处的8个数值累加,结果存储到b处的双字节中,补全程序。程序一:assumecs:codecodesegmentadw1,2,3,4,5,6,7,8bdd0start:movsi,0movcx,8s:movax,a[si]adda[16],axadca[18],0addsi,2loopsmovax,4c00h int21hcodeendsendstartC:DOCUME~1SNUSER>debug16-1.exe-u0C4E:0014BE0000MOVSI,00000C4E:0017B90800MOVCX,00080C4E:001A2ECS:0C4E:001B8B840000MOVAX,[SI+0000]0C4E:001F2ECS:0C4E:002001061000ADD[0010],AX0C4E:00242ECS:0C4E:00258316120000ADCWORDPTR[0012],+000C4E:002A83C602ADDSI,+020C4E:002DE2EBLOOP001A0C4E:002FB8004CMOVAX,4C000C4E:0032CD21INT21-rAX=0000BX=0000CX=0034DX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3EES=0C3ESS=0C4ECS=0C4EIP=0014NVUPEIPLNZNAPONC0C4E:0014BE0000MOVSI,0000-d0c4e:01f0C4E:00000100020003000400-0500060007000800................0C4E:001000000000BE0000B9-08002E8B8400002E................-g002fAX=0008BX=0000CX=0000DX=0000SP=0000BP=0000SI=0010DI=0000DS=0C3EES=0C3ESS=0C4ECS=0C4EIP=002FNVUPEIPLNZACPONC0C4E:002FB8004CMOVAX,4C00-d0c4e:01f0C4E:00000100020003000400-0500060007000800................0C4E:001024000000BE0000B9-08002E8B8400002E$...............-程序二:assumecs:codecodesegmentadw1,2,3,4,5,6,7,8bdd0start:movsi,0movcx,8s:movax,a[si]addwordptrb[0],axadcwordptrb[2],0 addsi,2loopsmovax,4c00hint21hcodeendsendstart检测点16.2下面的程序将data段中a处的8个数值累加,结果存储到b处的双字节中,补全程序。assumecs:code,es:datadatasegmentadb1,2,3,4,5,6,7,8bdw0dataendscodesegmentstart:movax,datamoves,axmovsi,0movcx,8s:moval,a[si]movah,0addb,axincsiloopsmovax,4c00hint21hcodeendsendstartC:DOCUME~1SNUSER>debug16-2.exe-u0C4F:0000B84E0CMOVAX,0C4E0C4F:00038EC0MOVES,AX0C4F:0005BE0000MOVSI,00000C4F:0008B90800MOVCX,00080C4F:000B26ES:0C4F:000C8A840000MOVAL,[SI+0000]0C4F:0010B400MOVAH,000C4F:001226ES: 0C4F:001301060800ADD[0008],AX0C4F:001746INCSI0C4F:0018E2F1LOOP000B0C4F:001AB8004CMOVAX,4C000C4F:001DCD21INT210C4F:001F56PUSHSI-rAX=0000BX=0000CX=002FDX=0000SP=0000BP=0000SI=0000DI=0000DS=0C3EES=0C3ESS=0C4ECS=0C4FIP=0000NVUPEIPLNZNAPONC0C4F:0000B84E0CMOVAX,0C4E-d0c4e:0f0C4E:00000102030405060708-0000000000000000................-g001aAX=0008BX=0000CX=0000DX=0000SP=0000BP=0000SI=0008DI=0000DS=0C3EES=0C4ESS=0C4ECS=0C4FIP=001ANVUPEIPLNZNAPONC0C4F:001AB8004CMOVAX,4C00-d0c4e:0f0C4E:00000102030405060708-2400000000000000........$.......-实验16包含多个功能子程序的中断例程(两个程序)安装一个新的int7ch中断例程,为显示输出提供功能子程序。(1)清屏;(2)设置前景色;(3)设置背景色;(4)向上滚动一行;入口参数说明如下。(1)用ah寄存器传递功能号:0表示清屏,1表示设置前景色,2表示设置背景色,3表示向上滚动一行;(2)对于2、3号功能,用al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}。程序一:;任务:安装一个新的int7ch中断例程;功能:为显示输出提供功能子程序;参数:ah传递功能号;0表示清屏,1表示设置前景色,2表示设置背景色,3表示向上滚动一行,对于2、3号功能,用al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}assumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsets;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetsend-offsets;设置cx为传输长度 cld;设置传输方向为正repmovsb;在中断向量表中设置新的int7ch中断例程的入口地址cli;设置IF=0屏蔽中断movwordptres:[7ch*4],200hmovwordptres:[7ch*4+2],0sti;设置IF=1不屏蔽中断;结束movax,4c00hint21h;新的int7ch中断例程s:jmpshortsettabledwsub1-s+200h,sub2-s+200h,sub3-s+200h,sub4-s+200hset:pushbxcmpah,3;判断ah中的功能号是否大于3jasretmovbl,ahmovbh,0addbx,bx;计算对应子程序在table表中的偏移callwordptrtable[bx];调用对应的功能子程序sret:popbxiret;功能:清屏sub1:pushbxpushcxpushesmovbx,0b800hmoves,bxmovbx,0movcx,2000subles:movbyteptres:[bx],""addbx,2loopsublespopespopcxpopbxret;设置前景色,al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}sub2:pushbxpushcxpushesmovbx,0b800hmoves,bxmovbx,1 movcx,2000sub2s:andbyteptres:[bx],11111000bores:[bx],aladdbx,2loopsub2spopespopcxpopbxret;设置背景色,al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}sub3:pushaxpushbxpushcxpushesmovcl,4shlal,clmovbx,0b800hmoves,bxmovbx,1movcx,2000sub3s:andbyteptres:[bx],10001111bores:[bx],aladdbx,2loopsub3spopespopcxpopbxpopaxret;向上滚动一行sub4:pushcxpushsipushdipushespushdsmovsi,0b800hmoves,simovds,simovsi,160;ds:si指向第N+1行movdi,0;es:di指向第N行cldmovcx,24;共复制24行sub4s:pushcxmovcx,160 repmovsb;复制popcxloopsub4smovcx,80sub4s1:movbyteptr[160*24+si],"";最后一行清空addbx,2loopsub4s1popdspopespopdipopsipopcxretsend:nopcodeendsendstart=============================================================================程序二:说明:在进行这个实验时,往往会参考16.4给出的代码(四个子程序和直接定址表功能选择程序)如果安装16.4给出的功能子程序的安装程序习惯采用下面图1安装结构会出问题,问题有两个:1:tabledwsub1……中SUB1存放的应该是子程序的偏移地址,这个偏移地址是相对于中断程序入口的,而此时Sub1中存放的是相对于安装程序入口的地址。所以应该将被安装代码放到code段标号Start前边。2:中断程序被调用时,table[bx]默认的段存器为cs,所以在安装程序中设置中断向量表时,应设:cs=200h,ip=0,而不是cs=0,ip=200hassumecs:codecodesegmentstart:安装程序;--------------------------被安装代码:;--------------------------codeendsendstart==图1==-----------------------------------------------------------------------------;任务:安装一个新的int7ch中断例程;功能:为显示输出提供功能子程序 ;参数:ah传递功能号;0表示清屏,1表示设置前景色,2表示设置背景色,3表示向上滚动一行,对于2、3号功能,用al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}assumecs:codecodesegment;新的int7ch中断例程s:jmpshortsettabledwsub1,sub2,sub3,sub4set:pushbxcmpah,3;判断ah中的功能号是否大于3jasretmovbl,ahmovbh,0addbx,bx;计算对应子程序在table表中的偏移callwordptrtable[bx];调用对应的功能子程序sret:popbxiret;功能:清屏sub1:pushbxpushcxpushesmovbx,0b800hmoves,bxmovbx,0movcx,2000subles:movbyteptres:[bx],""addbx,2loopsublespopespopcxpopbxret;设置前景色,al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}sub2:pushbxpushcxpushesmovbx,0b800hmoves,bxmovbx,1movcx,2000sub2s:andbyteptres:[bx],11111000bores:[bx],aladdbx,2loopsub2spopes popcxpopbxret;设置背景色,al传送颜色值,(al)∈{0,1,2,3,4,5,6,7}sub3:pushaxpushbxpushcxpushesmovcl,4shlal,clmovbx,0b800hmoves,bxmovbx,1movcx,2000sub3s:andbyteptres:[bx],10001111bores:[bx],aladdbx,2loopsub3spopespopcxpopbxpopaxret;向上滚动一行sub4:pushcxpushsipushdipushespushdsmovsi,0b800hmoves,simovds,simovsi,160;ds:si指向第N+1行movdi,0;es:di指向第N行cldmovcx,24;共复制24行sub4s:pushcxmovcx,160repmovsb;复制popcxloopsub4smovcx,80sub4s1:movbyteptr[160*24+si],"";最后一行清空addbx,2 loopsub4s1popdspopespopdipopsipopcxretsend:nopstart:movax,csmovds,axmovsi,offsets;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetsend-offsets;设置cx为传输长度cld;设置传输方向为正repmovsb;在中断向量表中设置新的int7ch中断例程的入口地址cli;设置IF=0屏蔽中断movwordptres:[7ch*4],0movwordptres:[7ch*4+2],20hsti;设置IF=1不屏蔽中断;结束movax,4c00hint21hcodeendsendstart=============================================================================应用举例测试程序assumecs:codecodesegmentstart:movax,303hint7chmovax,4c00hint21hcodeendsendstart17.3字符串的输入(非课后习题,仅为书中程序注释,实验用途)assumecs:codecodesegment start:movax,2000hmovds,axmovsi,0movdl,0movdh,0callgetstrmovax,4c00hint21h;子程序:接收字符串输入。getstr:pushaxgetstrs:movah,0int16hcmpal,20hjbnochar;ASCII码小于20h,说明不是字符movah,0callcharstack;字符入栈movah,2callcharstack;显示栈中字符jmpgetstrsnochar:cmpah,0eh;退格键的扫描码jebackspacecmpah,1ch;Enter键的扫描码jeenterjmpgetstrsbackspace:movah,1callcharstack;字符出栈movah,2callcharstack;显示栈中字符jmpgetstrsenter:moval,0movah,0callcharstack;0入栈movah,2callcharstack;显示栈中字符popaxret;子程序:字符栈的入栈、出栈和显示。;参数说明:(ah)=功能号,0表示入栈,1表示出栈,2表示显示; ;ds:si指向字符栈空间;;对于0号功能:(al)=入栈字符;;对于1号功能:(al)=返回的字符;;对于2号功能:(dh)、(dl)=字符串在屏幕上显示的行、列位置。charstack:jmpshortcharstarttabledwcharpush,charpop,charshowtopdw0;栈顶(字符地址、个数记录器)charstart:pushbxpushdxpushdipushescmpah,2;判断ah中的功能号是否大于2jasret;功能号>2,结束movbl,ahmovbh,0addbx,bx;计算对应子程序在table表中的偏移jmpwordptrtable[bx];调用对应的功能子程序charpush:movbx,topmov[si][bx],alinctopjmpsretcharpop:cmptop,0jesret;栈顶为0(无字符),结束dectopmovbx,top;//保存数据,其它作用不详moval,[si][bx];//保存数据,其它作用不详jmpsretcharshow:movbx,0b800hmoves,bxmoval,160movah,0muldh;dh*160movdi,axadddl,dl;dl*2movdh,0adddi,dx;di=dh*160+dl*2,es:di指向显存movbx,0;ds:[si+bx]指向字符串首地址 charshows:cmpbx,top;判断字符栈中字符是否全部显示完毕jnenoempty;top≠bx,有未显示字符,执行显示movbyteptres:[di],"";显示完毕,字符串末加空格jmpsretnoempty:moval,[si][bx];字符ASCII码赋值almoves:[di],al;显示字符movbyteptres:[di+2],"";字符串末加空格incbx;指向下一个字符adddi,2;指向下一显存单元jmpcharshowssret:popespopdipopdxpopbxretcodeendsendstart检测点17.1“在int16h中断例程中,一定有设置IF=1的指令。”这种说法对吗?正确,当键盘缓冲区为空时,如果设置IF=0,int9中断无法执行,循环等待会死锁。相关内容:IF=1,CPU响应中断,引发中断过程IF=0,不响应可屏蔽中断几乎所有由外设引发的外中断,都是可屏蔽中断(int9是可屏蔽中断)CPU对外设输入的通常处理方法:(1)外设的输入端口(2)向CPU发出外中断(可屏蔽中断)信息(3)CPU检测到可屏弊中断信息,如果IF=1,cpu在执行完当前指令后响应中断,执行相应的中断例程(4)可在中断例程中实现对外设输入的处理实验17通过逻辑扇区号对软盘进行读写(未调试,留底稿);功能:安装新的int7ch中断例程,实现通过逻辑扇区号对软盘进行读写;入口参数:;(dx)=读写扇区的逻辑扇区号;(ah)=0表示读扇区,(ah)=1表示写扇区 ;es:bx指向存储读出数据或写入数据的内存区;返回参数:;(ah)=int13h的功能号(2表示读扇区,3表示写扇区);(ch)=磁道号;(cl)=扇区号;(dh)=磁头号(面号)assumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsets;设置ds:si指向源地址movax,0moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetsend-offsets;设置cx为传输长度cld;设置传输方向为正repmovsb;在中断向量表中设置新的int7ch中断例程的入口地址cli;设置IF=0屏蔽中断movwordptres:[7ch*4],200hmovwordptres:[7ch*4+2],0sti;设置IF=1不屏蔽中断;结束movax,4c00hint21h;新的int7ch中断例程s:cmpah,0jes1cmpah,1jes2jasret;ah大于1,结束cmpdx,1443jasret;逻辑扇区号大于1443,结束s3:pushbxmovax,dx;逻辑扇区号赋值axmovdx,0movcx,1440divcx;商在ax;余在dxpushax;ax=面号=int(逻辑扇区号/1440),入栈movax,dxmovcx,18divcx;商在ax;余在dx pushax;ax=磁道号=int(rem(逻辑扇区号/1440)/18),入栈adddx,1;dx=扇区号=rem(rem(逻辑扇区号/1440)/18)+1movcl,dl;扇区号赋值clpopbx;磁道号出栈movch,blpopbx;面号出栈movdh,blpopbx;功能号出栈movah,blsret:popbxirets1:movah,2;int13h的功能号(ah=2表示读扇区)pushax;功能号,入栈jmps3s2:movah,3;int13h的功能号(ah=3表示写扇区)pushax;功能号,入栈jmps3send:nopcodeendsendstart课程设计2阅读下面的材料:开机后,CPU自动进入到FFFF:0单元处执行,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。硬件系统检测和初始化完成后,调用int19h进行操作系统的引导。如果设为从软盘启动操作系统,则int19h将主要完成以下工作。(1)控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00;(2)将CS:IP指向0:7c00。软盘的0道0面1扇区中装有操作系统引导程序。int19h将其装到0:7c00处后,设置CPU从0:7c00开始执行此处的引导程序,操作系统被激活,控制计算机。如果在0号软驱中没有软盘,或发生软盘I/O错误,则int19h将主要完成以下工作。(1)读取硬盘C的0道0面1扇区的内容到0:7c00;(2)将CS:IP指向0:7c00。这次课程设计的任务是编写一个可以自行启动的计算机,不需要在现有操作系统环境中运行的程序。该程序的功能如下:(1)列出功能选项,让用户通过键盘进行选择,界面如下1)resetpc;重新启动计算机2)startsystem;引导现有的操作系统3)clock;进入时钟程序4)setclock;设置时间 (2)用户输入"1"后重新启动计算机(提示:考虑ffff:0单元)(3)用户输入"2"后引导现有的操作系统(提示:考虑硬盘C的0道0面1扇区)。(4)用户输入"3"后,执行动态显示当前日期、时间的程序。显示格式如下:年/月/日时:分:秒进入此项功能后,一直动态显示当前的时间,在屏幕上将出现时间按秒变化的效果(提示:循环读取CMOS)。当按下F1键后,改变显示颜色;按下Esc键后,返回到主选单(提示:利用键盘中断)。(5)用户输入"4"后可更改当前的日期、时间,更改后返回到主选单(提示:输入字符串)。assumecs:codecodesegment;===============================================================;功能:将代码写入0面0道1扇区;入口参数:;(ah)=int13h的功能号(2表示读扇区,3表示写扇区);(al)=写入的扇区数;(ch)=磁道号;(cl)=扇区号;(dh)=磁头号(面号);(dl)=驱动器号软区从0开始,0:软驱A,1:软驱B;硬盘从80h开始,80h:硬盘C,81h:硬盘D;es:bx指向将写入磁盘的数据或指向接收从扇区读入数据的内存区;返回参数:;操作成功:(ah)=0,(al)=写入的扇区数;操作失败:(ah)=出错代码;===============================================================start:movax,floppyend-floppymovdx,0movbx,512divbx;商ax为所需的扇区数incal;写入的扇区数(为余数加扇区)pushcspopesmovbx,offsetfloppy;es:bx指向要被写入的内存单元movch,0;磁道号movcl,1;扇区号movdl,0;驱动器号,软盘Amovdh,0;磁头号(面号)movah,3;int13h的功能号(3表示写扇区)int13h;将代码写入0面0道1扇区 movax,4c00hint21hfloppy:jmpread;===============================================================;直接定址表;===============================================================tabledwfunction1-floppy,function2-floppydwfunction3-floppy,function4-floppymenudb"***mainMenu***",0db"1)resetpc",0db"2)startsystem",0db"3)clock",0db"4)setclock",0db"PleaseChoose:",0timedb"YY/MM/DDhh:mm:ss",0cmosdb9,8,7,4,2,0hintdb"pressF1tochangethecolor,pressEsctoreturn",0hint1db"Pleaseinput:YY/MM/DDhh:mm:ss",0chardb"//::",0;===============================================================;功能:将0面0道2扇区的内容写入0:7e00h;入口参数:;(ah)=int13h的功能号(2表示读扇区);(al)=写入的扇区数;(ch)=磁道号;(cl)=扇区号;(dh)=磁头号(面号);(dl)=驱动器号软区从0开始,0:软驱A,1:软区B;硬盘从80h开始,80h:硬盘C,81h:硬盘D;es:bx指向将写入磁盘的数据;返回参数:;操作成功:(ah)=0,(al)=写入的扇区数;操作失败:(ah)=出错代码;===============================================================read:movax,floppyend-floppymovdx,0movbx,512 divbx;商ax为所需的扇区数incalmovbx,0moves,bxmovbx,7e00h;es:bx指向要读入的内存单元movch,0;磁道号movcl,2;扇区号movdl,0;驱动器号movdh,0;磁头号(面号)movah,2;int13h的功能号(2表示读扇区)int13h;读取0面0道2扇区的内容到0:7e00h处;(第二扇区从512/200h开始)movax,7c0hpushax;pushcsmovax,showmenu-floppypushax;pushipretf;jmpshowmenu;***************************************************************;显示主菜单,调用show_str、clean子程序;***************************************************************showmenu:callclean;清屏pushcspopdsmovsi,menu-floppymovdh,8movdl,30movcx,6showmenu0:pushcxmovcl,2callshow_straddsi,16incdhpopcxloopshowmenu0;===============================================================;接收键盘输入,跳转相应功能程序段;调用BIOS用来提供读取键盘缓冲区功能的中断例程int16h, ;将读取的扫描码送入ah,ASCII码送入al;===============================================================go:movax,0int16hcmpal,"1"jbshowmenucmpal,"4"jashowmenusubal,31hmovbl,almovbh,0addbx,bxaddbx,3;计算相应子程序在table中的位移callwordptrcs:[bx]jmpshowmenu;***************************************************************;功能1:重新启动计算机;***************************************************************function1:movax,0ffffhpushaxmovax,0pushaxretf;jmpffff:0;***************************************************************;功能3:进入时钟程序;***************************************************************function3:pushaxpushbxpushcxpushdxpushsipushdspushescallclean;清屏movdh,0;行号movdl,0;列号movcl,2movsi,offsethint-floppy callshow_str;显示提示信息;===============================================================;名称:clock;功能:动态显示当前日期、时间;===============================================================movcx,2;显示颜色clock:movbx,offsetcmos-floppymovsi,offsettime-floppypushcxmovcx,6clock0:pushcxmoval,[bx]out70h,al;将al送入地址端口70hinal,71h;从数据端口71h处读出单元内容movah,almovcl,4shral,cl;右移4位andah,0fh;al分成两个表示BCD码值的数据addax,3030h;BCD码+30h=10进制数对应的ASCII码mov[si],ax;ASCII码写入time段incbxaddsi,3popcxloopclock0;---------------------------------------------------------------;按下F1键后,改变显示颜色;按下Esc键后,返回主菜单,其他键照常处理;---------------------------------------------------------------moval,0inal,60hpopcx;显示颜色cmpal,3bh;和F1的扫描码3bh比较jecolourcmpal,1;和esc的扫描码01h比较jeclockendjmpshow_clockcol_1:movcx,1;cl∈[1,7],0为黑色jmpshow_clockcolour:cmpcx,7jecol_1inccxshow_clock:movdh,12;行号movdl,30;列号 movsi,offsettime-floppycallshow_strjmpclock;循环显示CMOSclockend:popespopdspopsipopdxpopcxpopbxpopaxret;***************************************************************;功能4:设置时间;***************************************************************function4:pushaxpushbxpushcxpushdxpushsicallcleanmovdh,8;行号movdl,30;列号movcl,2movsi,offsethint1-floppycallshow_str;显示提示信息adddh,1;行号adddl,14;列号movsi,offsetchar-floppy;ds:si指向字符栈空间callshow_str;显示输入格式movdi,0callgetstrscallwiteincallcleancharpopsipopdxpopcxpopbxpopaxret ;===============================================================;清除char内输入数据,还原环境;===============================================================cleanchar:pushcxcleanchar1:movcx,dijcxzcleanchar2callcharpopjmpcleanchar1cleanchar2:popcxret;===============================================================;ASCII=>BCD,写入CMOS;===============================================================witein:pushsimovcx,6movbx,offsetcmos-floppywite:pushcxmoval,[bx]out70h,al;将al送入地址端口70hmovax,[si]subah,30h;10进制数对应的ASCII码-30h=BCD码subal,30hmovcl,4shlal,cl;左移4位addal,ah;al为8位BCD码out71h,al;从数据端口71h处写入单元内容addsi,3incbxpopcxloopwitepopsiret;===============================================================;子程序:接收数字输入;参数说明:di=char栈顶(字符地址、个数记录器);===============================================================getstrs:pushax pushbxgetstr:movax,0int16hcmpah,0eh;退格键的扫描码jebackspacecmpah,1ch;Enter键的扫描码jeenter1cmpal,"0"jbgetstrcmpal,"9"jagetstrcmpdi,16;限制输入个数jaenter1callcharpush;字符入栈callshow_str;显示栈中字符jmpgetstrbackspace:callcharpop;字符出栈callshow_str;显示栈中字符jmpgetstrenter1:callshow_str;显示栈中字符popbxpopaxret;===============================================================;子程序:数字的入栈。;参数说明:ds:si指向char栈空间;(al)=入栈字符;;===============================================================charpush:movbx,dimov[si][bx],alincdicmpdi,2jeaddscmpdi,5jeaddscmpdi,8jeaddscmpdi,11jeaddscmpdi,14jeaddsret adds:incdiret;===============================================================;子程序:数字的出栈。;参数说明:ds:si指向char栈空间;(al)=入栈字符;;===============================================================charpop:cmpdi,0jesret;栈顶为0(无字符),结束cmpdi,3jesubscmpdi,6jesubscmpdi,9jesubscmpdi,12jesubscmpdi,15jesubsdecdimovbx,dimoval,""mov[si][bx],alretsubs:subdi,2movbx,dimoval,""mov[si][bx],alretsret:ret;===============================================================;名称:show_str子程序;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。;参数:(dh)=行号(取值范围0~24);;(dl)=列号(取值范围0~79);;(cl)=颜色;;ds:si指向字符串的首地址。;返回:无。;===============================================================show_str:pushaxpushbxpushcx pushdxpushsipushesmovax,0b800hmoves,axmovax,160muldhmovbx,ax;bx=160*dhmovax,2muldl;ax=dl*2addbx,ax;movbx,(160*dh+dl*2)设置es:bx指向显存首地址moval,cl;把颜色cl赋值almovcl,0show0:movch,[si]jcxzshow1;(ds:si)=0时,转到show1执行moves:[bx],chmoves:[bx].1,alincsi;ds:si指向下一个字符地址addbx,2;es:bx指向下一个显存地址jmpshow0show1:popespopsipopdxpopcxpopbxpopaxret;===============================================================;名称:clean子程序;功能:清屏;===============================================================clean:pushbxpushcxpushesmovbx,0b800hmoves,bxmovbx,0movcx,2000clean0:movbyteptres:[bx],""addbx,2loopclean0popbxpopcx popesret;***************************************************************;功能2:引导现有的操作系统;***************************************************************;===============================================================;功能2实现引导现有的操作系统,代码需要将硬盘的0面0道1扇区读入0:7c00,;会覆盖从软盘读到0:7c00的第一个扇区,所以功能2代码不能写在第一个扇区;===============================================================function2:callcleanmovax,0moves,axmovbx,7c00hmoval,1;读取的扇区数movch,0;磁道号movcl,1;扇区号movdl,80h;驱动器号movdh,0;磁头号(面号)movah,2;int13h的功能号(2表示读扇区)int13h;读取0面0道1扇区的内容到0:7c00h处movax,0pushax;pushcsmovax,7c00hpushax;pushipretf;jmp0:7c00hfloppyend:nopcodeendsendstart研究试验1搭建一个精简的C语言开发环境除了TC.EXE外,必须用到的相关文件有5个,分别是:COS.OBJEMU.LIBMATHS.LIBGRAPHICS.LIBCS.LIB研究实验2使用寄存器(2)用debug加载ur1.exe,用u命令查看ur1.c编译后的机器码和汇编代码。 思考:main函数的代码在什么段?用debug怎样找到ur1.exe中main函数的代码?main函数的代码应该在code段中用Debug加载程序后用反汇编命令U找到main函数汇编代码。(3)用下面的方法打印出ur1.exe被加载运行时,main函数在代码段中的偏移地址:main(){printf("%xn",main);}"%x"指的是按照十六进制格式打印。思考:为什么这个程序能够打印出main函数在代码段中的偏移地址?main类似于汇编中子程序的标号,其入口偏移地址传递给printf函数被打印出来。(4)ur1.c源程序main(){_AX=1;_BX=1;_CX=2;_AX=_BX+_CX;_AH=_BL+_CL;_AL=_BH+_CH;printf("%xn",main);}Debug反汇编查看C:>debugur1.exe-u0C71:0000BAA90DMOVDX,0DA90C71:00032ECS:0C71:00048916F801MOV[01F8],DX0C71:0008B430MOVAH,300C71:000ACD21INT210C71:000C8B2E0200MOVBP,[0002]0C71:00108B1E2C00MOVBX,[002C]0C71:00148EDAMOVDS,DX0C71:0016A39200MOV[0092],AX0C71:00198C069000MOV[0090],ES0C71:001D891E8C00MOV[008C],BX-u. ..-u0C71:01F80000ADD[BX+SI],AL0C71:01FA55PUSHBP;main函数入口0C71:01FB8BECMOVBP,SP0C71:01FDB80100MOVAX,00010C71:0200BB0100MOVBX,00010C71:0203B90200MOVCX,00020C71:02068BC3MOVAX,BX0C71:020803C1ADDAX,CX0C71:020A8AE3MOVAH,BL0C71:020C02E1ADDAH,CL0C71:020E8AC7MOVAL,BH0C71:021002C5ADDAL,CH0C71:0212B8FA01MOVAX,01FA;main函数偏移地址赋值AX0C71:021550PUSHAX0C71:0216B89401MOVAX,0194-u0C71:021950PUSHAX0C71:021AE8B808CALL0AD5;调用显示地址子程序10C71:021D59POPCX0C71:021E59POPCX0C71:021F5DPOPBP0C71:0220C3RET;main函数结束0C71:022155PUSHBP0C71:02228BECMOVBP,SP0C71:022456PUSHSI0C71:02258B7604MOVSI,[BP+04]0C71:02280BF6ORSI,SI0C71:022A7C14JL02400C71:022C83FE58CMPSI,+580C71:022F7603JBE02340C71:0231BE5700MOVSI,00570C71:023489369801MOV[0198],SI0C71:02388A849A01MOVAL,[SI+019A]-u0C71:0AD50C71:0AD555PUSHBP;显示地址子程序1入口0C71:0AD68BECMOVBP,SP0C71:0AD8B84D0CMOVAX,0C4D0C71:0ADB50PUSHAX0C71:0ADCB81002MOVAX,02100C71:0ADF50PUSHAX0C71:0AE0FF7604PUSH[BP+04] 0C71:0AE38D4606LEAAX,[BP+06]0C71:0AE650PUSHAX0C71:0AE7E84C02CALL0D36;调用子程序20C71:0AEAEB00JMP0AEC0C71:0AEC5DPOPBP0C71:0AEDC3RET;子程序1结束返回0C71:0AEE55PUSHBP0C71:0AEF8BECMOVBP,SP0C71:0AF18B5E06MOVBX,[BP+06]0C71:0AF4FF0FDECWORDPTR[BX]-u0C71:0D360C71:0D3655PUSHBP;调用子程序2入口0C71:0D378BECMOVBP,SP0C71:0D3981EC9600SUBSP,00960C71:0D3D56PUSHSI0C71:0D3E57PUSHDI0C71:0D3FC746AA0000MOVWORDPTR[BP-56],00000C71:0D44C646AD50MOVBYTEPTR[BP-53],500C71:0D48EB38JMP0D820C71:0D4A57PUSHDI0C71:0D4BB9FFFFMOVCX,FFFF0C71:0D4E32C0XORAL,AL0C71:0D50F2REPNZ0C71:0D51AESCASB0C71:0D52F7D1NOTCX0C71:0D5449DECCX0C71:0D555FPOPDI-u0C71:0D56C3RET;子程序2结束返回0C71:0D578805MOV[DI],AL0C71:0D5947INCDI0C71:0D5AFE4EADDECBYTEPTR[BP-53]0C71:0D5D7E22JLE0D810C71:0D5F53PUSHBX0C71:0D6051PUSHCX0C71:0D6152PUSHDX0C71:0D6206PUSHES0C71:0D638D46AELEAAX,[BP-52]0C71:0D662BF8SUBDI,AX0C71:0D688D46AELEAAX,[BP-52]0C71:0D6B50PUSHAX0C71:0D6C57PUSHDI0C71:0D6DFF7608PUSH[BP+08]0C71:0D70FF560ACALL[BP+0A] 0C71:0D73C646AD50MOVBYTEPTR[BP-53],50-(5)通过main函数后面有ret指令,我们可以设想:C语言将函数实现为汇编语言中的子程序。研究下面程序的汇编代码,验证这个设想。ur2.c源程序voidf(void);main(){_AX=1;_BX=1;_CX=2;f();}voidf(void){_AX=_BX+_CX;}Debug反汇编查看C:>debugur2.exe-U0C71:1FA0C71:01FA55PUSHBP;main函数入口0C71:01FB8BECMOVBP,SP0C71:01FDB80100MOVAX,00010C71:0200BB0100MOVBX,00010C71:0203B90200MOVCX,00020C71:0206E80200CALL020B;调用f函数0C71:02095DPOPBP0C71:020AC3RET0C71:020B55PUSHBP0C71:020C8BECMOVBP,SP0C71:020E8BC3MOVAX,BX0C71:021003C1ADDAX,CX0C71:02125DPOPBP0C71:0213C3RET;main函数结束返回0C71:0214C3RET0C71:021555PUSHBP0C71:02168BECMOVBP,SP0C71:0218EB0AJMP0224-U0C71:020B0C71:020B55PUSHBP;f函数入口0C71:020C8BECMOVBP,SP 0C71:020E8BC3MOVAX,BX0C71:021003C1ADDAX,CX0C71:02125DPOPBP0C71:0213C3RET;f函数结束返回0C71:0214C3RET0C71:021555PUSHBP0C71:02168BECMOVBP,SP0C71:0218EB0AJMP02240C71:021A8B1E9E01MOVBX,[019E]0C71:021ED1E3SHLBX,10C71:0220FF97A601CALL[BX+01A6]0C71:0224A19E01MOVAX,[019E]0C71:0227FF0E9E01DECWORDPTR[019E]-当main函数在调用voidf(void)这个函数时,其汇编代码为call地址验证了C语言将函数实现为汇编语言中的子程序,C函数名相当于子程序的标号。研究试验3使用内存空间(1)um1.c源程序main(){*(char*)0x2000="a";*(int*)0x2000=0xf;*(charfar*)0x20001000="a";_AX=0x2000;*(char*)_AX="b";_BX=0x1000;*(char*)(_BX+_BX)="a";*(charfar*)(0x20001000+_BX)=*(char*)_AX;}Debug反汇编查看C:>debugum1.exe-u0c71:1fa0C71:01FA55PUSHBP;main函数入口0C71:01FB8BECMOVBP,SP0C71:01FDC606002061MOVBYTEPTR[2000],61;"a"写入ds:20000C71:0202C70600200F00MOVWORDPTR[2000],000F;0fh写入ds:20000C71:0208BB0020MOVBX,20000C71:020B8EC3MOVES,BX0C71:020DBB0010MOVBX,1000 0C71:021026ES:0C71:0211C60761MOVBYTEPTR[BX],61;"a"写入2000:10000C71:0214B80020MOVAX,20000C71:02178BD8MOVBX,AX0C71:0219C60762MOVBYTEPTR[BX],62;"b"写入ds:2000-u0C71:021CBB0010MOVBX,10000C71:021F03DBADDBX,BX0C71:0221C60761MOVBYTEPTR[BX],61;"a"写入ds:20000C71:02248BD8MOVBX,AX0C71:02268A07MOVAL,[BX]0C71:022833C9XORCX,CX0C71:022A81C30010ADDBX,10000C71:022E81D10020ADCCX,20000C71:02328EC1MOVES,CX0C71:023426ES:0C71:02358807MOV[BX],AL;"a"写入2000:30000C71:02375DPOPBP0C71:0238C3RET;main函数结束返回0C71:0239C3RET单步跟踪执行情况-g01faAX=0000BX=059ACX=0015DX=F21FSP=FFE8BP=FFF2SI=0366DI=0555DS=0CCAES=0CCASS=0CCACS=0C71IP=01FANVUPEIPLZRNAPENC0C71:01FA55PUSHBP-tAX=0000BX=059ACX=0015DX=F21FSP=FFE6BP=FFF2SI=0366DI=0555DS=0CCAES=0CCASS=0CCACS=0C71IP=01FBNVUPEIPLZRNAPENC0C71:01FB8BECMOVBP,SP-tAX=0000BX=059ACX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=0CCASS=0CCACS=0C71IP=01FDNVUPEIPLZRNAPENC0C71:01FDC606002061MOVBYTEPTR[2000],61DS:2000=69-d0cca:2000200f0CCA:200069636520796F7520-77616E7420746F20iceyouwantto-tAX=0000BX=059ACX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=0CCASS=0CCACS=0C71IP=0202NVUPEIPLZRNAPENC0C71:0202C70600200F00MOVWORDPTR[2000],000FDS:2000=6361-d0cca:2000200f0CCA:200061636520796F7520-77616E7420746F20aceyouwantto-tAX=0000BX=059ACX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555 DS=0CCAES=0CCASS=0CCACS=0C71IP=0208NVUPEIPLZRNAPENC0C71:0208BB0020MOVBX,2000-d0cca:2000200f0CCA:20000F006520796F7520-77616E7420746F20..eyouwantto-tAX=0000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=0CCASS=0CCACS=0C71IP=020BNVUPEIPLZRNAPENC0C71:020B8EC3MOVES,BX-tAX=0000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=020DNVUPEIPLZRNAPENC0C71:020DBB0010MOVBX,1000-tAX=0000BX=1000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0210NVUPEIPLZRNAPENC0C71:021026ES:0C71:0211C60761MOVBYTEPTR[BX],61ES:1000=00-d2000:1000100f2000:10000000000000000000-0000000000000000................-tAX=0000BX=1000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0214NVUPEIPLZRNAPENC0C71:0214B80020MOVAX,2000-d2000:1000100f2000:10006100000000000000-0000000000000000a...............-tAX=2000BX=1000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0217NVUPEIPLZRNAPENC0C71:02178BD8MOVBX,AX-tAX=2000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0219NVUPEIPLZRNAPENC0C71:0219C60762MOVBYTEPTR[BX],62DS:2000=0F-tAX=2000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=021CNVUPEIPLZRNAPENC0C71:021CBB0010MOVBX,1000-d0cca:2000200f0CCA:200062006520796F7520-77616E7420746F20b.eyouwantto-tAX=2000BX=1000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=021FNVUPEIPLZRNAPENC0C71:021F03DBADDBX,BX-t AX=2000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0221NVUPEIPLNZNAPENC0C71:0221C60761MOVBYTEPTR[BX],61DS:2000=62-tAX=2000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0224NVUPEIPLNZNAPENC0C71:02248BD8MOVBX,AX-d0cca:2000200f0CCA:200061006520796F7520-77616E7420746F20a.eyouwantto-tAX=2000BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0226NVUPEIPLNZNAPENC0C71:02268A07MOVAL,[BX]DS:2000=61-tAX=2061BX=2000CX=0015DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0228NVUPEIPLNZNAPENC0C71:022833C9XORCX,CX-tAX=2061BX=2000CX=0000DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=022ANVUPEIPLZRNAPENC0C71:022A81C30010ADDBX,1000-tAX=2061BX=3000CX=0000DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=022ENVUPEIPLNZNAPENC0C71:022E81D10020ADCCX,2000-tAX=2061BX=3000CX=2000DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0232NVUPEIPLNZNAPENC0C71:02328EC1MOVES,CX-tAX=2061BX=3000CX=2000DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0234NVUPEIPLNZNAPENC0C71:023426ES:0C71:02358807MOV[BX],ALES:3000=00-d2000:3000300f2000:30000000000000000000-0000000000000000................-tAX=2061BX=3000CX=2000DX=F21FSP=FFE6BP=FFE6SI=0366DI=0555DS=0CCAES=2000SS=0CCACS=0C71IP=0237NVUPEIPLNZNAPENC0C71:02375DPOPBP-d2000:3000300f2000:30006100000000000000-0000000000000000a...............- (2)char型数据为字节型操作,占1个内存单元int型数据为字型操作,占2个内存单元一条指令,需将颜色和字符同时写入,使用int型main(){*(int*)0xb80007ce=0x261;}(3)分析下面程序中所有函数的汇编代码,思考相关的问题。inta1,a2,a3;voidf(void);main(){intb1,b2,b3;a1=0xa1;a2=0xa2;a3=0xa3;b1=0xb1;b2=0xb2;b3=0xb3;printf("%xn",main);}voidf(void){intc1,c2,c3;a1=0x0fa1;a2=0xfa2;a3=0x0fa3;c1=0xc1;c2=0xc2;c3=0xc3;}问题:C语言将全局变量存放在哪里?将局部变量存放在哪里?每个函数开关的“pushbpmovbp,sp”有何含义?Debug反汇编查看1412:01FA55PUSHBP1412:01FB8BECMOVBP,SP1412:01FD83EC06SUBSP,+061412:0200C7062604A100MOVWORDPTR[0426],00A11412:0206C7062804A200MOVWORDPTR[0428],00A21412:020CC7062A04A300MOVWORDPTR[042A],00A31412:0212C746FAB100MOVWORDPTR[BP-06],00B11412:0217C746FCB200MOVWORDPTR[BP-04],00B21412:021CC746FEB300MOVWORDPTR[BP-02],00B31412:0221B8FA01MOVAX,01FA1412:022450PUSHAX;main函数入口1412:0225B89401MOVAX,01941412:022850PUSHAX1412:0229E8E508CALL0B111412:022C59POPCX 1412:022D59POPCX1412:022E8BE5MOVSP,BP1412:02305DPOPBP1412:0231C3RET全局变量存放在DS段中,局部变量存放在SS段中。PUSHBPMOVBP,SP作用为用BP保存堆栈指针,从而能够在使用局部变量时用[BP+idata]来定位。(4)分析下面程序的汇编代码,思考相关的问题。intf(void);inta,b,ab;main(){intc;c=f();}intf(void){ab=a+b;returnab;}问题:C语言将函数的返回值存放在哪里?Debug反汇编查看1412:01FA55PUSHBP1412:01FB8BECMOVBP,SP1412:01FD83EC02SUBSP,+021412:0200E80700CALL020A1412:02038946FEMOV[BP-02],AX1412:02068BE5MOVSP,BP1412:02085DPOPBP1412:0209C3RET1412:020A55PUSHBP1412:020B8BECMOVBP,SP1412:020DA1A601MOVAX,[01A6]1412:02100306A801ADDAX,[01A8]1412:0214A3AA01MOV[01AA],AX1412:0217A1AA01MOVAX,[01AA]1412:021AEB00JMP021C1412:021C5DPOPBP1412:021DC3RETC语言将函数的返回值存放在AX中。(5)下面的程序向安全的内存空间写入从"a"到"h"的8个字符,理解程序的含义,深入理解相关的知识。 #defineBuffer((char*)*(intfar*)0x02000000)main(){Buffer=(char*)malloc(20);Buffer[10]=0;while(Buffer[10]!=8){Buffer[Buffer[10]]="a"+Buffer[10];Buffer[10]++;}}标志寄存器flag151413121110090807060504030201000000ofdfiftfsfzf0af0pf0cfZF是flag的第6位,零标志位,判断结果是否为0,结果为0,ZF=1PF是flag的第2位,奇偶标志位,运算结果二进制数中1的个数为偶数,PF=1SF是flag的第7位,符号标志位,有符号数运算结果为负数,SF=1CF是flag的第0位,进位标志位,无符号数运算结果有进/借位,CF=1OF是flag的第11位,溢出标志位,有符号数运算结果溢出,OF=1DF是flag的第10位,方向标志位,DF=0每次操作后si,di递增DF=1每次操作后si,di递减TF是flag的第8位,TF=1,产生单步中断,引发中断过程IF是flag的第9位,IF=1,CPU响应中断,引发中断过程IF=0,不响应可屏蔽中断add、sub、mul、div、inc、or、and等运算指令影响flagmov、push、pop等传送指令对flag没影响abc带位加法指令,利用CF位上记录的进位值abcax,bx实现功能(ax)=(ax)+(bx)+CFsbb带位减法指令,利用CF位上记录的借位值sbbax,bx实现功能(ax)=(ax)-(bx)-CFcmp比较指令,相当于减法指令,不保存结果,只影响flag相关各位cmpax,bx如果(ax)=(bx),则zf=1如果(ax)≠(bx),则zf=0如果(ax)<(bx),则cf=1如果(ax)≥(bx),则cf=0如果(ax)>(bx),则cf=0且zf=0如果(ax)≤(bx),则cf=1或zf=1 如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然为负cmp指令和条件转移指令配合使用指令含义检测的相关标志位je等于则转移zf=1jne不等于则转移zf=0ja高于则转移cf=0且zf=0jb低于则转移cf=1jna不高于则转移cf=1或zf=1jnb不低于则转移cf=0[…]是闭区间,包括两端点的值(…)是开区间,不包括两端点的值DF标志和串传送指令DF方向标志位,在串处理指令中,控制每次操作后si、di的增减df=0每次操作后si、di递增df=1每次操作后si、di递减movsb:相当于moves:[di],byteptrds:[si]如果df=0如果df=1incdidecdiincsidecsimovsw:相当于moves:[di],wordptrds:[si]如果df=0如果df=1addsi,2subsi,2adddi,2subdi,2movsb或movsw和rep配合使用,格式如下:repmovsb相当于s:movsbloopsrep的作用是根据cx的值,重复执行rep后面的串传送指令cld将标志寄存器中的DF位置0,(配合movsb,则是正向传送)std将标志寄存器中的DF位置1,(配合movsb,则是反向传送)pushf标志寄存器的值压栈popf标志寄存器的值出栈标志位在debug中的表示AX=0000BX=0000CX=0000DX=0000SP=FFEEBP=0000SI=0000DI=0000 DS=****ES=****SS=****CS=****IP=0100NVUPEIPLNZNAPONCflagofdfsfzfpfcf值为1的标记OVDNNGZRPECY值为0的标记NVUPPLNZPONC确定补码:Xh为8位,X∈(80h,ffh),则Xh是(Xh-256)的补码Xh为16位,X∈(8000h,ffffh),则Xh是(Xh-65535)的补码内中断4种情况将产生相应的中断信息(1)除法错误(2)单步执行(3)执行into指令(4)执行int指令从内存0:0到0:3fff的1024个单元中存放着中断向量表一个表项存放一个中断向量,也就是一个中断处理程序的入口地址,这个入口地址包括段地址和偏移地址,一个表项占两个字,高地址存放段地址,低地址存放偏移地址中断过程:(1)取得中断类型码N(2)pushf(3)TF=0,IF=0(4)pushCS(5)pushIP(6)(IP)=(N*4),(CS)=(N*4+2)iret指令,相当于:ret指令,相当于:retf指令,相当于:popIPpopIPpopIPpopCSpopCSpopfiret与int指令配合使用,call和ret指令配合使用。编写N号中断处理程序步骤:(1)编写N号中断处理程序:do0(2)将do0送入内存0:200处(3)将do0的入口地址0:200存储在中断向量表N号表项中assumecs:codecodesegmentstart:movax,csmovds,axmovsi,offsetdo0;设置ds:si指向源地址movax,0 moves,axmovdi,200h;设置es:di指向目标地址movcx,offsetdo0end-offsetdo0;设置cx为传输长度cld;设置传输方向为正repmovsbmovax,0moves,axmovwordptres:[N*4],200hmovwordptres:[N*4+2],0;设置中断向量表movax,4c00hint21hdo0:……movax,4c00hint21hdo0end:nopcodeendsendstartTF是flag的第8位,TF=1,产生单步中断,引发中断过程IF是flag的第9位CPU执行完设置SS指令后,不响应中断端口CPU可以直接读写三个地方的数据:(1)CPU内部的寄存器(2)内存单元(3)端口端口N∈(0,255)从端口N读入一字节:inal,N从端口N读入一字:inax,N往端口N写入一字节:outN,al往端口N写入一字:outN,ax端口N∈(256,65535)从端口N读入一字节:movdx,Ninal,dx从端口N读入一字:movdx,Ninax,dx往端口N写入一字节:movdx,NoutN,ax往端口N写入一字:movdx,NoutN,ax CMOSRAM芯片,简称CMOS,有两个端口:70h为地址端口,存放要访问的CMOS单元的地址71h为数据端口,存放从选定的CMOS单元中读取的数据,或要写入的数据CPU对CMOSRAM的读写分两步进行:1、将N送入端口70h2、从端口71h处读出N号单元内容shl逻辑左移指令,功能:(1)将一个寄存器或内存单元中的数据向左移位(2)将最后移出的一位写入CF(3)最低位用0补充将X逻辑左移一位,相当于执行X=X*2shr逻辑右移指令,功能:(1)将一个寄存器或内存单元中的数据向右移位(2)将最后移出的一位写入CF(3)最高位用0补充将X逻辑右移一位,相当于执行X=X/2移动位数>1时,移动位数放在cl中moval,01010001bmovcl,3shlal,clshral,cl左移1位,N=N*2右移1位,N=N/2左移2位,N=N*4右移2位,N=N/4左移3位,N=N*8右移3位,N=N/8左移4位,N=N*16右移4位,N=N/16左移5位,N=N*32右移5位,N=N/32左移6位,N=N*64右移6位,N=N/64BCD码——4位2进制表示10进制数码,一个字节表示两个BCD码,两个BCD码表示两位的10进制数BCD码+30h=10进制数对应的ASCII码CMOSRAM存放着当前时间:每个信息长度1字节,以BCD码方式存放时间存放单元:秒分时日月年024789 1字节al分成两个表示BCD码值的数据,相当于al=12345678转成ah=5678,al=1234movah,almovcl,4shrah,cl;右移4位andal,00001111b外中断CPU通过总线和端口来与外部设备进行联系,外部可屏蔽中断的中断类型码是通过数据总线送入CPU的。IF=1,CPU响应中断,引发中断过程IF=0,不响应可屏蔽中断sti指令,设置IF=1cli指令,设置IF=0中断过程:(1)取得中断类型码N(2)pushf(3)TF=0,IF=0(4)pushCS(5)pushIP(6)(IP)=(N*4),(CS)=(N*4+2)不可屏蔽中断的中断过程:(不可屏蔽中断的中断类型码固定为2,不用获取)(1)pushf(2)TF=0,IF=0(3)pushCS(4)pushIP(5)(IP)=(8),(CS)=(0AH)几乎所有由外设引发的外中断,都是可屏蔽中断键盘按下一个键产生的扫描码为通码键盘松开一个键产生的扫描码为断码扫描码长度为一字节,通码第7位为0,断码第7位为1断码=通码+80hp274页——键盘上部分键的扫描码键盘输入到达60H端口时,引发9号中断9号中断是可屏蔽中断,由BIOS提供的,用来进行基本的键盘输入处理执行int9中断:(1)读出60H端口中的扫描码 (2)如果是字符扫描码,将扫描码和对应的字符码(ASCII码)送入内存BIOS键盘缓冲区如果是控制键,则将其转为状态字节写入存储状态字的单元(3)对键盘系统进行相关的控制在BIOS键盘缓冲区中可存储15个键盘输入,一个键盘输入用一个字单元存放,高位扫描码,低位字符码0040:17单元存放键盘状态字节,记录了控制键和切换键的状态p275页——键盘状态字节各位记录信息键盘输入的处理过程:1、键盘产生扫描码2、扫描码送入60H端口3、引发9号中断4、CPU执行int9中断例程处理键盘输入int指令执行中断过程:模拟(1)取得中断类型码N(1)不需要定位入口地址(2)标志寄存器入栈(2)pushf(3)TF=0,IF=0(3)pushfpopaxandah,11111100b;IF为flag的第9位;TF为flag的第8位pushaxpopf(4)CS、IP入栈(4)calldwordptrds:[0](5)(IP)=(N*4),(CS)=(N*4+2)因为在进入中断例程后,IF和TF都已置0,没有必要再进行设置了,对于模拟int指令可以精简为:pushf;标志寄存器入栈calldwordptrds:[0];CS、IP入栈;(IP)=ds:[0],(CS)=ds:[2]CPU对外设输入的通常处理方法:(1)外设的输入端口(2)向CPU发出外中断(可屏蔽中断)信息(3)CPU检测到可屏弊中断信息,如果IF=1,cpu在执行完当前指令后响应中断,执行相应的中断例程(4)可在中断例程中实现对外设输入的处理直接定址表assumecs:codecodesegmentadw1,2,3,4,5,6,7,8bdd0start:. ..movax,4c00hint21hcodeendsendstarta、b后面没有“:”,它们是同时描写内存单元地址和单元长度的标号在后面加“:”的地址标号,只能在代码段中使用,不能在其他段中使用数据标号和地址标号唯一的区别就是,数据标号既表示内存单元的地址,还表示内存单元的长度,而地址标号只表示内存单元的地址在代码段中直接使用数据标号访问数据,则需要用伪指令assume将标号所在的段和一个段寄存器联系起来。否则编译器在编译的时候,无法确定标号的段地址在哪一个寄存器中。这种联系是编译器需要的,但绝对不是说,因为编译器的工作需要,用assume指令将段寄存器和某个段相联系,段寄存器中就会真的存放该段的地址,在程序中还要使用指令对段寄存器进行设置。seg操作符,功能为取得某一段的段地址通过依据数据,直接计算出所要找的元素的位置的表为直接定址表直接定址表包含了数据长度信息,可以方便的编写一些查表类的程序,直接定址表的数据可以定义在代码段使用BIOS进行键盘输入和磁盘读写int9h是把键盘的扫描码读入并将其转化成ASCⅡ码或状态信息,存储在内存的指定位置的中断例程int9h中断例程对键盘输入的处理(一)当有字符键按下时:1、从60h端口读出该键通码2、检测状态字节(shift、ctrl等状态键是否按下)3、没有状态键按下,将该键扫描码和对应ASCII码写入键盘缓冲区(缓冲区字单元中,高位存储扫描码,低位存储ASCII码)(二)当有状态键按下时:1、接收该键通码2、设置40:17处状态字节第1位为1int16h是BIOS用来提供读取键盘缓冲区功能的中断例程int16h中断例程的0号功能:读取键盘缓冲区1、检测键盘缓冲区是否有数据2、没有则继续第一步3、读取缓冲区第一个字单元中的键盘输入4、将读取的扫描码送入ah,ASCII码送入al5、将已读取的键盘输入从缓冲区中删除 BIOS提供的访问磁盘的中断例程为int13h。3.5寸软盘分上下两面,每面80个磁道,每个磁道18个扇区,每个扇区大小为512个字节3.5寸软盘=2面*80磁道*18扇区*512字节=1440KB≈1.44MB面号和磁道号从0开始,而扇区号从1开始;功能:读取0面0道1扇区的内容到0:200;入口参数:;(ah)=int13h的功能号(2表示读扇区);(al)=读取的扇区数;(ch)=磁道号;(cl)=扇区号;(dh)=磁头号(对于软盘即面号,一个面用一个磁头来读写);(dl)=驱动器号软区从0开始,0:软驱A,1:软区B;硬盘从80h开始,80h:硬盘C,81h:硬盘D;es:bx指向接收从扇区读入数据的内存区;返回参数:;操作成功:(ah)=0;操作失败:(ah)=出错代码movax,0moves,axmovbx,200h;es:bx指向0:200moval,1;读取的扇区数movch,0;磁道号movcl,1;扇区号movdl,0;驱动器号movdh,0;磁头号(面号)movah,2;int13h的功能号(2表示读扇区)int13h;功能:将0:200的内容写入0面0道1扇区;入口参数:;(ah)=int13h的功能号(3表示写扇区);(al)=写入的扇区数;(ch)=磁道号;(cl)=扇区号;(dh)=磁头号(面号);(dl)=驱动器号软区从0开始,0:软驱A,1:软区B;硬盘从80h开始,80h:硬盘C,81h:硬盘D;es:bx指向将写入磁盘的数据;返回参数:;操作成功:(ah)=0,(al)=写入的扇区数 ;操作失败:(ah)=出错代码movax,0moves,axmovbx,200h;es:bx指向0:200moval,1;写入的扇区数movch,0;磁道号movcl,1;扇区号movdl,0;驱动器号movdh,0;磁头号(面号)movah,3;int13h的功能号(3表示写扇区)int13h;功能:将当前屏幕内容保存在磁盘上;1屏的内容占4000个字节,需要8个扇区,用0面0道的1-8扇区存储显示中的内容assumecs:codecodesegmentstart:movax,0b800hmoves,axmovbx,0;es:bx指向0b800:0moval,8;写入的扇区数movch,0;磁道号movcl,1;扇区号movdl,0;驱动器号movdh,0;磁头号(面号)movah,3;int13h的功能号(3表示写扇区)int13hmovax,4c00hint21hcodeendsendstart《汇编语言(第2版)》勘误《汇编语言(第2版)》第6页,第11行。原文为:机器码:101000000000001100000000修改为:机器码:101000010000001100000000 《汇编语言(第2版)》第330页第11行。“用补码的特性,-20的绝对值是20,00010100b,将其取反加1后为:11101100b。可知-20H的补码为:11101100b。”中的“-20H”应改为“-20”。《汇编语言(第2版)》目录(第VII页)“第12章内中断”中的子目录中原文:12.5中断处理程序和ire指令应为:12.5中断处理程序和iret指令《汇编语言(第2版)》第140页,第10行有印刷错误。原文为:“db"fork"”相当于“db66H、6FH、52H、4BH”修改为:“db"fork"”相当于“db66H,6FH,52H,4BH”《汇编语言(第2版)》第194页。检测点10.4中的“1000:2ffd0callax”一行应修改为“1000:3ffd0callax”。在masm5.0的实验环境下,《汇编语言(第2版)》中第180页中图9.3中的内容“jmps0”应修改为“jmpshorts0”。《汇编语言(第2版)》第22页倒数第2行。“比直”应修改为“笔直”。摘录的汇编网在线测试题目(部分)****************************************************************************第1章基础知识(1)一个CPU的寻址能力为8KB,那么它的地址总线的宽度为。1、82、103、124、13(2)总线从逻辑上分为3类,下列选项中不在其中的是:。1、数据总线2、并行总线3、地址总线4、控制总线(3)1个CPU的寻址能力为32KB,那么它的地址总线宽度为。1、132、15 3、184、32k(4)1个CPU读取1024字节的数据至少读取了512次,数据总线的宽度。1、82、103、164、32(5)1个CPU访问的最大内存地址是1023,地址总线的宽度。1、82、103、134、14****************************************************************************第2章寄存器(CPU工作原理)(1)下列地址信息与0020H:03EFH确定的内存地址不同的是。1、5EFH2、203H:00EFH3、005EH:000FH4、0002H:05CFH(2)指令执行后AX中的数据是:。movax,936aHmovbx,79b8Haddal,bl1、1c22H2、9322H3、9422H4、1d22H(3)CPU从1000:0处开始执行指令当执行完1000:10处的指令后CPU几次修改IP。1000:0movax,81000:3jmpax1000:5movax,01000:8movbx,ax1000:10jmpbx1、42、53、64、7(4)在DEBUG中,选项中的命令可以修改内存单元的内容 1、a2、d3、t4、u(5)下列说法中正确的是:。1、一条指令被执行后,IP的值进行改变。2、当CPU执行完当前指令返回debug后CPU就闲下来不再进行工作。3、e命令可将所有内存单元中的数据进行改变。4、CPU将CS:IP所指向的内存单元中的数据当作指令来执行。(6)下列关于8086CPU的工作原理的描述错误的是。1、汇编程序员可以通过对各种寄存器中内容的修改实现对CPU的控制。2、CPU在访问内存时,采用“段地址*16+偏移地址”的形式给出要访问的内存单元的物理地址。3、任意时刻,CS:IP指向的内容即是此刻CPU正在执行的指令。4、传送指令能够更改所有通用寄存器的内容。****************************************************************************第3章寄存器(内存访问)(1)下列说法正确的是:。1、数据段和代码段的段地址不能相同。2、指令movax,bx执行完后bx中的值为零。3、一个栈段的大小可以设为任意值。4、当SP=0时,再次压栈将发生栈顶超界,但压栈操作有效。(2)能够将ax中的内容送到内存0000:0200H处的指令序列是。1、movds,0;movbx,200hmov[bx],ax2、movax,200hmovds,axmovbx,0mov[bx],ax3、movax,20hmovds,axmovbx,0mov[bx],ax4、movbx,20hmovds,bxmovbx,0mov[bx],ax(3)在8086CPU系统中一个栈段的容量最大为。1、1KB 2、512KB3、64KB4、32GB(4)能够只将al中的内容压入栈的指令序列是。1、pushal2、popax3、movah,0pushax4、movax,0pushax(5)若将以1000H为段地址的整个段空间当作栈使用,那么寄存器SP的初始值最合理的设置是。1、0000H2、0001H3、FFFFH4、FFFEH****************************************************************************第4章第一个程序(1)关于伪指令相关描述错误的是。1、伪指令没有对应的机器码,只用来指导汇编过程的。2、伪指令由编译器处理,在程序中可有可无。3、编译器要通过执行伪指令才能对源程序进行相应的处理操作,完成编译工作。4、伪指令是汇编语言源程序不可缺少的组成部分。(2)下列程序中,出现逻辑错误的是:。1、assumecs:codecodesegmentmovax,2addax,axmovax,4c00hint21hcodeend2、assumecs:codecodesegmentmovax,2addax,axcodeendsend3、aumecs:codecodesegmentmovax,2 addax,axmovax,4c00hint21hcodeendsend4、assumecs:codecodesegmentmovax,2addax,axmovax,4c00hint21hcodeends****************************************************************************第5章[bx]和loop指令(1)在Intel8086环境下,对指令movax,[bx]描述错误的是。1、指令中,源操作数的段地址默认为ds中的内容2、指令中,源操作数的偏移地址为bx中的内容3、指令执行后,(al)=((ds)*16+(bx)),(ah)=((ds)*16+(bx)+1)4、指令执行后,((ds)*16+(bx))=(al),((ds)*16+(bx)+1)=(ah)(2)movcx,5s:movax,[bx]addbx,2loops上面指令序列,当指令第一次执行到addbx,2时cx的值。1、52、43、34、2(3)已知21000h处字单元的内容为BE00H,对于如下程序:movax,2000hmovds,axmovbx,1000hmovax,[bx]incbxincbxmov[bx],axincbxincbxmov[bx],axincbxmov[bx],al incbxmov[bx],al程序执行后,内存中字单元2000:1005中的内容为。1、002、BE3、00BE4、0000(4)要计算123与456的乘积,应填在空白处的指令序列是。assumecs:codecodesegment____________movax,4c00hint21hcodeendsend1、movax,1movcx,123s:addax,123loops2、movax,0movcx,456s:addax,456loops3、movax,1movcx,456s:addax,123loops4、movax,0movcx,456s:addax,123loops(5)对于如下程序assumecs:codecodesegmentstart:movax,codemovds,axmovax,0020hmoves,axmovbx,0s:moval,[bx]moves:[bx],alincbx loopsmovax,4c00hint21hcodeendsend下列说法正确的是。1、指令movax,code改为movax,start对程序要实现的功能没有任何影响。2、程序不能通过编译,因为在loop指令之前,没有对寄存器cx进行设定。3、程序实现的功能是将程序的所有指令复制到内存中以0:200h为起始地址的一段内存空间中。4、程序实现的功能是用内存中以0:200h为起始地址的一段内存空间中的数据将程序的所有指令覆盖。****************************************************************************第6章包含多个段的程序(1)在Intel8086环境下,下列说法合理的是。1、汇编语言程序载入内存后处于64K空间以外的数据和指令将无法使用和执行。2、一个数据段命名为data,此标号代表这个数据段在内存中的起始地址。3、如果载入的程序没有返回语句,那么当程序代码执行完毕,将继续读取后续内存空间存储的指令到CPU内部作为指令执行下去,直到遇到返回指令为止。4、用DW和DD定义进行的数据,只能够以字为单位访问。(2)在某程序中,定义了262B的数据段data,那么程序载入内存,该段实际占用的内存空间是B。1、2562、2623、2724、512(3)assumecs:codecodesegmentstart:movax,3jmps1s:movbx,0movax,bxs1:movcx,3s2:addax,2loops2s3:movax,4c00hint21hcodeendsends上面代码执行s3处的指令之前,ax的值是。1、92、63、54、2 (4)如下程序:assumecs:codesgcodesgsegmentdw0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987hstart:movax,0movds,axmovbx,0movcx,8s:________addbx,2loopsmovax,4c00hint21hcodesgendsendstart要实现一次用内存0:0--0:15单元中的数据改写程序中定义的数据,添加到空白处的指令序列不能是。1、movcs:[bx],ds:[bx]2、movdx,[bx]movcs:[bx],dx3、push[bx]popcs:[bx]4、movax,[bx]movcs:[bx],ax(5)某程序有数据段、栈段和代码段三部分,如果加载后代码段的段地址为X,那么下列说法正确的是。1、可以断定数据段的段地址是X-2。2、可以断定栈段的段地址是X-1。3、可以断定程序PSP区的段地址是X-10。4、确定数据段和栈段的段地址与X的关系,要视其大小和在其在源程序中定义的位置关系。****************************************************************************第7章更灵活的定位内存地址的方法(1)生成EXE之后用Debug加载后,查看寄存器内容如下:ds=0b2des=0b2dss=0b3dcs=0b3eip=0000程序的起始地址的段地址是。1、0b3e2、0b2d3、0b3d4、0(2)下列指令不能执行的是。1、movax,10h[bx]2、movax,10h[di] 3、movax,[di+si]4、movax,10h[bx][si](3)对如下程序要实现将datasg段中的字符串"welcometomasm!"复制到它后续的数据区中,assumecs:codesg,ds:datasgdatasgsegmentdb"welcometomasm!"db"................"datasgendscodesgsegmentstart:movax,datasgmovds,axmovsi,0________________movax,4c00hint21hcodesgendsendstart在空白区域添加的指令序列合理的是。1、movdi,10hmovcx,10hs:movax,[si]mov[di],axaddsi,2adddi,2loops2、movdi,10hmovcx,8s:movax,[si]mov[di],axincsiincdiloops3、movss,axmovsp,32movcx,8s:movax,[si]pushaxaddsi,2loops4、movcx,8s:movax,[si]mov[si+10h],ax addsi,2loops****************************************************************************第8章数据处理的两个基本问题(1)下列指令序列不能够实现把内存地址0:202h中的字节数据送入al功能的是。1、movax,0movds,axmovbx,202hmoval,[bx]2、movax,0movds,axmovbx,200hmoval,[bx+2]3、movax,0movds,axmovbp,202hmoval,[bp]4、movax,0movds,axmovbp,200hmoval,ds:[bp+2](2)下列指令不合理的是。1、movds:[0ffh],al2、movds:[0ffh],ax3、movds:[0ffh],0ffh4、pushds:[0ffh](3)movdx,0movax,1001movbx,100divbl以上四条指令执行完后,ah值是。1、12、103、10014、0(4)对如下程序:assumecs:codesg,ds:datasgdatasgsegmentdd123456hdw789h,0h datasgendscodesgsegmentstart:movax,datasgmovds,axmovax,ds:[0]movdx,ds:[2]divwordptrds:[4]movds:[6],axmovax,4c00hint21hcodesgendsendstart下列说法正确的是。1、该程序实现的功能是计算123456h与78900h相除。2、该程序由于数据定义非法,无法通过编译。3、指令divwordptrds:[4]可改为divnearptrds:[4],不影响程序功能。4、指令divwordptrds:[4]采用了直接寻址方式。****************************************************************************第9章转移指令的原理(1)对于如下程序:movax,2movcx,3s:addax,2s1:loopsmovdi,offsets1movsi,offsets3movax,cs:[di]movcs:[si],axmovax,1movcx,3s2:addax,2s3:nopnop所有指令执行完后ax的值为_____。1、152、73、114、3(2)对于如下程序:assumecs:codedatasegment? dataendscodesegmentstart:movax,datamovds,axmovbx,0jmpdwordptr[bx+2]codeendsendstart若在指令jmpdwordptr[bx+2]执行后,要使程序再次从第一条指令开始执行,下列对data段中的数据的定义更合理的是______。1、dd0,0,02、dw0,0,03、dw0,0,segcode4、dw0,0,offsetcode(3)对于指令jmpdwordptr[bx+0dh]的说法错误的是______。1、该指令能够实现段间转移。2、该指令转移的目的地址是在指令明确给出的。3、该指令转移的目的地址被存放在内存空间中。4、该指令中运用的寻址方式是寄存器相对寻址。(4)有如下程序段,填写2条指令,使程序在运行中将s处的一条指令复制到s0处。assumesegmentcodesegments:movax,bxmovsi,offsetsmovdi,offsets0______________________________s0:nopnopcodeendsends1、movax,cs:[si]movcs:[di],ax2、movax,cs:[di]movcs:[si],ax3、movax,[si]mov[di],ax4、movax,ds:[di]movds:[si],ax(5)下列能够改变CS:IP所指位置并能通过编译的指令是______。1、jmpshort[bx] 2、jne[bx]3、loopbyteptr[bx]4、jmp[bx](6)movdx,0movax,1001movbx,100divbl以上四条指令执行完后,ah值是_____。1、12、103、10014、0****************************************************************************第10章CALL和RET指令(1)某程序中定义了如下数据:datasegmentdb"Hello"db"world"db"!"db"W","elcome"db"to","masm!"db"Bye","b","ye!"dw0,1,2,3,4,5,6,7,8,9,0ah,0bh,0ch,0dh,0eh,0fhdd16dup(0)dataends下列说法正确的是。1、该程序加载后其中的字符数据和数字数据在内存中都是以ASCII码的形式存放的。2、该程序加载后这组数据在内存中所占用实际空间是90HB。3、该数据段定义可放在该程序中end伪指令之前的任何位置。4、在编译阶段,该程序因如此定义数据而报错。(2)补全程序,实现从内存1000:0处开始执行指令。assumecs:codestacksegmentdb16dup(0)stackendscodesegmentstart:movax,stackmovss,axmovsp,16movax,____pushax movax,____pushaxretfcodeendsendstart1、cs,ip2、0,1000h3、1000h,04、0,1000(3)对下列程序说法正确的是。assumecs:codesgstacksegmentdw10dup(0)stackendscodesgsegmentmovax,4c00hint21hstart:movax,stackmovss,axmovsp,20movax,0pushcspushaxmovbx,0retfcodesgendsendstart1、程序中start之后的汇编指令不能得到执行。2、程序加载后stack段在内存中实际占用的内存空间是20b。3、程序的每一条指令都能获得执行,但不能正常返回。4、指令retf可替换为ret,并能够正常返回。(4)下面的程序执行完addax,5时,ax中的数值为多少。assumecs:codestacksegmentdw8dup(0)stackendscodesegmentstart:movax,stackmovss,axmovsp,16movds,axmovax,0 callwordptrds:[0EH]addax,2incaxaddax,5movax,4c00Hint21Hcodeendsendstart1、32、83、04、4c00H(5)下面指令执行后,ax中的数值为多少。内存地址机器码汇编指令1000:0b80000movax,01000:39a09000010callfarptrs1000:840incax1000:958s:popaxaddax,axpopbxaddax,bx1、1006h2、1010h3、0020h4、000ch****************************************************************************第11章标志寄存器(1)下列指令对标志寄存器内容产生影响,但不会改变参与其执行过程的其它寄存器内容的是。1、loops2、cmpcx,03、jcxzs4、divcx(2)对于Intel8086cpu标志寄存器的说法正确的是。1、cpu执行每一条指令都有可能改变标志寄存器的内容。2、无符号数运算的进位或借位情况由cf标志位记录,有符号数运算的溢出情况由of标志位记录。3、当前指令对标志寄存器的影响为此指令的执行提供了所需的依据,对后续指令没有任何指导作用。4、所有的条件转移指令都要参考标志寄存器中的相关标志位。(3)subax,axmovax,5 addax,-3以上程序执行完后,CF,OF的值是_____。1、0,02、0,13、1,04、1,1(4)movax,8movbx,3cmpax,bx上面指令执行前ZF,PF的值是0,0,执行后ZF,PF的值是_____。1、0,12、0,03、1,04、1,1(5)movax,0pushaxpopfmovax,0fff0haddax,0010hpushfpopaxandal,11000101Bandah,00001000B上面指令执行后ax的值是。1、845H2、8C5H3、45H4、C5H****************************************************************************第12章内中断****************************************************************************第13章INT指令(1)用7ch中断例程模拟loop指令的功能,指令序列如下:lp:pushbpmovbp,spdeccxjcxzlpretadd[bp+2],bxlpret:popbp iret关于7ch中断下列说法正确的是。1、此中断的最大转移位移为1282、此中断的最大转移位移为1K3、此中断根据bx中的偏移量实现跳转4、此中断不能设定跳转的次数****************************************************************************第14章端口(1)下列各代码序列,要从端口号为6FFh的端口读取一个字节的数据,正确的是。1、movbx,6FFHoutal,bx2、inal,6FFH3、movdx,6FFHinal,dx4、movdx,6FFHoutal,dx(2)以下关于移位错误的是。1、shl的功能是将寄存器或内存单元的数据向左移位。2、shl移位时将最后移出的一位放入OF中。3、shr把最高位用0补充。4、把al中的数据向左移3位的代码是movcl,3shlal,cl(3)下列说法正确的是。1、我们可以编程改变FFFF:0处的指令,使CPU不去执行BIOS中的硬件系统检测和初始化程序。2、int19h中断例程可以由DOS提供。3、中断例程都是由BIOS提供的。4、CPU可以直接读取端口中的数据。(4)下列指令序列能读取CMOS中的2号单元内容的是。1、movax,0c000hmovds,axmovbx,2moval,[bx]2、out70h,2inal,71h3、moval,2out70h,alinal,71h4、movax,70hout2,ax movax,71hinax,71h****************************************************************************第15章外中断(1)下面的说法正确的是。1、外设的输入随时都能获得CPU的处理。2、计算机外设的输入不直接送入CPU,而是直接送入内存。3、标志寄存器IF位决定着中断信息能否被CPU处理。4、以上说法都有错误。(2)以下说法错误的是。1、CPU通过总线和端口来与外部设备进行联系。2、不可屏蔽中断过程的第一步是取中断类型码。3、外部可屏蔽中断的中断类型码是通过数据总线送入CPU的。4、中断过程中将IF置为0是为了在中断过程中禁止其他的可屏蔽中断。(3)下列关于9号中断的说法正确的是。1、9号中断是不可屏蔽中断。2、9号中断的作用是读出按键的扫描码,如果是字符转换成字符码,并将其显示在屏幕上。3、9号中断例程是DOS提供的。4、9号中断例程中肯定包含读端口数据指令inal,60h。(4)下列指令中不会影响标志寄存器内容的是。1、cld2、oral,0fh3、nop4、shlal,1****************************************************************************第16章直接定址表(1)将标号a处的8个数累加的和放到标号b处所在的单元中,下面选项中的程序正确的是。1、assumecs:codecodesegmentmovsi,0movcx,8s:addb,a[si]incsiloopsmovax,4c00hint21hadb1,2,3,4,5,6,7,8bdb0codeends end2、assumecs:code,ds:datadatasegmentadb1,2,3,4,5,6,7,8bdb0dataendscodesegmentstart:movsi,0movcx,8s:moval,a[si]addb,alincsiloopsmovax,4c00hint21hcodeendsendstart3、assumecs:codedatasegmentadb1,2,3,4,5,6,7,8bdb0dataendscodesegmentmovax,datamovds,axmovsi,0movcx,8start:moval,a[si]addb,alincsiloopstartmovax,4c00hint21hcodesegmentend4、assumecs:code,ds:datacodesegmentp:movsi,0movcx,8movax,datamovds,axs:moval,a[si] movah,0addb,axincsiloopsmovax,4c00hint21hcodeendsdatasegmentadb1,2,3,4,5,6,7,8bdw0dataendsendp(2)下列说法中正确的是。1、当数据的标号不在代码段时,只要用assume伪指令将数据段和相应的段寄存器连接起来就可以了。2、数据标号和地址标号唯一的区别就是,数据标号既表示内存单元的地址,还表示内存单元的长度,而地址标号只表示内存单元的地址。3、直接定址表只可以存储数据的地址,不可以存储程序段的地址。4、在中断服务程序用到直接定址表时,和不在中断服务程序的使用一样,直接调用即可。(3)关于直接定址表描述错误的是。1、直接定址表和数据标号一样只是用来标记地址的。2、直接定址表可以方便的编写一些查表类的程序。3、直接定址表中包含了数据长度信息。4、直接定址表的数据可以定义在代码段。****************************************************************************第17章使用BIOS进行键盘输入和磁盘读写(1)把键盘的扫描码读入并将其转化成ASCⅡ码或状态信息,存储在内存的指定位置的中断例程是。1、int16h2、int21h3、int9h4、int10h(2)提供读取键盘缓冲区功能的BIOS中断例程是_。1、int9h2、int21h3、int10h4、int16h(3)当有键按下时,将按键的依次存储在键盘缓冲区中。1、通码和断码2、通码和扫描码3、通码和ASCII码 4、断码和ASCII码****************************************************************************第18章综合研究(1)就C语言而言,对于函数intmain(){return1;}和intfunc(){return1;}以下说法错误的是。1、两个函数对应的可执行程序的返回值传送都通过寄存器AX2、字符串“main”和“func”在编译过程中都被处理为一个偏移地址3、函数func()对应的C程序无法通过编译和连接4、从本质上说,两个函数的具有的功能是一样的,没有任何区别(2)下列关于C语言变量与内存空间的说法错误的是。1、全局变量存储在程序向系统申请的数据段所在的内存空间中2、局部变量存储在程序向系统申请的栈段所在的内存空间中3、变量是C语言程序访问内存空间的唯一方式4、指针变量包涵所指向数据所要占用的内存空间的地址信息及其长度信息(3)下列无法完成向内存空间写入数据的指令语句是。1、*(char*)0x2000="a";2、*(int*)(_BX*2)="b";3、int*c=*(_DL*160+_DH*2+1);4、*(charfar*)(0xb8000000+_DL*160+_DH*2)=("d"+1);(4)下列关于C语言不定形参的说错误的是。1、不定形参函数的形式参数的类型可以不一样2、不定形参函数的定义格式为:返回值类型函数名(...);3、不定形参函数的定义格式为:返回值类型函数名(参数类型,...);4、不定形参函数中可以通过第一个实参的地址来确定参数的个数及每个参数的类型摘录的汇编网在线测试题目答案(部分)(1)(2)(3)(4)(5)(6)第1章基础知识42232第2章寄存器(CPU工作原理)223143第3章寄存器(内存访问)44331第4章第一个程序22第5章[bx]和loop指令41443第6章包含多个段的程序33214 第7章更灵活的定位内存地址的方法334第8章数据处理的两个基本问题3314第9章转移指令的原理第10章CALL和RET指令33422第11章标志寄存器223第12章内中断第13章INT指令3第14章端口3243第15章外中断4243第16章直接定址表421第17章使用BIOS进行键盘输入和磁盘读写343第18章综合研究3332'