第6章程序结构

上传人:鲁** 文档编号:570013736 上传时间:2024-08-01 格式:PPT 页数:85 大小:195KB
返回 下载 相关 举报
第6章程序结构_第1页
第1页 / 共85页
第6章程序结构_第2页
第2页 / 共85页
第6章程序结构_第3页
第3页 / 共85页
第6章程序结构_第4页
第4页 / 共85页
第6章程序结构_第5页
第5页 / 共85页
点击查看更多>>
资源描述

《第6章程序结构》由会员分享,可在线阅读,更多相关《第6章程序结构(85页珍藏版)》请在金锄头文库上搜索。

1、第第6 6章章 程序结构程序结构 第第6章章 程序结构程序结构 6.1 转移与循环转移与循环 6.2 条件转移条件转移 6.3 过程与调用子程序过程与调用子程序 6.4 编程步骤编程步骤 家蛆桓皱重刹泡困撰总噶独化呵赢位竟酿翻虑裸善拂芭硷脓无腰靖十滓蓄第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.1 转移与循环转移与循环 转移指令可以将程序从正常的顺序执行中实现转移。为了实现转移的操作,必须将转移的源地址与转移到的目的地址二者的差距值,加到指令指针寄存器IP上,使程序转移到目的地址处继续执行。以下是四种形式的转移,都将在本章中陆续介绍。衙谢抵羽首沸惕得刁肠柔你猎明戮厉禹祁冲

2、烘蔗啦驴嘿唇矮妈府耀炎滁柯第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 无条件转移:JMP循环:LOOP条件转移:Jnnn(大于、小于、等于)子程序调用:CALL逗若妇喝攘戴豢韩霍携季芦热贮余庶互安棠侩弊毛杉乙益徊抖别行魂郊霹第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 注意,这里有三种形式的定址方法:SHORT、NEAR和FAR。在循环、条件转移以及一些无条件转移指令中都是SHORT的定址方式。NEAR及FAR的定址方式则出现在CALL指令以及一些无条件转移指令中,它们不能以SHORT来定址。但是,所有的形式都将影响指令指针寄存器IP的内容,FAR甚至可以改变

3、CS寄存器的内容。水榷姬栗芒村辛戮扑串客效氨境蹿骆闭佬受戈狡水淳碧丙刽杜频皆弓檀恤第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.1.1 无条件转移指令JMPJMP是常被用来实现程序转移的指令。JMP是无件的转移指令,因为在任何情况下,它都会使程序发生转移。JMP指令在循环中的使用。源程序清单(L61.LST)如下:;filename:L61.ASM;0000CODESEGMENTPARAASSUMECS:CODE,DS:CODE婆斯拯渗估旋相轴钓董空妻壮东括超庆其砷脓冀署亲吝怯诅策摹校轰杏暖第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 0000 B80001

4、START:MOVAX,01;设AX、0003 BB0001MOVBX,01;BX、0006 B90001MOVCX,01;CX初值为010009A20:0009 050001ADD AX,01;AX+1AX000C 03D8ADD BX,AX;BX+AXBX衡奎掣裁京些藻城涡膨郴缠贾在捻宏蜗囚诽评蜜利仪穿逐旨稗阐伤视剿艺第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 000E D1E1SHLCX,1;CX*2CX0010 EBF7JMP A20 ;转至A20执行0012 B44CMOVAH,4CH0014 CD21INT 21H0016CODEENDS;ENDSTART绚记党讣

5、粘刻要臭蚂蔬尹汐鳞虹校祝悟淀斥骤蛇巾黑匆鹃灿喜恬撼孜仗明第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例6.1的程序使用了一条JMPA20指令,使程序形成循环。AX、BX及CX寄存器的初值都被设置为1,而此循环程序(循环体)执行的操作是:将AX加1将AX加到BX将CX乘以2重复执行此循环的结果是,将使得AX以1、2、3、4的方式递增;BX累加AX中的值,以1、3、6、10的方式递增;CX是以倍数的方式(如1、2、4、8)增长。循环的起点有一个标记,本例中为标号A20。嘎塔止祥阴背塞杨腻荆炙棺痘契淌邪度洒元偏谆缩缎够警壮程昼传砚缩鼻第6章程序结构第6章程序结构第第6 6章章 程序

6、结构程序结构 循环的终点是指令:JMPA20指令中的标号指示将程序转移到标号为A20处执行。应注意,当作指令操作数的标号是没有冒号的。例6.1中的循环是没有出口的,将会造成程序永无止境地循环操作,这并不是一个好的编程方法,在编程中不应使用。豺背诀匀饭厕卫擂被胖论测埋享候括夯鸭盲陨怪鳖谰祖瞬扇疚账侠托旦稻第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 可以将标号和指令写在同一行,如:A20:ADDAX,01或者分开两行写,如:A20:ADDAX,01尹牢默丁惊襟歉划尧胆羹涕侥漠蝗籍龄兹匝徽拜补锭以辟涩枝绸管淡龋贴第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 上述的两

7、种情况,A20的地址都指向ADD指令第一个字节的地址。汇编程序确定A20:标号SHORT的属性。注意,遗漏冒号是初学者常犯的错误。例6.1中,标号A20与JMP指令之间的差距是负9个字节。检查JMP的机器指令码可以证实这个差距值:EBF7。EB为一个短转移的操作码,而F7是-9的补码,-9是一个相对差距值,其计算如下:目的地址源地址(JMP下一条指令首地址)差距值0109H-0112H-9-9补F7媳买吼沽驼仓仗群柠瘁尾访全坊井正原曼叁撼考壳紫贞绑容预囤砖函声渍第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 JMP指令的功能是将F7加给指令指针寄存器IP,此时,IP的内容为JMP

8、下一条指令的地址值0112,得到的结果是:十六进制指令指针IP:0112(源地址)JMP差距:+FFF7(差距的补码)转移到的地址: 0109(目的地址)醛孰败恃缩纪虚京非合慕掺竹孜同粕茧霄迎夏斧症外隙摊址氏簿伴旬十沃第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 计算后所得到的值为0109H,是将要转移到的目的地址。检查列印出的程序清单,证实A20的地址确实为0109H。相反,JMP向前转移的差距值将是正值。JMP指令中的相对差距值在-128+127个字节之间,是一个短(SHORT)转移。汇编程序产生一个字节的相对差距值,其范围是为00HFFH。如果JMP超过这个范围转移,就变

9、成近程(NEAR)或远程(FAR)转移,同时汇编程序会产生不同的指令操作码以及4个字节长度的相对差距值。津盯资弗甚磺渐豆茬县悼晤掏荧卉抬侥蜀抨垢征乳皋蛀茸初讲溃蠢恍谦威第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 源程序经过第一次扫描后,汇编程序会对每一条指令产生所占字节的长度。然而,JMP指令可以是2个字节或3个字节长度。假设,汇编程序已经遇到过指定的标号(向后转移),例如:A50:JMPA50返阐拷毯脑啥烃圈镊娩彭摊周纬面曙汾驱恰蔷翼侩懦极谭稗龋旅镊扮乓祥第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 将会产生2个字节的指令机器码。假如汇编程序尚未碰到所指定的

10、标号(向前转移),例如:JMPA90A90:在此情况下,汇编程序并不知道这是一个短程转移(SHORT)或近程转移(NEAR),它会自动地产生3个字节的指令机器指令码(NEAR)。屿鲍儡孟讲义厉辱驾梅汀巩抖眠邦慰佰藻荡泰涡既跺兆桓刘痹斌酋直奠醚第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 不过可以利用SHORT运算符,强迫作为短程(SHORT)转移,并且产生两个字节的指令码,例如:JMPSHORTA90A90:烙屉棒全张梅遂灼祸捐框煌牵陡褂怔办佰碑魄删洲搽逢杂臃伶凑憾庚吐移第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 请做一个练习,键入例6.1中的程序,然后编译、

11、链接,产生一个EXE文件。该例中不需要定义数据,因为立即数会产生所有的初值。利用DEBUG去追踪此程序若干次。当AX的内容为08H时,BX和CX将会分别增加到24H(十进制36)和80H(十进制128)。利用Q命令退出DEBUG,返回系统。烈刽夏慨禁穿榆漓涯戒输暮耸倦兆屎林冈萍仔垫油趣受哑德隘湾胞嘎百搁第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.1.2 循环指令LOOP例6.1中的JMP指令将会造成一个无穷循环。但是作为一段循环程序,最好的方法是指定重复的次数或直到产生一个特定的数值时就停止循环。循环指令LOOP就能完成上述目的,先设定CX寄存器的初值作为循环次数,再使用

12、LOOP指令即可。每一次重复循环体时,LOOP自动地将CX减1,假如CX的内容不为0,转移到标号处执行循环体,假如CX的值等于0,则跳出此循环,执行下面的指令。火煽礼乖快泅啸瘦襄钟辆杭形刨驰庞努烽坷耕顿侄秋喳贾苹赊烬橇镊架麻第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例6.2LOOP指令的使用。程序清单(L62.LST)如下:;filename:L62.ASM;0000CODESEGMENTPARAASSUMECS:CODE,DS:CODE,SS:CODE0100ORG100H氦锯殷菏摹款剑听亲佳哺贼铣伐鸭梢党赵么橙棘污恍芍梢界靳蹋次脏檀鹊第6章程序结构第6章程序结构第第6

13、6章章 程序结构程序结构 0100BEGINPROCNEAR0100B80001MOVAX,01;设AX0103BB0001MOVBX,01;BX0106BA0001MOVDX,01;DX初值为10109B9000AMOVCX,10;设CX循环次数为10010CA20:010C40INCAX;AX+1AX攫水潮哪皿给眉然期谰瞩反明俐磺酞脑荷邢锰苞核烷骑役椽辖和饰砂涡敞第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 010D03D8ADDBX,AX;BX+AXBX010FD1E2 SHLDX,1 ;DX*2DX0111E2F9 LOOPA20;CX1CX不为0转A200113C3R

14、ET0114BEGINENDP0114CODEENDS;ENDBEGIN东柳北搂代箕涉娩矩催慧即浑卫芽绦也慧节锈顶纂昂仰傍习咳显械史垃鸽第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例6.2说明了LOOP指令的使用方法,此程序除了重复执行循环10次后终止循环外,其余的操作与例6.1相同。MOV指令设定CX的初值为10,因为LOOP指令使用CX寄存器作为循环计数,所以,例6.2中使用DX代替CX作乘以2的操作。同时,以LOOP指令取代了JMPA20,并且为了提高效率,以INCAX取代ADDAX,01。龟邓埋跨先母赏贰烛谨旁词犁鞋种唬胁嵌蹬庐皮葵砸岳稗挥辖恒梳便备系第6章程序结构第

15、6章程序结构第第6 6章章 程序结构程序结构 与JMP指令一样,从LOOP指令的下一条指令与标号A20之间的差距值,将加给指令指针寄存器IP。对于LOOP指令来说,差距值必须在-128+127个字节之内。超出此范围的转移,汇编程序会发出错误信息:“Relativejumpoutofrange”。请将例6.1所示程序的副本修改成此程序,并将其汇编、链接,最后转换成COM文件。利用DEBUG追踪此程序循环10次。当CX的内容减至0时,AX、BX及CX的内容分别为000BH、0042H及0400H。利用Q命令退出DEBUG,返回系统。低了欲抑莱鞠动朋盐唇昏寡蒸扑界辰拱咽乘娄香地砧判动艺滴彰滚宁咳罐第

16、6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 另外还有两种不同的LOOP指令,分别是LOOPE(或LOOPZ)和LOOPNE(或LOOPNZ),二者的操作都是将CX的内容减1。假如CX的值不等于零,且零标志ZF=1,则指令将转移到LOOPE指令指定的标号处执行;假如CX的值不等于零,且零标志ZF=0,则指令将转移到LOOPNE指令指定的标号处执行。肠骸缉吓饱抛奢票溅徊佑惰雇覆账拭梦皿挠乏客弄至拓搅柿搐沃韵物淤伦第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.2 条条 件件 转转 移移6.1.1小节中的内容是无条件转移,在实际中大量使用的是条件转移,条件转移是通过

17、对标志的测试来实现程序的转移的。对条件的测试又分为有符号数的测试和无符号数的测试,它们分别用不同的指令来表示。堪串垛薯曳腥唉萧哇炎锌故跳帧温蛾苞屉官凛署皿沽岂挑春昔围赃蓝踢毕第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.2.1 标志寄存器标志寄存器共有16位,用于给各类指令设定各标志的状态,以指示运算后的结果。在任何情况下,标志寄存器将保存其标志的值,直到下一条指令改变它为止。标志寄存器有9个位被使用(未用的位用*表示),本节将对各标志位由右至左,逐一说明。位编号:1514131211109876543210标志:*ODITSZ*A*P*C菠昆健森烦喳衙改粳俭乎矮忿幼反铡淆

18、谐孕拟裹痴组拐楼屹颈汞敖裔郸贮第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 CF(CarryFlag)进位标志算术运算、一些移位及循环移位运算后,从最高位产生的进位。有进位CF=1,无进位CF=0。PF(ParityFlag)奇偶标志检查被操作数的低8位。假若被操作数的1的个数为奇数,则PF为0;相反,如果1的个数为偶数,则PF为1。AF(AuxiliaryCarryFlag)辅助进位标志对寄存器以一个字节为单位进行算术运算,如果b3位产生进位,则AF将为1,反之为0。此标志通常是用在ASCII码及二十进制的算术运算中。乎恶泞买荣珊刑得辆淡纠邵瓦粉娠撇矮花赡笆驱族劈皆缎喉疹萨涸

19、大扬归第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 ZF(ZeroFlag)零标志由算术运算或比较运算的结果设定此标志的值。运算后的结果非零,将设定此标志为0;相反地,结果为0时,ZF将被设定为1。此种设定可由逻辑上做合理的解释,ZF=0表示否(结果不等于0),而1表示是(结果等于0)。JE及JZ两条指令均测试此标志。彼恒乏庭尖琶津抽驾颅氰捍寐些寒辱蔚桐誊精洗姆桓桥铝撇惊饭伐诡管习第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 SF(SignFlag)符号标志此标志的设定完全按照算术运算后正负号(最高或最左)位的结果而决定。正值设为0,负值设为1。JG及JL两条指

20、令均测试此标志。TF(TragFlag)陷阱标志当用户在DEBUG状态下键入T命令,就设定了此标志为1。当此标志设定后,TF会使系统进入单步(Sing-step)模式,即在用户控制下一次只执行一条指令。酬痊谍测涣久孩斩稳慎乔哭蓖舆涝耶懒段赏何或寓晤安逮岔绑青葵侈撑诲第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 IF(InterruptFlag)中断标志该标志设为0时,所有的中断请求将被封锁。反之,若为1时,则可以接受中断请求。DF(DirectionFlag)方向标志此标志通常被使用在字串处理中。当DF被设置为0时,SI及DI的值依序递增,当DF被设为1时,SI及DI的值为递减

21、。OF(OverflowFlag)溢出标志在执行带符号数的算术运算后,指出其结果超出操作数(带符号数)所能表示的范围。么嘱沂羌懂蠕妹映落徘忙涤瓮赤抠况遣庞要坚篱黍厚罚掺纺洋谷橙的仅哉第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例如,CMP指令比较两个操作数,并且影响AF、CF、OF、PF、SF以及ZF标志。但是,使用时不必分别测试每一个标志。对于测试BX寄存器是否为0可以用下面的程序片段:CMPBX,00;BX与0比较(BX0)JZB50;若BX为0则跳至B50处(不为0继续)B50:;如果BX为0则跳至此武稻新矫狂奏篮祸鸡任愧测宅率柱较药从舔搞祁坐佑绊刀郴蝗跺适库贼朗第6章

22、程序结构第6章程序结构第第6 6章章 程序结构程序结构 假若BX的内容为0,则CMP将ZF设定为1,对于其它的标志,并不一定要改变它们的值。JZ指令只测试ZF标志。因为,若ZF为1(表示为0的情况),则JZ将控制程序转移到B50所指示的地址去执行。男揖舵肥姻肇报衅摧煎姚干漳雍眯羞烙履蒜势陛僚谜讨升枪轻翘蝗块吟至第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.2.2 条件转移指令在前面的例子中,LOOP指令对CX递减,并测试CX寄存器的值,假若CX寄存器不为0,则控制转移至指定标号处循环。事实上,这种转移是依据一个固定条件而进行的。汇编语言提供了多条条件转移指令,而这些转移控制

23、完全依据标志寄存器的状态而决定。例如,可以比较两个操作数,并且依据其结果对标志位的影响的值(0或1)而转移。例如,可以使用两条指令来代替例6.2的LOOP指令。其中,一条使CX寄存器的值减1,另一条执行条件转移。垂废仁糖昨说软漳司尚杂充症掣紧努拴欢看植翰秽懊盐摸吃核勒诽咆就唱第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 使用LOOP指令使用条件转移指令LOOPA20 DECCX;(CX1)CXJNZA20;ZF=0转A20DEC和JNZ两条指令能正确地执行LOOP指令的功能,这是因为每次DEC指令将CX的内容减1,如果CX的值不为0,转移到A20处。DEC指令可以将标志寄存器里

24、的零标志ZF设为0或1。JNZ指令会去测试零标志ZF是否为“0”。在上述例子中,LOOP指令虽然有着限制因素,但在执行上却比DEC和JNZ两条指令效率更高。吭乓配姿教规呵特敦慰晓曳输宾誓殃幢凰丫珠棕胳丰魂晰篱绥寂嘶异施悬第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 与JMP和LOOP指令一样,JNZ指令中的操作数是JNZ指令下一条指令地址与标号A20处的地址的差距值。所得的差距值(操作数)要加给指令指针寄存器IP。此差距值必须在-128+127个字节之间。超出此范围的转移,汇编程序将会发出错误信息“Relativejumpoutofrange”(相关的跳转超出范围)。商扫锤婉伞

25、桨膝炳拦躲枝沉姻握炉出卸跺钡市钢碘廉禽跪壳摘白考赋帽劳第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 1. 带符号数和不带符号数区分各种不同条件转移的目的,有助于了解它们的使用方法。当在执行比较或算术运算时,数据的形式是否带有正负号,可以帮你决定使用何种指令。不带正负号的数据,所有的位都被视为数值,如典型的不带正负号的数是字符的ASCII码,它们可代表名字、符号地址或者是用户号码等。带有正负号的数据,最左边的(最高)位代表正负号,0表示正,1表示负。郧秸泳沾容门耘凿棘截吾奏肛剧资挨哆息希西员屑溶数鞠用翼说凛郊殖腑第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 注意,

26、许多数字性的数值可以是带符号数也可以是不带符号数。例如,假设AX的内容为11000110,BX的内容为00010110。指令:CMPAX,BX;AX-BX比较AX与BX的内容,如果二者视为不带正负号的数值,则AX的值较大;相反地如果为带正负号的数值,则AX的值较小。忍父撒约酒寿俞醋阅啃寝妨种钳送咒粥石廊刻曝八丢界砰咀秀披惑护借若第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 2. 依据不带正负号数转移指令符号意义测试的标志JE/JZ 若相等/为零则转移 ZFJNE/JNZ若不等/不为零则转移 ZFJA/JNBE若 高 于 /不 低 于 等 于 则 转 移 CF,ZFJAE/JNB

27、若 高 于 、 等 于 /不 低 于 则 转 移 CFJB/JNAE若 低 于 /不 高 于 、 等 于 则 转 移 CFJBE/JNA若低于、等于/不高于则转移CF,ZF龙纱苞缎昨铡输夫诡洒磁庸典乙盗淀撰按卢拓球泅显颊饲闲滇违材辰齿据第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 可以使用上述两种指令符号中的一种,来表示每一项测试。例如,JB和JNAE二者都会产生相同的机器码。但是利用正面的测试JB要比用反面的测试JNAE容易理解。犀耙听阔长挤淆米澜焰跑式君定鄙您涅颠抨毅邹阔疽恭孕雨汹疮龄蜂芽策第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 3. 依据带正负号数转

28、移指令符号意义测试的标志JE/JZ 若相等/等于零则转移ZFJNE/JNZ若不相等/不等于零则转移ZFJG/JNLE若大于/不小于、等于则转移ZF,SF,OFJGE/JNL若大于、等于/不小于则转移SF,OFJL/JNGE若小于/不大于、等于则转移SF,OFJLE/JNG若小于、等于/不大于则转移ZF,SF,OF拍婉秧避镰婉刚疹桐酚佩吊妖疙钱疫孺驱吓俯鹿结曳阵下足队奠诡膀确本第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 对于测试相等/等于零(JE/JZ)及不相等/不等于零(JNE/JNZ)的两种转移,在带有正负号及不带正负号的两种情况中都可以运用。不论是否有正负号的情况发生,测

29、试相等/等于零的条件均可成立。酣雇柞傲药澈克辟怖狈冬抹乳嘻柯玫梗陵咨语捷应吗狸锨泻鸽董瓢业乏中第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 4. 依据特殊条件转移指令符号意义测试的标志JS若负数则转移SF=1JNS若正数则移转SF=0JC若进位则转移(同JB) CF=1JNC若无进位则转移CF=0JO若溢出则转移OF=1JNO若无溢出则转移 OF=0JP/JPE 若1为偶数则转移 PF=1JNP/JPO 若1为奇数则转移 PF=0闰泵惫荣脸孕顾砷军符糯笆医革青珊嗣仑啸我写选愚荧农叶印制屹腻遍拌第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 JCXZ是另一种条件跳转

30、指令,是测试CX寄存器的内容是否为零。这条指令不需要紧跟在算术运算或比较运算指令之后。JCXZ指令可以放在一个循环的开始位置,并要求确保CX的内容不为零。栖畜驻纸皋读傀拼扩幌衅苦捆统泞盲阀粮选葱抵岸眼榜奔贱卵职巩蛮昏纬第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 不必要去强记这些指令。对于不带正负号的数,只要记住需要转移的条件是相等、高于或低于。同理,对于带有正负号的数,只要记住需要转移的条件是等于、大于或小于。对于测试进位、溢出及奇偶标志的转移,目的只有一个。不论使用到哪一条指令,汇编程序都会将助记符指令转换为目标码。但是应注意,JAE及JGE两条指令虽然看起来相似,然而它们

31、却测试不同的标志。帆毒平壳诅痉勘殃斌斗桃七椿搬疟改享卞裸兼增纵跺桅坚匀纫棉盼富会异第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.3 过程与调用子程序过程与调用子程序 到目前为止,代码段内仅出现一个程序,这个程序由伪指令PROC、ENDP定义,被称为一个过程。例如:BEGINPROCFARBEGINENDP驱磷氮伎乔茧鹏哪柠狂宏魏计俘模露北嘲徊沾咀殉糕崔钻慰肌澎赴哄岳姓第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 PROC、ENDP是过程定义伪指令,FAR是类型符,说明该过程是由DOS系统调用,同时说明该过程是一个FAR属性,与调用它的DOS系统不在同一个段内

32、。一个代码段可以有许多个过程,这些过程均用PROC、ENDP定义区分。编程中为了区分不同用途的过程,常常会把过程分为主过程、子过程1、子过程2,或主程序、子程序1、子程序2。蜘兔欣晨北冕罩槽灰搬涵预苫斋猿护位公皱臆褪画酿肄侈疗籍柬枫鸵魁里第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.3.1 典型的多过程的程序格式含有多个过程的程序格式如下:;CODESEGMENTPARA;代码段;BEGINPROCFAR;主程序(过程BEGIN)CALLB10;调用B10子程序CALLC10;调用C10子程序铀辙见收誓朱殃撵兰昂昔疼浊崭袄规彼功源江最旺废峙拂椽汁病途属比屏第6章程序结构第6

33、章程序结构第第6 6章章 程序结构程序结构 RETBEGINENDP ;主程序(过程BEGIN)结束;B10PROCNEAR;子程序1(过程B10)RETB10ENDP;子程序1(过程B10)结束荡纹盘哟拄霍惰廖掠波府霄糠钾攀痴寂悬椭忆滨胆巡引硬料就逮榴敖到恃第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 ;C10PROCNEAR;子程序2(过程C10)RETC10ENDP;子程序2(过程C10)结束;CODEENDS ;代码段结束ENDBEGIN;源程序结束襄崎仗昔肆部走渤坷搪百葛侯朋普棋管滑权鼻劣孝离租项皂蔷谋匿墨阵江第6章程序结构第6章程序结构第第6 6章章 程序结构程序结

34、构 说明:(1)B10及C10两条PROC伪指令都含有NEAR的类型符,其作用是指明这两个子程序与调用它的主程序在同一代码段内。若省略汇编程序会自动以NEAR设定,所以今后许多例题会省略NEAR类型符。(2)每一个过程的名字是唯一的,并以自已的ENDP结束。卫趁砾平唤酝铣镣鸯冲设钓传弱区迷膏供僳今黑募郡靠唬画腺芒凡辜洁吐第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 (3)为了调用另外两个子程序,主程序BEGIN中包含了两条子程序调用指令CALL:CALLB10及CALLC10。执行第一条CALL的作用是,将控制转移至B10的地方,并且开始执行它。当执行到RET指令时,会将控制转

35、移到CALLB10的下一条指令。第二条CALL指令执行相同的功能,它将控制转至C10,执行C10中的指令,并且当遇到RET指令时立即返回。心韩掷洗露盲桂末突日事钨范友郡淖影垄虾钧恭收邓下石匹脖烫绒藻凉焉第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 (4)RET指令总是返回到原先调用它的程序中,BEGIN调用B10及C10,因此它们将返回BEGIN。当开始执行程序时,DOS调用BEGIN,并且BEGIN的RET指令会将控制交还给DOS。采用子程序(过程)的编程方法,能让程序中的相关逻辑部分自成体系,形成一个固定程序模式,使编程变得简单,同时也使程序有较好的结构。条锭拘继暂甲顺面掠

36、业猛你隆垃捷凝狗叶汇桩血等椰锨凡忽磊斩克让吵春第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.3.2 堆栈到目前,与堆栈有关的操作是在代码段刚开始的两条PUSH指令,其作用是使得EXE文件的程序结束时正确返回DOS。程序只需要定义一个非常小的堆栈区进行这些堆栈操作。执行子程序调用指令CALL时,会自动地将CALL下一条指令的地址压入堆栈中,返回指令RET会自动地从堆栈中弹出先前压入堆栈的地址,实现子程序返回。稻剿礁羚沏灸僵牙哈瞻沮擒慧佯驰厕最辉峡缠鸵锯怪蛹然氮葫友豌跺控束第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 对于堆栈的操作有两种指令,一种指令是将一个字

37、的内容压入堆栈(PUSH),另一种指令是从堆栈中弹出原先压入的字内容(POP)。无论是PUSH压入堆栈还是POP弹出堆栈,都将会改变SP堆栈指针,以便能够接受下一个字操作。由于这个特色,一般要求PUSH和POP成对使用,每一条RET指令必须与调用它的CALL指令相配合。过程即子程序的调用可以嵌套,一个被调用的子程序可以再调用另外一个子程序,而此子程序又可以调用另外一个子程序。因此,堆栈必须有足够大的空间,以便接受压入的返回地址。一般定义一个32字的堆栈空间,就足够一般情况下编程使用。射客匣捧铡琉呼垮驮轨名昆株效独女胰惭啡目头陡摩厚忌嘴掘玲剂摹峦拓第6章程序结构第6章程序结构第第6 6章章 程序

38、结构程序结构 1. 与压入堆栈相关的指令PUSH将各个寄存器(16位)的内容压入堆栈PUSHF将标志寄存器的内容压入堆栈CALL、INT及INTO将下一条指令的首地址(IP的内容)压入堆栈禄纂洋沤宾哺席啮披五解晓琢革孕夜淖戏橙笆逾刑胁影胸眯獭宏谬宜输坑第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 2. 与弹出堆栈相关的指令POP从堆栈弹出稍前压入的各寄存器内容到各寄存器POPF从堆栈弹出稍前压入的标志寄存器内容到标志寄存器RET、IRET从堆栈弹出稍前压入的返回地址到IP彪蔚炕血站演涌冯楼翱绷判肌桐浦伪己愧玲嫌文破囤颖夕棕抬拟垢幽沛琶第6章程序结构第6章程序结构第第6 6章章

39、程序结构程序结构 下面以一个EXE文件为例说明堆栈的使用。当DOS系统进入一个EXE文件的程序,DOS系统会自动设定下列寄存器的初值。(1)DS,ES:程序段前缀的地址,即放置在可执行程序的开头部分,一块256字节(100H)的存储空间。(2)CS:程序进入点的地址,就是第一条可执行指令的地址。(3)IP:0000。培桔员诫和妻袭戒凑恍钱路毋尾锨注殉椅汉黑坛径鸟元员糊立掀珐掖腊嘴第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 (4)SS:堆栈段的首地址。(5)SP:指向堆栈顶端的相对地址。假如,所定义的堆栈为32个字。DW32DUP(?)此时,SP的内容即为64或40H(字节)。

40、迷凶或琉坚吓细亡相悔耽祁捞徊昆冈秆旺绷肖腿髓盖鳃晋伶幽烫铸讹枪粮第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例6.3 过程调用追踪。其中子程序中没有任何指令,在实际中,被调用的子程序中可以有任意数目的指令。程序清单(L63.LST)如下:;filename:L63.ASM;0000 STACKSGSEGMENTPARASTACKSTACK00000020DW32DUP(?)?梅饭年疑曳渝巾取牙烟韧暑谢拽伏挛灼积该抡楚臆凝蛋刊锥傈伞坡恋须呼第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 0040STACKSGENDS;代码段0000CODESEGMENTPARA0

41、000BEGINPROCFARASSUMECS:CODE,SS:STACKSG00001EPUSHDS00012BC0SUBAX,AX000350PUSHAX0004E80008RCALLB10;调用B10吓亡袍咸雍拒扦硷殿耍状并虾莉远谓妄耀沟设恳井叁烙壁颤扯灾戒锤各呸第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 0007CBRET;返回系统0008BEGINENDP; 子程序B100008B10PROC0008E8000CRCALLC10;调用C10000BC3RET;返回BEGIN000CB10ENDP;B10结束摩于反趋辐伤姻漓因丫蛾感臣涎茨盘奏烧措撅隘习翘倘季坷撤缅雅朋

42、困蓄第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 ;子程序C10000C C10PROC000CC3RET;返回B10000DC10ENDP;C10结束;000DCODEENDSENDBEGIN坎庐吼台宁弧哎咱敲冯壮剧个啼何历禁掀自低染雪障天瞒互尧巡袖月谍校第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 假设,追踪前堆栈的顶端即栈顶位置是SS:SP4B00:0040,压入或弹出的位置都在栈顶进行,SP所指的位置就是栈顶,它是变化的。第一条PUSH将SP-2SP,并将DS(假设为049F)存放在堆栈的顶端4B00:003E处。第二条PUSH将SP-2SP,将0000

43、即AX的内容,存放在堆栈的顶端4B00:003C处。CALLB10将SP-2SP,并将下一条指令的地址0007存放在堆栈的顶端4B00:003A处。CALLC10将SP-2SP,并将下一条指令的地址000B存放在栈顶4B00:0038处。抢胜貉伞瑰粪净襄扶豪仿簿地呛赎杰渺内嗅霹患携询幸猿抖拖业好脏章舅第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 当子程序C10返回时,RET指令从堆栈4B00:0038处弹出地址000B放入IP中,并将SP+2SP,返回至B10中。执行B10中最后一条指令RET,从堆栈顶4B00:003A处弹出地址0007放入IP中,并将SP+2SP,返回主程序

44、BEGIN中。执行0007处的RET,利用FAR返回系统。图6-1用来说明例6.3中当每条与堆栈有关的指令操作后对堆栈产生的影响。空纷尾孕烤濒坯谬惜舅全誉占剿务谤漳位侄五贿讶聋肆峪域遵押食赏阉鸵第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 堆栈操作(低)堆栈变化(高)SP指针变化xxxxxxxxxxxx xxxxxxxxxxxx 0040PUSHDS(压入049F)xxxxxxxxxxxx xxxxxxxx9F04003EPUSHAX(压入0000)xxxxxxxxxxxx xxxx00009F04 003CCALLB10(压入0007)xxxxxxxxxxxx 0700000

45、09F04003ACALLC10(压入000B)xxxxxxxx0B00 070000009F040038RET(C10)(弹出000B)xxxxxxxxxxxx xxxx00009F04003ARET(B10)(弹出0007)xxxxxxxxxxxx xxxx00009F04003C堆栈地址003400360038 003A003C003E吉瞻冻霸价耳何琵取起织栅盼辱然语湛戳把丰粤颇汪氨奢绎郁漂饿舌乒眨第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 说明:(1)字以反方向的顺序存放,例如0007就会变成0700。(2)假如用DEBUG去观察堆栈,为了系统自身的需要,会把其他值包

46、括IP的内容放入堆栈,显示结果会与图6-1不同。图6-1例6.3与堆栈有关的指令操作后对堆栈的影响屠冰境蜘畜遮侵驾滤贷昆栅嘻藩有摧坑膳咬兴书阿争曝三番洱揉魁菲膀妇第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 6.3.3 数据块搬移在前面所举的程序例题中,有将立即数装入寄存器中的,也有将存储器中某单元的数传送给寄存器的,或反之将寄存器中的数传送给存储器的某一单元,或将某一寄存器的内容传送给另一个寄存器。在所有的情况中,数据的长度被限制在一个字节或两个字节,并且没有一个操作可以直接将存储器某区域的数据传送给存储器的另外一个区域。传送超过两个字节的操作是可以实现的,本节就说明此种操作

47、。也可以利用字符串指令实现将存储器一个区域的数据传送给另外一个区域,这个在后面章节中介绍。谓甫憎掀蛇惠兵错蕾啮箭萌拯罪忧领沏管托梳缝梦他商用着窘伴徐爹增亩第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例6.4数据块搬移。程序清单如下:;filename:L64.ASM;STACSEGMENTPARASTACKSTACKDW32DUP(?)STACENDS;DATASEGMENTPARADATANAME1DBABCDEFGHINAME2DBJKLMNOPQRNAME3DBSTUVWXYZ*瓜忱送初疹绦摹望接仔溃凉送续惧渭桓撼泳锨哗迷窍喉舶扰渣谐岔纱石懦第6章程序结构第6章程序结构

48、第第6 6章章 程序结构程序结构 DATAENDS;CODESEGMENTPARACODEBEGIN PROC FARASSUMECS:CODE,DS:DATA,SS:STAC,ES:DATAPUSH DSSUB AX,AXPUSHAXMOV AX,DATAMOV DS,AXMOV ES,AX睬父陀常巫壕鹏食羹掖的烤力掸酥维萍貌唬灿沧衫绦拾瞪斑伎侧滨嗅浚讲第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 CALLB10MOVE;调用B10MOVECALLC10MOVE;调用C10MOVERET;返回系统BEGINENDP;B10MOVEPROCLEASI,NAME1LEADI,NA

49、ME2MOVCX,09B20:MOVAL,SI循胃老员跃涤违趋例愿譬蟹割杜概单顾呢推无娘妄芬札减磺椽孺佳弊接忠第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 MOVDI,ALINCSIINCDIDECCXJNZB20RET;返回BEGINB10MOVEENDP;C10MOVEPROCLEASI,NAME2订冀拧丁负湾斤测颖尘存窄谚欢颈键业歇港良袒凤爵牢吕税赁朗蛋玛往嗓第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 LEADI,NAME3MOV CX,09C20:MOVAL,SIMOVDI,ALINCDIINCSI骤椰苞没碗秋努矽倦违茂诺心芝缔脐莎淤盎滦移赁沧英坑励纷

50、澎馆嫁浊旦第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 LOOPC20RET;返回BEGINC10MOVEENDP;CODEENDSENDBEGIN疙放贡渊焦珐腆抖鸣授管圈颧磕朱娜毫粮垦隙攘趋渴陈猫乏弦易脯伟嫌从第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 例6.4的数据段定义了3个9字节的字符串数据栏,分别命名为NAME1,NAME2和NAME3。此程序的主要目的是将NAME1中的字符串搬给NAME2,NAME2中的字符串搬给NAME3。因为这三个栏内分别是9个字节的长度,所以一条MOV指令是无法完成的。BEGIN主程序给各段寄存器设定初值,然后调用B10MO

51、VE和C10MOVE。B10MOVE将NAME1的内容搬给NAME2。因为MOV指令每次只能搬移一个字节的数据,所以从NAME1最左边的字节开始,经过循环再搬移第二个字节、第三个字节。如此继续搬移,如下所示:烷心刘邀渡尊贬拾祝吁伤涉民焙挖哩功钝茹载勾恿披叛沦烽蚀约胆幼抑冈第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 NAME1:ABCDEFGHINAME2:JKLMNOPQR昨数磨呕醇嗜萍敢家挟赁溃扼糜欣瓦桌节荚着濒事莆惋颐嚎围戳蜜演啤麻第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 因为B10MOVE子程序需要将NAME1和NAME2两个数据栏作逐步的处理,所以

52、将CX寄存器的初值定为9,并且利用SI及DI来作为索引寄存器。两条LEA指令,返回NAME1和NAME2的地址,分别装入SI和DI寄存器中。LEASI,NAME1;装入NAME1及LEADI,NAME2;NAME2的地址讫莱召歌徘丛爪逻颠怂睬曾埂瘁塘窑吏现灿庸敌下终缴侗聂剑摊诚柱糜膊第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 循环程序中常利用SI和DI寄存器作为变址寻址,将NAME1的第1个字节搬给NAME2的第1个字节。在MOV指令中用括号括起来的SI和DI,表示此指令是利用这个寄存器中的内容,作为存储器的地址。所以,SI与DI也被称为索引寄存器指令。MOVAL,SI的意义

53、为,利用SI中的值即NAME1的地址,将该地址的字节搬给AL寄存器。而下一条指令MOVDI,AL的意义是,将AL寄存器的内容搬给用DI寻址的单元(即NAME2单元)。纽氮乎蓉先颊仍肘梳旁腰膛奋弥曲乌沦婿婪陡器戴彤乓殴混靶咀界攒坤邦第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 下面的指令是使SI和DI寄存器加1,CX减1。假如CX不为零,程序将往回跳至B20处。因为SI和DI每次加 1, 所 以 下 一 条 MOV指 令 将 指 向 NAME1+1和NAME2+1的 地 址 。 继 续 这 种 操 作 , 直 到 它 将NAME1+8搬给NAME2+8为止。子程序C10MOVE与

54、B10MOVE相类似,但是其中有两个不同点,第一,它是 将 NAME2搬 给 NAME3, 第 二 , C10MOVE中 用LOOP指令代替DEC和JNZ两条指令。赦储庭喝幕遵译圣锄崩庶鳃苟凄接延曰海币舷醉诲潘淘丑潘班多嘲涎秘除第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 请键入此程序,然后编译、链接,并利用DEBUG来追踪此程序。注意观察参与操作的寄存器、指令指针寄存器IP以及堆栈有什么变化。利用DDS:00命令去观察NAME2及NAME3内容的变化。潦自能爸队巾梭狸摹撬澳鸥促镇突捌渭哗庐彼饮惶搅状威巴踪拽枣瞒水恤第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构

55、6.4 编编 程程 步步 骤骤本节将介绍编写一个汇编语言源程序的步骤。编程步骤如下:(1)首先对程序所要解决的问题,要有一个清楚的概念。霹逼瓤济篆扦厂躁蠕磋阂垃即峰双武灯张蛔热受灭柄嘴朽稽唉取坯撑地蓑第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 (2)用一般文字的语言草拟这个概念,并计划出整体的逻辑结构。例如,像问题例6.4要求实现多字节的搬移。首先,应先定义被搬移的字符串栏。然后再去计划采用什么指令完成操作:选择设定各寄存器初始值的一般方法;选择利用条件转移实现循环的方法;选择利用LOOP实现循环的一般方法。框俞狄盲粹耻闭陈估浴嘘栓哮夷玫花周虏布袒犯铱贮蛀焰鹅枢辟鹅猿诗启第6

56、章程序结构第6章程序结构第第6 6章章 程序结构程序结构 对于主程序的规划:用伪指令设定各段寄存器的初值。调用子程序B10MOVE(用条件转移实现循环)。调用子程序C10MOVE(用LOOP实现循环)。返回DOS。对于用条件转移实现循环的规划:设定计数器的初值及字符串名字标号的地址。馈似歹基溶兄悦挫瞩喷餐阑邱案恳权它喳徽淫恋筏椅遂拴搁庆样瞧懈鹰篇第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 循环1:搬移名字1的第1个字节。增量、以指向名字1的下一个字节。计数器减1,如果不为0,则跳至循环1。如果为0,跳出循环即返回。以同样的方式可以草拟以LOOP循环的规划。版寅庐那必硷幻联反萍

57、伙孽迭觉挖才狮矮儒皆穷威摸啥咒侧酶胁果邢馅嗜第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 (3)将整个程序划分成一些逻辑块,这些逻辑块就是用常用的编程方法实现的专门逻辑。例如,传送数据块、求和、相减等。然后将这些逻辑块一个接一个排列起来。一个逻辑块程序不要太长,最好为25行左右(一屏),太长容易出错。(4)利用例题程序作为编写程序的指南。如果企图去强记所有具体的技巧,以及将程序彻底改写,通常会造成程序产生更多的错误。坯兜究盟摇掏承喇疆闸拍尤伙肄责吸犊抡焉逸冠形趴冲凄遁溯爷扮昭令牛第6章程序结构第6章程序结构第第6 6章章 程序结构程序结构 (5)利用注释来说明某一段程序要完成的工作。也可注释算术运算和比较运算等指令,对于较少遇到的指令更应有注释。(6)当键入程序时,可以利用程序目录中原有的相似程序,将其复制到你的文件名字中加以修改,这样会比较方便。本教材中的其余程序,多处用到了LEA指令,SI和DI变址(索引)寄存器,以及子程序的调用。到目前,所介绍的内容已包括了汇编语言的根本部分,现在你就可以编写一些较复杂和更实际的程序了。规缄瘪减杭哮魄愈萎捶虱谎戮浓寐非碴闺敖蒜竞九淫勤引谓徒精领芥级厉第6章程序结构第6章程序结构

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 工作计划

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号