资源描述:
《(第13讲)第5章控制转移和程序结构ppt课件.ppt》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
第5章控制转移和程序结构5.4子程序结构补充:DOS功能调用 第5章控制转移和程序结构5.1目标地址寻址方式5.1.1转移范围5.1.2寻址方式5.1.3无条件转移指令5.2分支程序结构5.2.1条件转移指令5.2.2单分支结构5.2.3双分支结构5.2.4多分支结构5.3循环程序结构5.3.1循环指令5.3.2计数控制循环5.3.3条件控制循环5.4子程序结构5.4.1子程序指令5.4.2子程序设计5.4.3参数传递5.4.4程序模块 5.4子程序结构5.4.1子程序指令5.4.2子程序设计5.4.3参数传递5.4.4程序模块 5.4.1子程序指令1.子程序定义2.子程序调用指令CALL3.子程序返回指令RET 子程序(过程)定义——有独立功能独立程序模块子程序(过程)定义格式符号名PROC类型(NEAR或FAR)……RET符号名ENDP位于程序段内程序名 LablePROC[NEAR或FAR]RETLableENDP子程序调用过程CALLlabel主程序子程序回到CALL指令后的指令处——返回地址 例.带子程序(计算变量差)的汇编程序DATASSEGMENTVARADB34HVARBDB12HRESULTDB?DATASENDSCODESSEGMENTASSUMECS:CODES,DS:DATASSTART:MOVAX,DATASMOVDS,AXMOVAL,VARAMOVAH,VARBCALLA_B;调用子程序MOVRESULT,ALMOVAH,4CHINT21HA_BPROC;过程定义SUBAL,AHRET;子程序返回A_BENDP;过程结束CODESENDSENDSTART 子程序类型按子程序与调用语句间的位置NEAR类型段内调用:改IPCALL与过程在同一个段FAR类型段间调用:改IP和CSCALL与过程不在同一个段 5.4.1子程序指令1.子程序调用指令CALL2.返回指令RET子程序调用时要“有去有回”转移指令执行后“有去无回” 1.子程序调用指令CALL格式CALLlabel;标号指定的子程序CALLreg16/reg32;寄存器指定子程序的地址CALLmem16/mem32;存储单元指定子程序的地址目标地址在CALL指令中相对寻址、直接寻址在CALL指令指定的寄存器或内存单元中间接寻址段内调用(近调用)、段间调用(远调用) (1)CALL指令操作注意不同的子程序属性(NEAR或FAR)形成不同的目标地址,并装入IP或IP与CS将下一条指令(断点)的地址(IP或IP与CS)压入堆栈子程序的首地址装入IP或IP与CS (2)CALL指令分类直接调用段内段间间接调用存储器寄存器段内段间 直接调用段内PROC属性:NEAR操作(SP)←(SP)-2((SP)+1,SP)←(当前IP)(IP)←(当前IP)+D16(16位位移量)段间PROC属性:FAR操作(SP)←(SP)-2((SP)+1,SP)←(CS)(SP)←(SP)-2((SP)+1,SP)←(IP)(IP)←PROC的偏移地址(CS)←PROC的段地址下条指令的IP(当前IP)入栈PROC提供的目标地址送入IP当前IP和CS入栈目标地址送入IP和CS 例1.段内直接调用codeSEGMENT…CALLsubpXXX:YYY……subpPROCNEAR…RETsubpENDPcodeENDS;代码段;过程定义机器指令中的偏移量,即目标地址与断点地址的差。当前IP;返回;YYY入栈,D16=subp-YYY①③② 例2.段内直接调用——两个数据变量X与Y相乘DATASGSEGMENTXDW100YDW10DATASGENDSCODESGSEGMENTASSUMECS:CODESG,DS:DATASGSTART:…CALLSUBP…MOVAH,4CHINT21HSUBPPROCNEARMOVAX,XMOVBX,YMULBXRETSUBPENDPCODESGENDSENDSTART 例3.段间直接调用CALL2500H:3600H;段间直接调用;指给出被调用子程序的;段地址和偏移量CALLSUB_PROC1;设SUB_PROC1为FAR型;段间直接调用 CSEG1SEGMENT…CALLFARPTRsubp;a处的CS:IP入栈转subpa:……CSEG1ENDSCSEG2SEGMENT…subpPROCFAR…RETsubpENDP…CSEG2ENDS①③②例4.段间直接调用 间接调用段内PROC属性:NEAR操作(SP)←(SP)-2((SP)+1,SP)←(当前IP)(IP)←(EA)/REG段间PROC属性:FAR操作(SP)←(SP)-2((SP)+1,SP)←(CS)(SP)←(SP)-2((SP)+1,SP)←(IP)(IP)←(EA)(CS)←(EA+2)寄存器或存储单元提供子程序的目标地址当前IP入栈REG或MEM提供的目标地址送入IP当前IP和CS入栈MEM提供的目标地址送入IP和CS 例1.段内直接调用CALLAX;IP←AXCALLWORDPTR[BX];IP←[BX] 例2.CALLdwordptr[BX+ADDR3]设:DS=2000H,BX=1400H,DDR3=020AHIPCS执行跳转指令后,转移至4000H:3000H处执行程序300040002000H00300040EA=1400H+020AH数据段DS 2.子程序返回指令RET作用:子程序结束,实现返回格式RET;无参数返回返回地址出栈RETi16;有参数返回返回地址出栈ESP←ESP+i16分类段内返回、段间返回注意:(1)MASM确定调用远近并产生相应返回指令(2)为能准确返回,返回指令类型必须与调用指令类型一致 无参数返回RET功能子程序程定义为NEAR段内返回:栈顶的一个字送IPFAR段间返回:栈顶的一个双字送IP,CS段内与段间返回指令的异同相同:指令形式不同:指令机器代码 RET有参数返回RETi16功能完成RET指令的功能将当前栈顶的imm16个字节内容废除(IP)←((SP)+1,(SP))(IP)←((SP)+1,(SP))(SP)←(SP)+2(SP)←(SP)+2(CS)←((SP)+1:(SP))(SP)←(SP)+n(SP)←(SP)+2(SP)←(SP)+nNEARFAR CODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AX……PUSHBXPUSHCXCALLDELCHARCS:XXXXMOVAH,4CHINT21HCODEENDSENDSTARTDELCHARPROCNEAR……RET4DELCHARENDP例:RETimm16堆栈使用情况 [例题5-15]十六进制转换为ASCII码程序-1;代码段(子程序)htoascproc;过程定义andal,0fh;只取AL的低4位oral,30h;AL高4位变成3cmpal,39h;是0~9,还是A~Fjbehtoendaddal,7;是A~F,再加上7htoend:ret;子程序返回htoascendp;过程结束子程序名HTOASC入口参数AL=1位十六进制数(低4位)出口参数AL=ASCII码功能说明十六进制数转换为ASCII码子程序功能 [例题5-15]十六进制转换为ASCII码程序-2;代码段(主程序)movax,wvarmovcx,4;共4位十六进制数again:rolax,4pushaxcallhtoasc;调用子程序movah,2movdl,alint21h;显示一个字符popaxloopagain子程序名HTOASC入口参数AL=1位十六进制数(低4位)出口参数AL=ASCII码功能说明十六进制数转换为ASCII码子程序功能不关心实现 5.4.2子程序设计1.子程序文件2.子程序嵌套3.子程序设计中的问题 1.子程序文件组成子程序说明文挡+子程序说明文档的组成功能描述子程序的名称、功能、性能指标(如执行时间)等子程序的入口、出口参数所用寄存器和存储单元子程序中又调用的其它子程序调用实例(可有可无) 例1.子程序说明文档;子程序DTOB;程序功能:将两位10#(BCD码)转换成2#;入口参数:AL寄存器中存放10#;出口参数:CL寄存器中存放转换完的2#;所用Reg:BX;执行时间:0.06ms 例2.子程序说明文档——matlab程序dct2.m 2.子程序嵌套子程序中调用别的子程序只要堆栈空间允许,嵌套层次不限主过程子过程1CALL子过程1断点1子过程嵌套示意图子过程2①②③④⑤RETRETCALL子过程2断点2⑥⑦⑧⑨ 3.子程序设计中的问题(1)主程序与子程序的连接CALL、RET(2)现场的保护与恢复(3)主、子程序之间的参数传递 (2)现场的保护与恢复“现场”主程序→子程序时,主程序的状态包括:当时的标志寄存器、段寄存器、通用寄存器及指令指针目的保证主、子程序的数据信息和工作状态不互相干扰方法用成对的PUSH、POP保护主、子程序中都用到的Reg及mem “现场”保护和恢复的方法方法一:PUSHBXPUSHCXCALLPROC-1POPCXPOPBX方法二:.PROC-1PROC.PUSHBX.PUSHCXCALLPROC-1.POPCX.POPBX.RETPROC-1ENDP…常用第二种方法保护和恢复现场对中断子程序必须用第二种方法。 子程序设计要点过程定义确定子程序名和调用属性调用子程序:CALL返回主程序:RET保持堆栈平衡:压入和弹出操作成对使用现场:进入保护,返回前恢复在代码段的主程序之外允许嵌套和递归与主程序,可共用一个数据段,也可具有独立数据段 [例题5-17]寄存器内容显示程序-1;数据段dvardd1234abcdhregddb'EAX=';代码段movebx,offsetregdmovecx,4;显示4个字符dregd1:movah,2movdl,[ebx]int21hincebxloopdregd1 [例题5-17]寄存器内容显示程序-2movecx,8;共8位十六进制数moveax,dvardregd2:roleax,4pusheaxcallhtoasc;调用子程序movah,2movdl,alint21h;显示一个字符popeaxloopdregd2子程序名HTOASC入口参数AL=1位十六进制数(低4位)出口参数AL=ASCII码功能说明十六进制数转换为ASCII码子程序功能 [例题5-17]寄存器内容显示程序-3htoascprocpushebxmovebx,offsetASCIIandal,0fh;取得一位十六进制数xlatASCII;换码:AL←CS:[EBX+AL]popebxret;子程序的局部数据(在代码段CS)ASCIIdb30h,31h,32h,33h,34hdb35h,36h,37h,38h,39hdb41h,42h,43h,44h,45h,46hhtoascendp [例题5-16]字符串显示程序-1;数据段msgdb'Well,Imadeit!',0;代码段(主程序)movsi,offsetmsg;主程序提供显示字符串calldpstri;调用子程序子程序名DPSTRI入口参数DS:SI=字符串首地址功能说明显示字符串(以0结尾) [例题5-16]字符串显示程序-2;代码段(子程序)dpstriproc;子程序:显示字符串pushax;寄存器保护dps1:moval,[si];取显示字符cmpal,0;是结尾,则显示结束jzdps2calldpchar;调用字符显示子程序incsijmpdps1dps2:popax;寄存器恢复retdpstriendp子程序名DPCHAR入口参数AL=ASCII码功能说明显示字符子程序嵌套 [例题5-16]字符串显示程序-3dpcharproc;子程序显示字符pushax;顺序入栈,保护寄存器pushdxmovah,2movdl,al;显示一个字符int21hpopdx;逆序出栈,恢复寄存器popaxretdpcharendp子程序名DPCHAR入口参数AL=ASCII码功能说明显示字符 (3)主、子程序之间的参数传递参数传递入口参数(输入参数):主程序→子程序出口参数(输出参数):子程序→主程序参数内容数据本身传递数值数据的存储地址传递地址、传递引用参数传递方法寄存器、变量或堆栈 参数传递——寄存器最简单和常用传递的内容少量数据:数值大量数据:数据存放地址出口参数寄存器不能保护和恢复入口参数寄存器可以保护、也可以不保护(1)优点:简单快捷(2)缺点:寄存器数量有限,仅适于参数较少的情况 例1.参数传递——寄存器要求:数组ARRAY中所有元素之和,并存于SUM单元中子程序说明:;子程序名:SUM1;程序功能:求字节数组和;入口参数:SI=数组首址,CX=数组长度;出口参数:AX=数组和;使用寄存器:AX,CX,SI STACKSEGMENTSTACKDB100DUP(?)STACKENDSDATASEGMENTARRAYDBd1,d2,d3,…,dn;是字节数组COUNTEQU$-ARRAY;字节数组元素个数SUMDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXLEASI,ARRAYMOVCX,COUNTCALLSUM1;调用子程序求和,返回值在AX中MOVSUM,AX;和存于SUM单元MOVAH,4CH;返回DOSINT21H ;子程序名:SUM1;程序功能:求字节数组和;入口参数:SI=数组首址,CX=数组长度;出口参数:AX=数组和;使用寄存器:AX,CX,SISUM1PROCNEARCMPCX,0;提前退出JZEXITMOVAX,0;数组和通过AX寄存器;回送到主程序AGIN:ADDAL,[SI]ADCAH,0INCSILOOPAGINEXIT:RETSUM1ENDPCODEENDSENDSTART 例2.参数传递——寄存器要求:二进制数(0-F)转换成ASCII(‘0’-‘F’)入口参数:AL——待转换数在AL的低四位出口参数:AL——转换结果 ;程序完整代码:CODESSEGMENTASSUMECS:CODES,DS:DATAS,SS:STACKSSTART:MOVAX,DATASMOVDS,AXMOVAL,0CHCALLBIN2ASCMOVAH,4CHINT21HBIN2ASCPROCCMPAL,9JBETOBEADDAL,7HTOBE:ADDAL,30HDONE:RETBIN2ASCENDPCODESENDSENDSTART [例题5-18]有符号十进制数输入程序-1算法如下:首先判断输入正数还是负数,并用一个寄存器记录下来;接着输入0~9数字(ASCII码),并减30H转换为二进制数;然后将前面输入的数值乘10,并与刚输入的数字相加得到新的数值;重复2、3步,直到输入一个非数字字符结束;如果是负数进行求补,转换成补码;否则直接将数值保存 [例题5-18]有符号十进制数输入程序-2movecx,countmovebx,offsetarrayagain:callreadsid;输入一个数据mov[ebx],eax;存放出口参数addebx,4calldpcrlf;光标回车换行loopagain子程序名READSID出口参数EAX=32位二进制补码功能说明有符号十进制数输入 [例题5-18]有符号十进制数输入程序-3readsidproc;输入有符号十进制数子程序pushebx;说明:负数用“-”引导pushecxpushedxxorebx,ebx;EBX保存结果xorecx,ecx子程序名READSID出口参数EAX=32位二进制补码功能说明有符号十进制数输入 [例题5-18]有符号十进制数输入程序-4;ECX为正负标志:0为正,-1为负movah,1;输入一个字符int21hcmpal,'+';是“+”,继续输入字符jzrsid1cmpal,'-';是“-”,设置-1标志jnzrsid2movecx,-1 [例题5-18]有符号十进制数输入程序-5rsid1:movah,1;继续输入字符int21hrsid2:;不是0~9之间的字符,则输入数据结束cmpal,‘0’jbrsid3cmpal,'9'jarsid3;是0~9之间的字符,则转换为二进制数subal,30h [例题5-18]有符号十进制数输入程序-6imulebx,10;数值乘10:EBX←EBX×10movzxeax,aladdebx,eax;与新输入数值相加jmprsid1;继续输入字符rsid3:cmpecx,0;是负数,进行求补jzrsid4negebxrsid4:moveax,ebx;设置出口参数popedxpopecxpopebxret;子程序返回readsidendp [例题5-18]有符号十进制数输入程序-7dpcrlfproc;光标回车换行子程序pushaxpushdxmovah,2movdl,0dhint21hmovah,2movdl,0ahint21hpopdxpopaxretdpcrlfendp 参数传递——存储单元(共享变量)子程序和主程序用同一个变量名存取数据子程序的通用性较差适合在多个程序段间、尤其在不同的程序模块间传递数据两种直接传递(又称变量传递)利用事先约定的存储单元直接传递数据本身参数地址表传递 [例题5-19]有符号十进制数输出程序-1算法如下首先判断数据是零、正数或负数,是零显示“0”退出;是负数,显示“-”,求数据的绝对值;接着数据除以10,余数加30H转换为ASCII码压入堆栈;重复第3步,直到商为0结束;依次从堆栈弹出各位数字,进行显示 [例题5-19]有符号十进制数输出程序-2movecx,countmovebx,0again:moveax,array[ebx*4]movdtemp,eax;入口参数存放到共享变量calldispsid;调用子程序显示一个数据incebxcalldpcrlf;光标回车换行loopagain子程序名DISPSID入口参数DTEMP=32位二进制补码功能说明有符号十进制数显示 [例题5-19]有符号十进制数输出程序-3dispsidproc;显示有符号十进制数子程序pusheax;入口参数:共享变量DTEMPpushebxpushedxmoveax,dtemp;取出显示数据testeax,eax;判断数据是零、正数或负数jnzdsid1movdl,'0';是零,显示“0”后退出movah,2int21hjmpdsid5 [例题5-19]有符号十进制数输出程序-4dsid1:jnsdsid2;是负数,显示“-”movebx,eax;EAX数据暂存于EBXmovdl,'-'movah,2int21hmoveax,ebxnegeax;数据求补(绝对值)子程序名DISPSID入口参数DTEMP=32位二进制补码功能说明有符号十进制数显示 [例题5-19]有符号十进制数输出程序-5dsid2:movebx,10pushbx;10压入堆栈,作为退出标志dsid3:cmpeax,0;数据(商)为零,转向显示jzdsid4subedx,edx;扩展被除数EDX.EAXdivebx;数据除以10:EDX.EAX÷10adddl,30h;余数(0~9)转换为ASCII码pushdx;数据先低位后高位压入堆栈jmpdsid3 [例题5-19]有符号十进制数输出程序-6dsid4:popdx;数据先高位后低位弹出堆栈cmpdl,10;是结束标志10,则退出jedsid5movah,2;进行显示int21hjmpdsid4dsid5:popedxpopebxpopeaxret;子程序返回dispsidendp 例1.把BX中的2#数用16#的形式在屏幕上显示出来①2#→16#(每4位一组)②16#→ASCII,并显示:0~9+30H;A~F+37H算法:将4位2#数+30H后做一次判断:若原字符在‘0’~‘9’之间,输出;若原字符‘A’~’F’之间,应再+7H输出。 MOVCH,4ROTATE:MOVCL,4ROLBX,CLMOVAL,BLANDAL,0FHADDAL,30HCMPAL,3AH;>9?JLPRINTITADDAL,7HPRINTIT:MOVDL,ALMOVAH,2;DOS调用显示单个字符INT21HDECCHJNZROTATERETBHBL 例2.100个字节的16进制数进行累加LEABX,TABLEMOVCL,100XORAX,AXLOOPER:ADDAL,[BX]JNCGOONINCAHGOON:INCBXDECCLJNZLOOPERMOVSUM,AXHLT 参数传递——堆栈主程序入口参数压入堆栈子程序弹出取得子程序出口参数压入堆栈主程序弹出堆栈取得 [例题5-20]计算有符号数平均值程序-1算法如下被加数进行符号扩展求和除以数据个数得到平均值32位有符号数扩展到64位,32位表示数据个数(最大232),不会溢出子程序名MEAN入口参数32位数据个数和偏移地址压入堆栈出口参数EAX=平均值功能说明计算有符号数平均值 [例题5-20]计算有符号数平均值程序-2moveax,countpusheax;压入数据个数(0表示232个)movebx,offsetarraypushebx;压入缓冲区的偏移地址callmean;调用子程序,求平均值addesp,8;平衡堆栈movdmed,eax;保存出口参数 [例题5-20]计算有符号数平均值程序-3meanproc;计算有符号数平均值pushebpmovebp,esppushebx;保护寄存器pushecxpushedxpushesipushedimovebx,[ebp+6];从堆栈取偏移地址movecx,[ebp+10];从堆栈取数据个数堆栈示意图 [例题5-20]计算有符号数平均值程序-4xoresi,esi;ESI保存求和的低32位值movedi,esi;EDI保存求和的高32位值mean1:moveax,[ebx];取出一个数据→EAXcdq;符号扩展→EDX.EAXaddesi,eax;求和低32位adcedi,edx;求和高32位addebx,4;指向下一个数据dececx;数据个数减少一个jnzmean1;循环moveax,esi;累加和在EDX.EAXmovedx,edi [例题5-20]计算有符号数平均值程序-5movecx,[ebp+10];数据个数在CXidivecx;有符号数除法,EAX=平均值(EDX=余数)popedi;恢复寄存器popesipopedxpopecxpopebxpopebpretmeanendp 补充:DOS功能调用DOS磁盘操作系统提供功能调用模块管理文件、设备和内存等用户不必深入了解有关设备的电路和接口,只须遵照DOS规定的调用原则即可使用 图6.18PC-DOS对内存的分配(a)DOS启动后(b)执行程序装入后 软件中断分类DOS中断中断类型号20H~3FH21H:DOS系统功能调用BIOS中断中断类型号5~1FH自由中断中断类型号40H~FFH可供系统或应用程序设置开发的中断处理程序用 DOS功能调用类型号中断功能类型号中断功能20H程序结束21H请求DOS功能调用22H结束地址23H中止(Ctrl-Break)处理24H关键性错误处理25H磁盘顺序读26H磁盘顺序写27H程序结束且驻留内存28HDOS内部使用29~2EHDOS内部保留2FHDOS内部使用30~3FHDOS内部保留 BIOS功能调用类型号中断功能类型号中断功能00H被零除11H设备检测01H单步12H存储容量02H不可屏蔽13H磁盘I/O03H断点14H通信I/O04H溢出15H盒式磁带I/O05H打印屏幕16H键盘I/O06H保留17H打印机I/O07H保留18HROMBASIC08H日时钟19H引导09H键盘1AH日时钟0AH保留1BHCtrl-Break0BH串口21CH定时器报时0CH串口11DH显示器参数0DH硬盘1EH软盘参数0EH软盘1FH图形字符扩展0FH打印机40H保留给软盘10H显示器41H硬盘参数与DOS相比,BIOS是在更低的层次上为用户提供系统服务 DOS调用与BIOS调用两者的区别DOS功能调用在更高层次上提供了与BIOS类同的功能BIOS调用比DOS调用复杂,但运行速度快,功能更强DOS功能调用只适用于DOS环境,而BIOS功能调用不受任何操作系统的约束某些功能只有BIOS具有 DOS功能子程序的调用方法格式INTn;n为中断类型号;n=20H~3FHINT21H有100多个字程序DOS系统功能调用DOS的核心功能设置入口参数在AH设置功能号n执行中断指令INTN分析、应用出口参数 例.将一个ASCII字符显示于屏幕的当前光标所在位置。解:使用BIOS的中断类型号10H、功能调用号0EH的子程序MOVAL,'?‘;要显示的字符送入ALMOVAH,0EH;功能号送入AHINT10H;调用10H软中断 常用DOS系统功能调用单字符输入(01H、07H、08H功能)显示单字符(02H、05H功能)单字符输入或显示(06H功能)字符串输入(0AH功能)显示字符串(09H功能)检测键盘状态(0BH功能) 小结掌握子程序的调用和返回主、子程序间的参数传的方法常用DOS系统功能调用的使用方法作业5.18、5.25,请上机验证