汇编语言 课件 第6章子程序结构_第1页
汇编语言 课件 第6章子程序结构_第2页
汇编语言 课件 第6章子程序结构_第3页
汇编语言 课件 第6章子程序结构_第4页
汇编语言 课件 第6章子程序结构_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章子程序结构(jiégòu)讲授(jiǎngshòu)要点子程序的定义、调用与返回。子程序的参数传递方法。精品资料2/4/202380x86汇编语言程序设计子程序调用(diàoyòng)和返回指令:code1segmentmainprocfar……

callfarptrsubp……retmainendpcode1endscode2segmentsubpprocfar……

retsubpendpcode2ends段间调用(diàoyòng)和返回codesegmentmainprocfar……callsubp……retmainendpsubpprocnear……

retsubpendpcodeends段内调用和返回精品资料2/4/202380x86汇编语言程序设计CALL调用指令段内直接近调用:CALLDST执行操作:(SP)←(SP)-2((SP)+1,(SP))←(IP)(IP)←(IP)+16位位移(wèiyí)量段内间接近调用:CALLDST执行操作:(SP)←(SP)-2((SP)+1,(SP))←(IP)(IP)←(EA)精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计段间直接远调用:CALLDST执行操作:(SP)←(SP)-2((SP)+1,(SP))←(CS)(SP)←(SP)-2((SP)+1,(SP))←(IP)(IP)←偏移(piānyí)地址(CS)←段地址段间间接远调用:CALLDST执行操作:(SP)←(SP)-2((SP)+1,(SP))←(CS)(SP)←(SP)-2((SP)+1,(SP))←(IP)(IP)←(EA)(CS)←(EA+2)精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计RET返回指令段内近返回:RET执行操作(cāozuò):(IP)←((SP)+1,(SP))(SP)←(SP)+2段内带立即数近返回:RETEXP段间远返回:RET执行操作(cāozuò):(IP)←((SP)+1,(SP))(SP)←(SP)+2(CS)←((SP)+1,(SP))(SP)←(SP)+2段间带立即数远返回:RETEXP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计例:带立即(lìjí)数返回(SP)堆栈(duīzhàn)段codesegmentmainprocfar……pushaxpushbxpushcxcallsub……retmainendpsubprocnear……ret6subendpcodeends(IP)(cx)(bx)(ax)(SP)(SP)精品资料2/4/202380x86汇编语言程序设计6.1子程序概述

6.1.1过程(guòchéng)的定义过程定义由PROC与ENDP伪指令实现,形式如下(rúxià): 过程名PROC[NEAR|FAR] <过程体> 过程名ENDP1.过程名在整个程序中必须是唯一的。2.过程名本质上与标号一样,也具有3种属性:段地址、偏移地址和类型(NEAR或FAR)。3.PROC后用关键字NEAR、FAR或空,以表示过程的类型(缺省为NEAR)。精品资料2/4/202380x86汇编语言程序设计6.1.2过程调用(diàoyòng)和返回1.过程调用和返回指令(1)CALL:过程调用与JMP指令类似,CALL指令包括下列4种调用方式:段内直接调用(Intrasegment/DirectCall)段间直接调用(Intersegment/DirectCall)段内间接(jiànjiē)调用(Intrasegment/IndirectCall)段间间接(jiànjiē)调用(Intersegment/IndirectCall)段内调用在同一代码段内进行,又称近(Near)调用;段间调用可以在不同代码段之间进行,又称远(Far)调用。精品资料2/4/202380x86汇编语言程序设计语法格式: CALLProcName 段内直接调用:IP进栈,IP=label的偏移地址; 段间直接调用:CS:IP进栈,CS:IP=label的分段地址

功能描述:(1)返回地址进栈。 远调用:CS与IP(下一条指令(zhǐlìng)的地址)依次进栈。 近调用:IP(下一条指令(zhǐlìng)的16位偏移地址)进栈。(2)转移到过程的第1条指令(zhǐlìng)去执行。 远调用:根据操作数,将32位地址送CS:IP。 近调用:根据操作数,将16位偏移地址送IP。对标志位的影响:无。精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计(2)RET指令RET(Return):过程返回语法格式: RET ;近返回或远返回 RET imm16 ;近返回或远返回,并调整堆栈:SP=SP+imm16功能描述(miáoshù): RET:返回地址出栈,从而实现转移到返回地址处。其中, 远返回:POP1个双字到CS:IP。 近返回:POP1个字到IP。 RETimm16:在返回地址出栈后,CPU立即将imm16加到堆栈指针SP。这种机制用来在返回前将参数从栈中移出。对标志位的影响:无。说明:RET由汇编程序根据其所在过程的类型(NEAR或FAR)决定是近返回还是远返回。缺省为近返回。精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计2.使用(shǐyòng)过程应注意的问题在过程体内必须有一条RET指令被执行到。如果在过程内没有执行到RET或其它转移指令,程序将继续执行ENDP后的指令。正确选择过程的类型。通常基于下列原则:若过程只在同一代码段中被调用,则定义为NEAR。若过程可以在不同代码段中被调用,则定义为FAR。通常要保证RET指令执行前,栈顶内容正好是返回地址。注意保护相关寄存器的值。通常,除了作为返回参数的寄存器外,过程不应改变其它寄存器的值。可以将过程定义放在单独的代码段中。若过程定义与主程序处于同一代码段,则要保证其只有被调用时,才会执行。精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计3.保存(bǎocún)和恢复寄存器例:SUBTPROCNEARPUSHAXPUSHBXPUSHCX……POPCXPOPBXPOPAXRETSUBTENDP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计【例6.1】分析下列程序(chéngxù),描述它的功能。dsegSEGMENTbufDB80,81DUP(0)dsegENDSssegSEGMENTSTACKDW64DUP(0)ssegENDScsegSEGMENTASSUMECS:cseg,DS:dseg,SS:sseg精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计crPROC(NEAR)MOVAH,2MOVDL,13INT21HMOVDL,10INT21HRETcrENDP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计main:MOVAX,dsegMOVDS,AXLEADX,bufMOVAH,10INT21H;输入一个符号串CALLcrMOVAH,1INT21H;输入一个字符(zìfú)MOVBL,AL;用BL保存读入的字符(zìfú)LEASI,BUF+2MOVCX,BUF+1精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计lab2:MOVDL,[SI]CMPDL,BLJZlab1;等于(děngyú)第2次输入的符号则转MOVAH,2INT21HINCSILOOPlab2lab1:MOVAH,4CHINT21HcsegENDSENDmain精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计【例6.2】编写一个子程序,对一个无符号的字型数组的各元素(yuánsù)求和。在调用子程序之前,已把数组的段地址放在DS中,起始偏移地址放在寄存器SI中,数组元素(yuánsù)个数(>0)放在CX中。要求子程序把计算结果以双字的形式存放,高位放在DX中,低位放在AX中。sumPROCNEARPUSHBX;保护(bǎohù)用到的寄存器BXXORAX,AXMOVDX,AX;求和前先把存放结果的DX,AX清0MOVBX,AX精品资料2/4/202380x86汇编语言程序设计s1:ADDAX,[BX+SI];把一个(yīɡè)元素加到AX中ADCDX,0;若有进位,DX加1INCBXINCBX;BX加2,指向数组的下一元素LOOPs1POPBX;恢复寄存器BX的值RETsumENDP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计6.2过程(guòchéng)的参数传递参数的分类:入口参数:由调用者向过程传递的数据,作为(zuòwéi)过程的输入参数。出口参数:由过程向调用者返回的数据,作为(zuòwéi)过程的输出参数。根据问题的需要,过程可以只有入口参数或只有出口参数,也可以二者兼有。对于过程与调用者之间的参数传递,可根据传递的数据量,选择采用寄存器、变量或堆栈等方式。由于过程是相对独立的功能块,因此,在定义过程时,通常要加上适当的注释,主要包括功能、入口参数与出口参数等。精品资料2/4/202380x86汇编语言程序设计6.2.1用变量传递(chuándì)参数在程序中定义全局变量,如放在数据(shùjù)段,过程直接按名访问该变量。过程直接以变量作为参数,虽然方便,但通用性较差。

【例6.3】编写一个子程序,以放在DS段中year的公元年份为入口参数,判断该年是否为闰年。另有一个应用程序,它已定义了一个字节型数组t,依次存放着12个月的每月天数,其中2月份的天数是28。应用程序已经在DS段中存放了年份值,利用前面编写的子程序,编写程序段调整数组t中2月份的天数。精品资料2/4/202380x86汇编语言程序设计【解】;功能:根据一个年份是否为闰年,设置该年2月份的天数;入口(rùkǒu):DS段中的字型变量year=公元年份;出口:DS段中的字节型变量t+1=该年2月份天数;破坏寄存器:无jud1PROCNEARPUSHAXPUSHBXPUSHCXPUSHDXMOVBYTEPTR[t+1],28MOVAX,[year]精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计MOVDX,0MOVBX,4DIVBX;除以4CMPDX,0JNZlab1;不能整除4则不是闰年,转MOVAX,[year];取回(qǔhuí)年份值MOVBX,100DIVBX;除以100CMPDX,0JNZlab2;不能整除100则是闰年,转MOVAX,[year]MOVBX,400DIVBX;除以400精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计CMPDX,0JNZlab1lab2:INCBYTEPTR[t+1];是闰年(rùnnián),把天数加1,设置出口参数lab1:POPDXPOPCXPOPBXPOPAXRETJud1ENDP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计6.2.2用寄存器传递(chuándì)参数通过寄存器传递数据或数据地址。通常选择AL、AX、DX:AX(或EAX)传递字节、字或双字。传递16位偏移(piānyí)地址最好选择SI、DI或BX,传递32位地址可以用DS:BX、DS:SI、DS:DI、ES:BX、ES:SI或ES:DI等。精品资料2/4/202380x86汇编语言程序设计【例6.4】用寄存器传递参数,编写例6.3要求的子程序。【解】;功能:判断一个年份是否为闰年;入口:AX=公元年份;出口(chūkǒu):CF,1表示是闰年,0表示非闰年;破坏寄存器:AXjudPROCNEARPUSHBXPUSHCXPUSHDXMOVCX,AX;临时保存年份值MOVDX,0MOVBX,4精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计DIVBX;除以4,为预防溢出(yìchū),用双字除以字CMPDX,0JNZlab1;不能整除4则不是闰年,转MOVAX,CX;取回年份值MOVBX,100DIVBX;除以100CMPDX,0JNZlab2;不能整除100则是闰年,转MOVAX,CXMOVBX,400DIVBX;除以400CMPDX,0JZlab2精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计lab1:CLC;把CF清0表示非闰年,设置出口参数JMPlab3lab2:STC;把CF置1表示是闰年,设置出口参数lab3:POPDXPOPCXPOPBXRETjudENDP对于DX中存放的年份值,需要先放到AX中,才能调用子程序jud,然后(ránhòu)以调用返回后的CF值决定是否把t数组中表示2月份天数的[t+1]加1。程序段如下:MOVAX,DXCALLjudADCBYTEPTR[t+1],0;原值+0+CF精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计6.2.3用地址表传递(chuándì)参数建立一个(yīɡè)地址表,存放所有参数的地址,传递地址表的首地址给过程。这种方法特别适合于参数较多的情况。精品资料2/4/202380x86汇编语言程序设计6.2.4用堆栈(duīzhàn)传递参数过程(guòchéng)从堆栈得到入口参数,返回前将出口参数写入堆栈;调用者通过出栈得到返回参数。过程(guòchéng)从堆栈存取参数时,通常使用BP,因为其隐含的段地址在SS中。采用堆栈传递参数时,典型的过程(guòchéng)结构如下: StdProc proc near push bp mov bp,sp ;BP指向当前栈顶,用于取入口参数 ... pop bp ret ParmSize;返回前从堆栈移出入口参数 StdProcendp其中,ParmSize是过程(guòchéng)被调用前进栈的入口参数的字节数。精品资料2/4/202380x86汇编语言程序设计【例6.5】用堆栈传递入口参数,编写子程序,把接收的两个(liǎnɡɡè)带符号整数中大的一个作为结果,出口参数放在AX中。【解】;功能:求两个(liǎnɡɡè)带符号整数中大的一个;入口参数:调用前把两个(liǎnɡɡè)带符号整数入栈;出口参数:AX;破坏寄存器:AX精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计_maxPROCNEARPUSHBP;暂时保存寄存器BP的值MOVBP,SPMOVAX,WORDPTR[BP+6];取第1个参数(cānshù)到AXCMPAX,WORDPTR[BP+4];与第2个参数(cānshù)比较JGElabMOVAX,WORDPTR[BP+4];取第2个参数(cānshù)到AXlab:POPBP;恢复寄存器BP的原值RET_maxENDP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计6.3子程序举例(jǔlì)【例】编写子程序write,把整型数据以十进制形式显示到屏幕上。【分析】参照高级语言中输出语句的功能,write子程序应具备这样(zhèyàng)一些特点:被显示的整数可以是无符号的,也可以是带符号的,但需要明确指出是哪一种情况;整数在计算机内部是字型数据,范围为-32768~+65535;被输出的数据是带符号数时,负号“-”必须输出,而正号“+”总是省略;输出数据的最大位数是十进制的5位,当计算出5位中的某一位是0时,需要判断这个0是否应该输出,输出条件是前面已经输出过非0数字或者这个0是个位数。输出的数必须是以ASCII码形式存放在DL中。精品资料2/4/202380x86汇编语言程序设计【解】;功能:在屏幕上输出整数值;入口:AX=待输出的整数;CF=为0表示输出无符号数,为1则输出带符号数;出口:无;破坏寄存器:无;DX、AX-存放整数,BX-分离各整数位(shùwèi)时除数,CX-分离各数位(shùwèi)次数,;SI-表示是否输出过非0数字,DI-暂存输出的整数writePROCNEARPUSHBXPUSHCXPUSHDXPUSHSI精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计PUSHDIMOVSI,0;SI清0表示还没有输出过非0数字MOVDI,AX ;保存(bǎocún)待输出的数值到DI中JNCw1 ;作为无符号数输出转CMPAX,0JGEw1;AX是正数转MOVDL,'-'MOVAH,2INT21H ;输出负号NEGDI ;取绝对值放在DI中精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计w1:MOVBX,10000;第一次的除数MOVCX,5;重复次数w2:MOVAX,DI;取回待输出数值MOVDX,0;被除数高位清0DIVBX ;做双字除以字的除法MOVDI,DX;余数保存(bǎocún)在DI中CMPAL,0JNEw3 ;商非0转CMPSI,0 ;商是0,判断前面是否输出过数字JNEw3 ;前面已输出过数字,则当前的0应该输出,转CMPCX,1 ;判断是否是个位JNEw4 ;不是个位则不输出当前的0,转精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计w3:MOVDL,ALADDDL,30HMOVAH,2INT21H ;输出当前这一位数字(shùzì)MOVSI,1 ;用SI记载已输出过数字(shùzì)w4:MOVAX,BXMOVDX,0MOVBX,10DIVBXMOVBX,AX;bx/10=>bx,计算下一次的除数LOOPw2精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计POPDIPOPSIPOPDXPOPCXPOPBXRETwriteENDP精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计【例6.11】编写子程序read,从键盘上读入一个整数。【分析】为了尽可能与高级语言中整数输入的情况一致,子程序不仅要能读入正确输入时的数据,还要能对不正确的输入做出适当的反应,因此设计上要注意几个问题:首先是要用字符串输入方式(DOS的10号子功能),因为这种方式支持退格键修改(xiūgǎi)功能,因而需要准备相应的输入缓冲区;出口参数需要两个,以CF的设置表示输入是否正确,当输入正确时把整数值放在AX中作为输入结果;要能够跳过若干个连续的空格符;要能够处理正负号。精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计【解】;功能:从键盘读入整数值;入口:CF=为0表示废弃多余符号(fúhào)。;为1则把多余符号(fúhào)留作下一次输入。;出口:CF=0表示正常读入,1表示输入有错;破坏寄存器:无readPROCNEARPUSHBXPUSHCXPUSHDXPUSHSIPUSHDS;以上为寄存器保护精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计PUSHFPUSHCSPOPDS;令DS取CS的值rd1:MOVBX,CS:[point];取上次(shànɡcì)输入后已读取到输入串的位置rd2:INCBXCMPCS:[bufin+BX+1],''JErd2;跳过空格CMPCS:[bufin+BX+1],13JNZrd4;不是回车键,转读入数值处理精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计rd3:LEADX,CS:[bufin]MOVAH,10INT21H;遇回车键要求再次输入MOVAH,2MOVDL,10INT21H;换行MOVCS:[point],0JMPrd1;对新的输入再转去(zhuǎnqù)跳过前导空格rd4:MOVSI,BXDECSI;令SI指向输入串的第一个有效字符MOVAX,0MOVBX,10MOVCX,0精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计rd5:CMPCS:[bufin+SI+2],'+'JNZrd6;不是正号转CMPCL,1JErd10;已读到正确(zhèngquè)数值后,遇正号转CMPCL,0JErd8;正号是第一个有效字符转STC;输入有错JMPrd13精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计rd6:CMPCS:[bufin+SI+2],'-'JNZrd9CMPCL,1;已读到正确数值后,遇负号(fùhào)转JErd10CMPCL,0JErd7;负号(fùhào)是第一个有效字符转STC;输入有错JMPrd13精品资料2/4/202380x86汇编语言(huìbiānyǔyán)程序设计rd7:MOVCH,1;记下(jìxià)读入的是负数rd8:MOVCL,2;记下(jìxià)已读入正/负号INCSI;指向下一字符JMPrd5rd9:CMPCS:[bufin+SI+2],'0'JBrd10;不是数字转CMPCS:[bufin+SI+2],'9'JArd10

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论