汇编语言4课件.ppt_第1页
汇编语言4课件.ppt_第2页
汇编语言4课件.ppt_第3页
汇编语言4课件.ppt_第4页
汇编语言4课件.ppt_第5页
已阅读5页,还剩88页未读 继续免费阅读

下载本文档

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

文档简介

第4章,教学重点,综合应用第2章硬指令和第3章伪指令,第4章从程序结构角度展开程序设计,重点掌握:分支结构程序设计循环结构程序设计子程序结构程序设计,4.1顺序程序设计,顺序程序完全按指令书写的前后顺序执行每一条指令,是最基本、最常见的程序结构,例4.1计算,例4.2移位,例题代码转换,例4.1,.modelsmall.stack.dataXdw5Ydw6Zdw7Wdw?,.code.startupmovax,Xaddax,Yaddax,ZmovW,ax.exit0end,例4.21/2,.dataqvardq1234567887654321h.codemoval,byteptrqvar6movbyteptrqvar7,almoval,byteptrqvar5movbyteptrqvar6,almoval,byteptrqvar4movbyteptrqvar5,almoval,byteptrqvar3movbyteptrqvar4,al,图示,例4.22/2,moval,byteptrqvar2movbyteptrqvar3,almoval,byteptrqvar1movbyteptrqvar2,almoval,byteptrqvar0movbyteptrqvar1,almovbyteptrqvar0,0,1234567887654321h,3456788765432100h,移位后,图示,64位数据左移8位,12,34,56,78,87,65,43,21,00,qvar0,qvar1,qvar2,qvar3,qvar4,qvar5,qvar6,qvar7,例题代码转换1/2,;查表法,实现一位16进制数转换为ASCII码显示.modelsmall.stack256.dataASCIIdb30h,31h,32h,33h,34h,35hdb36h,37h,38h,39h;09的ASCII码db41h,42h,43h,44h,45h,46h;AF的ASCII码hexdb0bh;任意设定了一个待转换的一位16进制数,例题代码转换2/2,.code.startupmovbx,offsetASCII;BX指向ASCII码表moval,hex;AL取得一位16进制数,正是ASCII码表中位移andal,0fh;只有低4位是有效的,高4位清0 xlat;换码:ALDS:BXALmovdl,al;入口参数:DLALmovah,2;02号DOS功能调用int21h;显示一个ASCII码字符.exit0end,4.2分支程序设计,分支程序根据条件是真或假决定执行与否判断的条件是各种指令,如CMP、TEST等执行后形成的状态标志转移指令Jcc和JMP可以实现分支控制;还可以采用MASM6.x提供的条件控制伪指令实现,单分支:求绝对值等,双分支:例4.3等,多分支:例4.4等,单分支程序设计,条件成立跳转,否则顺序执行分支语句体;注意选择正确的条件转移指令和转移目标地址,例题求绝对值,;计算AX的绝对值cmpax,0jnsnonneg;分支条件:AX0negax;条件不满足,求补nonneg:movresult,ax;条件满足;计算AX的绝对值cmpax,0jlyesneg;分支条件:AX0jmpnonnegyesneg:negax;条件不满足,求补nonneg:movresult,ax;条件满足,Good,Bad,例题无符号数除以2,;将AX中存放的无符号数除以2,如果是奇数,则加1后除以2testax,01h;测试AX最低位jzeven;最低位为0:AX为偶数addax,1;最低位为1:AX为奇数,需要加1even:rcrax,1;AXAX2;如果采用SHR指令,则不能处理AXFFFFH的特殊情况,双分支程序设计,条件成立跳转执行第2个分支语句体,否则顺序执行第1个分支语句体。注意第1个分支体后一定要有一个JMP指令跳到第2个分支体后,例题显示BX最高位,shlbx,1;BX最高位移入CFjcone;CF1,即最高位为1,转移movdl,0;CF0,即最高位为0,DL0jmptwo;一定要跳过另一个分支体one:movdl,1;DL1two:movah,2int21h;显示,对比,双分支程序改为单分支程序,例题显示BX最高位,shlbx,1;BX最高位移入CFjncone;CF0,即最高位为0,转移movdl,1;CF1,即最高位为1,DL1jmptwo;一定要跳过另一个分支体one:movdl,0;DL0two:movah,2int21h;显示,双分支程序改为单分支程序,对比,例题显示BX最高位,movdl,0;DL0shlbx,1;BX最高位移入CFjnctwo;CF0,最高位为0,转移movdl,1;CF1,最高位为1,DL1two:movah,2int21h;显示,编写分支程序,需留心分支的开始和结束,例4.3判断有无实根1/2,.startupmoval,_bimulalmovbx,ax;BX中为b2moval,_aimul_cmovcx,4imulcx;AX中为4ac(DX无有效数据),例4.3判断有无实根2/2,cmpbx,ax;比较二者大小jgeyes;条件满足?movtag,0;第一分支体:条件不满足,tag0jmpdone;跳过第二个分支体yes:movtag,1;第二分支体:条件满足,tag1done:.exit0,;寄存器AL中是字母Y或y,则令AH0;否则令AH1cmpal,Y;AL是大写Y否?jznext;是,转移cmpal,y;AL是小写y否?jznext;是,转移movah,-1;不是Y或y,则AH1,结束jmpdone;一定要跳过另一个分支体next:movah,0;是Y或y,则AH0,结束done:.,例题单分支和双分支,多分支程序设计,多个条件对应各自的分支语句体,哪个条件成立就转入相应分支体执行。多分支可以化解为双分支或单分支结构的组合,例如:orah,ah;等效于cmpah,0jzfunction0;ah0,转向function0decah;等效于cmpah,1jzfunction1;ah1,转向function1decah;等效于cmpah,2jzfunction2;ah2,转向function2,图示,多分支结构,地址表形成多分支,需要在数据段事先安排一个按顺序排列的转移地址表输入的数字作为偏移量。因为只有2个字节16位偏移地址,所以偏移量需要乘2关键是要理解间接寻址方式JMP指令,.datamsgdbInputnumber(18):,0dh,0ah,$msg1dbChapter1:.,0dh,0ah,$msg2dbChapter2:.,0dh,0ah,$.msg8dbChapter8:.,0dh,0ah,$tabledwdisp1,disp2,disp3,disp4dwdisp5,disp6,disp7,disp8;取得各个标号的偏移地址,例4.4数据段1/3,start1:movdx,offsetmsg;提示输入数字movah,9int21hmovah,1;等待按键int21hcmpal,1;数字8?jastart1andax,000fh;将ASCII码转换成数字,例4.4代码段2/3,decaxshlax,1;等效于addax,axmovbx,axjmptablebx;(段内)间接转移:IPtable+bxstart2:movah,9int21h.exit0disp1:movdx,offsetmsg1;处理程序1jmpstart2.,例4.4代码段3/3,4.3循环程序设计,循环结构一般是根据某一条件判断为真或假来确定是否重复执行循环体循环指令和转移指令可以实现循环控制;还可以采用MASM6.x提供的循环控制伪指令实现,循环指令LOOPE:例4.6,转移指令:例4.7,多重循环:例4.8等,循环指令LOOP:例4.5等,循环结构,.modelsmall.stack.datasumdw?.code.startupxorax,ax;被加数AX清0movcx,100again:addax,cx;从100,99,.,2,1倒序累加loopagainmovsum,ax;将累加和送入指定单元.exit0end,例4.5求和,计数控制循环循环次数固定,;用二进制显示从键盘输入的一个字符的ASCII码movah,1;从键盘输入一个字符int21hmovbl,al;BLAL字符的ASCII码;DOS功能会改变AL内容,故字符ASCII码存入BLmovah,2movdl,:;显示一个分号,用于分隔int21h,习题4.161/2,movcx,8;CX8(循环次数)again:shlbl,1;左移进CF,从高位开始显示movdl,0;MOV指令不改变CFadcdl,30h;DL030HCF;CF若是0,则DL0;若是1,则DL1movah,2int21h;显示loopagain;CX减1,如果CX未减至0,则循环,习题4.162/2,计数控制循环循环次数固定,.startupmovax,wordX;测试目标送AXmovcx,16;循环计数器置初值movdl,-1;计位器置初值again:incdltestax,1rorax,1;循环指令不影响ZFloopeagain;CX0且ZF=1(测试位为0),继续循环jenotfoundmovbyteY,dljmpdonenotfound:movbyteY,-1;ZF=1,16个位均为0done:.exit0,例4.6,计数控制循环最大循环次数固定,满足条件退出,movbx,offsetstringagain:moval,bx;取一个字符oral,al;是否为结尾符0jzdone;是,退出循环cmpal,A;是否为大写AZjbnextcmpal,Zjanextoral,20h;是,转换为小写字母(使D5=1)movbx,al;仍保存在原位置next:incbxjmpagain;继续循环done:.exit0,例4.7大小写,条件控制循环利用标志退出,冒泡法,“冒泡法”是一种排序算法,不是最优的算法,但它易于理解和实现冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不大于后一个元素;将所有元素比较完之后,最大的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次大的元素排在后面;如此重复,直至完成就实现元素从小到大的排序这需要一个双重循环程序结构,图示,冒泡法的排序过程,movcx,count;CX数组元素个数deccx;元素个数减1为外循环次数outlp:movdx,cx;DX内循环次数movbx,offsetarrayinlp:moval,bx;取前一个元素cmpal,bx+1;与后一个元素比较jnanext;前一个不大于后一个元素,则不进行交换xchgal,bx+1;否则,进行交换movbx,alnext:incbx;下一对元素decdxjnzinlp;内循环尾loopoutlp;外循环尾,例4.8,计数控制双重循环,;现有一个以$结尾的字符串,要求剔除其中的空格.datastringdbLetushaveatry!,$.code.startupmovsi,offsetstringoutlp:cmpbyteptrdi,$;外循环,先判断后循环jzdone;为$结束cmpbyteptrsi,;检测是否是空格jnznext;不是空格继续循环,例4.9剔除空格1/2,movdi,si;是空格,进入剔除空格分支;该分支是循环程序段inlp:incdimoval,di;前移一个位置movdi-1,alcmpbyteptrdi,$;内循环,先循环后判断jnzinlpjmpoutlpnext:incsi;继续对后续字符进行处理jmpoutlpdone:.exit0;结束,例4.9剔除空格2/2,条件控制双重循环,4.4子程序设计,把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序子程序可以实现源程序的模块化,可简化源程序结构,可以提高编程效率,子程序设计要利用过程定义伪指令,参数传递是子程序设计的重点和难点,子程序可以嵌套;一定条件下,还可以递归和重入,4.4.1程序定义伪指令,过程名procnear|far.过程名endp,过程名(子程序名)为符合语法的标识符NEAR属性(段内近调用)的过程只能被相同代码段的其他程序调用FAR属性(段间远调用)的过程可以被相同或不同代码段的程序调用对简化段定义格式,在微型、小型和紧凑存储模式下,过程的缺省属性为near;在中型、大型和巨型存储模式下,过程的缺省属性为far对完整段定义格式,过程的缺省属性为near用户可以在过程定义时用near或far改变缺省属性,子程序的常见格式,subnameproc;具有缺省属性的subname过程pushax;保护寄存器:顺序压入堆栈pushbx;ax/bx/cx仅是示例pushcx;过程体popcx;恢复寄存器:逆序弹出堆栈popbxpopaxret;过程返回subnameendp;过程结束,;子程序功能:实现光标回车换行dpcrlfproc;过程开始pushax;保护寄存器AX和DXpushdxmovdl,0dh;显示回车movah,2int21hmovdl,0ah;显示换行movah,2int21hpopdx;恢复寄存器DX和AXpopaxret;子程序返回dpcrlfendp;过程结束,例题无参数传递的子程序,ALdispproc;实现al内容的显示pushax;过程中使用了AX、CX和DXpushcxpushdxpushax;暂存axmovdl,al;转换al的高4位movcl,4shrdl,clordl,30h;al高4位变成3cmpdl,39hjbealdisp1adddl,7;是0Ah0Fh,还要加上7aldisp1:movah,2;显示int21h,例4.10子程序1/3,popdx;恢复原ax值到dxanddl,0fh;转换al的低4位ordl,30hcmpdl,39hjbealdisp2adddl,7aldisp2:movah,2;显示int21hpopdxpopcxpopaxret;过程返回ALdispendp,例4.10子程序2/3,.;主程序,同例4.8源程序movbx,offsetarray;调用程序段开始movcx,countdisplp:moval,bxcallALdisp;调用显示过程movdl,;显示一个逗号,分隔数据movah,2int21hincbxloopdisplp;调用程序段结束.exit0.;过程定义end,例4.10主程序3/3,HTOASCproc;将AL低4位表达的一位16进制数转换为ASCII码andal,0fhcmpal,9jbehtoasc1addal,37h;是0AH0FH,加37Hret;子程序返回htoasc1:addal,30h;是09,加30Hret;子程序返回HTOASCendp,例题具有多个出口的子程序,2019/12/14,47,可编辑,4.4.2子程序的参数传递,入口参数(输入参数):主程序提供给子程序出口参数(输出参数):子程序返回给主程序参数的形式:数据本身(传值)数据的地址(传址)传递的方法:寄存器变量堆栈,例4.11求校验和,子程序计算数组元素的“校验和”校验和是指不记进位的累加入口参数:数组的逻辑地址(传址)元素个数(传值)出口参数:求和结果(传值),把参数存于约定的寄存器中,可以传值,也可以传址。子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)子程序对带有入口参数的寄存器可以保护,也可以不保护;但最好一致例4.11a入口参数:CX元素个数,DS:BX数组的段地址:偏移地址出口参数:AL校验和,用寄存器传递参数,.startup;设置入口参数(含有DS数组的段地址)movbx,offsetarray;BX数组的偏移地址movcx,count;CX数组的元素个数callchecksuma;调用求和过程movresult,al;处理出口参数.exit0,例4.11a主程序,checksumaprocxoral,al;累加器清0suma:addal,bx;求和incbx;指向下一个字节loopsumaretchecksumaendpend,例4.11a子程序,主程序和子程序直接采用同一个变量名共享同一个变量,实现参数的传递不通模块间共享时,需要声明例4.11b入口参数:count元素个数,array数组名(含段地址:偏移地址)出口参数:result校验和,用变量传递参数,;主程序callchecksumb;子程序checksumbprocpushaxpushbxpushcxxoral,al;累加器清0movbx,offsetarray;BX数组的偏移地址movcx,count;CX数组的元素个数,例4.11b1/2,sumb:addal,bx;求和incbxloopsumbmovresult,al;保存校验和popcxpopbxpopaxretchecksumbendp,例4.11b2/2,主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数子程序将出口参数压入堆栈,主程序弹出堆栈取得它们例4.11c入口参数:顺序压入偏移地址和元素个数出口参数:AL校验和,用堆栈传递参数,.startupmovax,offsetarraypushaxmovax,countpushaxcallchecksumcaddsp,4movresult,al.exit0,例4.11c主程序,图示,要注意堆栈的分配情况,保证参数存取正确、子程序正确返回,并保持堆栈平衡,checksumcprocpushbpmovbp,sp;利用BP间接寻址存取参数pushbxpushcxmovbx,bp+6;SS:BP+6指向偏移地址movcx,bp+4;SS:BP+6指向元素个数xoral,alsumc:addal,bxincbxloopsumcpopcxpopbxpopbpretchecksumcendp,例4.11c子程序,图示,堆栈区及参数,主程序实现平衡堆栈:addsp,n子程序实现平衡堆栈:retn,子程序的嵌套,子程序内包含有子程序的调用就是子程序嵌套没有什么特殊要求,ALdispprocpushaxpushcx;实现al内容的显示pushax;暂存axmovcl,4shral,cl;转换al的高4位callhtoasc;子程序调用(嵌套)popax;转换al的低4位callhtoasc;子程序调用(嵌套)popcxpopaxretALdispendp,例4.10嵌套子程序1/3,;将AL低4位表达的一位16进制数转换为ASCII码HTOASCprocpushaxpushbxpushdxmovbx,offsetASCII;BX指向ASCII码表andal,0fh;取得一位16进制数xlatCS:ASCII;换码:ALCS:BXAL,注意数据在代码段CS,例4.10嵌套子程序2/3,movdl,al;显示movah,2int21hpopdxpopbxpopaxret;子程序返回;子程序的数据区ASCIIdb30h,31h,32h,33h,34h,35h,36h,37hdb38h,39h,41h,42h,43h,44h,45h,46hHTOASCendp,例4.10嵌套子程序3/3,这是一个具有局部变量的子程序。因为数据区与子程序都在代码段,所以利用了换码指令XLAT的另一种助记格式(写出指向缓冲区的变量名,目的是便于指明段超越前缀)。串操作MOVS、LODS和CMPS指令也可以这样使用,以便使用段超越前缀除采用段超越方法外,子程序与主程序的数据段不同时,我们还可以通过修改DS值实现数据存取;但需要保护和恢复DS寄存器,子程序的递归,当子程序直接或间接地嵌套调用自身时称为递归调用,含有递归调用的子程序称为递归子程序递归子程序必须采用寄存器或堆栈传递参数,递归深度受堆栈空间的限制例4.12:求阶乘,.modelsmall.stack256.dataNdw3resultdw?.code.startupmovbx,Npushbx;入口参数:Ncallfact;调用递归子程序popresult;出口参数:N!.exit0,例4.12主程序1/3,图示,;计算N!的近过程;入口参数:压入N;出口参数:弹出N!factprocpushaxpushbpmovbp,spmovax,bp+6;取入口参数Ncmpax,0jnefact1;N0,N!N(N-1)!incax;N0,N!1jmpfact2,例4.12递归子程序2/3,图示,fact1:decax;N-1pushaxcallfact;调用递归子程序求(N-1)!popaxmulwordptrbp+6;求N(N-1)!fact2:movbp+6,ax;存入出口参数N!popbppopaxretfactendp,例4.12递归子程序3/3,图示,递归子程序,调用时进栈,返回时出栈,1,3!,2!,1!,子程序的重入,子程序的重入是指子程序被中断后又被中断服务程序所调用,能够重入的子程序称为可重入子程序。在子程序中,注意利用寄存器和堆栈传递参数和存放临时数据,而不要使用固定的存储单元(变量),就能够实现重入。子程序的重入不同于子程序的递归。重入是被动地进入,而递归是主动地进入;重入的调用间往往没有关系,而递归的调用间却是密切相关的。递归子程序也是可重入子程序。,例题4.13:从键盘输入有符号十进制数,子程序从键盘输入一个有符号十进制数;子程序还包含将ASCII码转换为二进制数的过程输入时,负数用“”引导,正数直接输入或用“”引导子程序用寄存器传递出口参数,主程序调用该子程序输入10个数据,转换算法,.datacount=10arraydwcountdup(0);预留数据存储空间.code.startupmovcx,countmovbx,offsetarrayagain:callread;调用子程序输入一个数据movbx,ax;将出口参数存放缓冲区incbxincbxcalldpcrlf;调用子程序,光标回车换行以便输入下一个数据loopagain.exit0,例题4.131/5,;输入有符号10进制数的通用子程序;出口参数:AX补码表示的二进制数值;说明:负数用“”引导,正数用“”引导或直接输入;数据范围是3276732768readprocpushbxpushcxpushdxxorbx,bx;BX保存结果xorcx,cx;CX为正负标志,0为正,1为负movah,1;输入一个字符int21h,例题4.132/5,cmpal,+;是“”,继续输入字符jzread1cmpal,-;是“”,设置1标志jnzread2;非“”和“”,转read2movcx,-1read1:movah,1;继续输入字符int21hread2:cmpal,0;不是09之间的字符,则输入数据结束jbread3cmpal,9jaread3,例题4.133/5,转换算法,subal,30h;是09之间的字符,则转换为二进制数;利用移位指令,实现数值乘10:BXBX10shlbx,1movdx,bxshlbx,1shlbx,1addbx,dx;movah,0addbx,ax;已输入数值乘10后,与新输入数值相加jmpread1;继续输入字符,例题4.134/5,转换算法,read3:cmpcx,0jzread4negbx;是负数,进行求补read4:movax,bx;设置出口参数popdxpopcxpopbxret;子程序返回readendp;使光标回车换行的子程序dpcrlfproc.;省略dpcrlfendpend,例题4.135/5,ASCII码转换为二进制数,首先判断输入为正或负数,并用一个寄存器记录接着输入09数字(ASCII码),并减30H转换为二进制数然后将前面输入的数值乘10,并与刚输入的数字相加得到新的数值重复、步,直到输入一个非数字字符结束负数进行求补,转换成补码;否则直接保存数值本例采用16位寄存器表达数据,所以只能输入32767732768间的数值但该算法适合更大范围的数据,例题4.14:显示有符号十进制数,子程序在屏幕上显示一个有符号十进制数;子程序还包含将二进制数转换为ASCII码的过程显示时,负数用“”引导,正数直接输出、没有前导字符子程序的入口参数用共享变量传递,主程序调用该子程序显示10个数据,转换算法,.datacount=10arraydw1234,-1234,0,1,-1,32767dw-32768,5678,-5678,9000wtempdw?;共享变量.code.startupmovcx,countmovbx,offsetarrayagain:movax,bxmovwtemp,ax;将入口参数存入共享变量callwrite;调用子程序显示一个数据incbxincbxcalldpcrlf;便于显示下一个数据loopagain.exit0,例题4.141/5,;显示有符号10进制数的通用子程序;入口参数:共享变量wtempwriteprocpushaxpushbxpushdxmovax,wtemp;取出显示数据testax,ax;判断零、正数或负数jnzwrite1movdl,0;是零,显示“0”后退出movah,2int21hjmpwrite5,例题4.142/5,write1:jnswrite2;是负数,显示“”movbx,ax;AX数据暂存于BXmovdl,-movah,2int21hmovax,bxnegax;数据求补(求绝对值)write2:movbx,10pushbx;10压入堆栈,作为退出标志,例题4.143/5,转换算法,write3:cmpax,0;数据(余数)为零jzwrite4;转向显示subdx,dx;扩展被除数DX.AXdivbx;数据除以10:DX.AX10adddl,30h;余数(09)转换为ASCII码pushdx;数据各位先低位后高位压入堆栈jmpwrite3write4:popdx;数据各位先高位后低位弹出堆栈cmpdl,10;是结束标志10,则退出jewrite5,例题4.144/5,转换算法,movah,2;进行显示int21hjmpwrite4write5:popdxpopbxpopaxret;子程序返回writeendp;使光标回车换行的子程序dpcrlfproc.;省略dpcrlfendpend,例题4.145/5,二进制数转换为ASCII码,首先判断数据是零、正数或负数,是零显示“0”退出是负数,显示“”,求数据的绝对值;接着数据除以10,余数加30H转换为ASCII码压入堆栈重复步,直到余数为0结束依次从堆栈弹

温馨提示

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

评论

0/150

提交评论