【文档说明】IBM-PC汇编语言程序设计5课件.ppt,共(42)页,237.001 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44739.html
以下为本文档部分文字说明:
第五章循环与分支程序设计5.1循环程序设计5.2分支程序设计5.3如何在实模式下发挥80386及其后继机型的优势1.编写汇编语言程序步骤l分析实际问题,确定解决问题的算法l按算法画出程序流程图l按流程图编写程序l上机调试,运行程序注:本教材所讨
论的编程环境只限于在DOS操作系统下的实模式2.判断程序质量的标准l程序的正确性l程序的可读性l程序的执行时间l程序所占内存大小3.几种程序结构l顺序结构l循环结构l分支结构l子程序结构顺序结构形式循环结构形式当型循环(当条件
成立进入循环)循环初始设置循环体循环条件判断?YN直到型循环(直到条件成立退出循环)YN循环初始设置循环体循环条件判断?两个分支YN、、、CMPAL,BLJGgreatJMPexitgreat:exit:、、、、、、AL≤BL处理AL>BL处理分支结构形式三个分支、、
、CMPAL,0JGgreatJLlessJMPexitless:JMPexitgreat:exit:、、、AL=0处理AL>0处理AL<0处理YYNN分支结构形式……1.多处调用完成同一功能的子程:codeSEGMENTstart:、、CALLsubp、、CALLsubp、、C
ALLsubp、、MOVAH,4CHINT21HsubpPROC、、、、RETsubpENDPcodeENDSENDstart2.模块化程序设计:codeSEGMENTbegin:CALLsub1CALLsub2CALLsub3MOVAH,4CHIN
T21Hsub1PROC、、RETsub1ENDPsub2PROC、、RETsub2ENDPsub3PROC、、RETsub3ENDPcodeENDSENDbegin子程结构形式注意返回DOS语句位置开始结束初始化循环的初始状态循环体循环的工作部分及修改部分控制条件计数
控制特征值控制地址边界控制5.1.1循环程序的结构形式5.1循环程序设计(1)DO-WHILE结构(2)DO-UNTIL结构▲有关字符、数码转换的处理1.计算机处理字符时,常用的字符编码是ASCII码。2.数字和字母的ASCII码是一个有序序列数字0~9:30H~39H大写字母A~
Z:41H~5AH小写字母a~z:61H~7AH5.1.2循环程序设计方法例5.1将寄存器BX中的内容以十六进制形式显示出来。▲BX是一个16位寄存器二进制1010100100111110▲用十六进显示时,每4
位用一个字符显示,共4个其中:0000→’0’30H,1010→’A’41H0001→’1’31H,1011→’B’42H、、、、1001→’9’39H,1111→’F’46H?十六进制A93E屏幕上的显示‘A’‘9’‘3’‘E’对应的AS
CII41H39H33H45HBX1234算法:取出要显示的某4位,转换为对应的ASCII码,再调用DOS系统功能进行显示。(1)对于0000~1001(0~9),先扩展成一个字节,高4位清0,加上30H后,即可得字符’0’~’9’对应的ASCII码。00000001B+30H=31H000010
01B+30H=39H0001B‘1’1001B‘9’(2)对于1010~1111(A~F),先扩展成一个字节,高4位清0,加上30H后,还要再加上07H,才能得到’A’~’F’对应的ASCII码00
001010B+30H+07H=41H00001111B+30H+07H=46H1010B‘A’1111B‘F’codeSEGMENTASSUMECS:codestart:MOVCH,4;字符个数rot
ate:MOVCL,4;循环移位次数ROLBX,CL;取显示位的值MOVAL,BL;保存在AL中ANDAL,0FH;清除高4位ADDAL,30H;转变为数字的ASCIICMPAL,3aH;大于3aH,则应转变JLprint;为数字0~9
的ASCIIADDAL,07H;为字母A~F的ASCIIprint:MOVDL,AL;送ASCII字符到DLMOVAH,2;显示DL中的字符INT21HDECCH;显示结束?JNZnextMOVAH,
4CH;返回DOSINT21HcodeENDSENDstart显示字符个数CH=4循环移位次数CL=4BX循环左移4位,将要显示的值移至低4位,保存在AL中清AL的高4位,只保留要显示位的值AL←AL+30H完成数值0~9的ASCII码转换YNAL←AL+07H完成数值A~F的ASCII码转换用
02功能显示DL中的字符YN返回DOSAL超出39H?CH←CH-1转换结束?开始例5.2在ADDR单元中存放着数Y,度编制一程序把Y中1的个数存入COUNT单元中。datareasegmentaddredw1234hcountd
w?datareaendsmovcx,0movbx,addremovax,bxagain:testax,0ffffhjzexitjnsshiftinccxshift:shlax,1jmpagainexit:movcount,cx
ret例5.4将正数n插入一个已整序的字数组的正确位置。xdw?array_headdw3,5,15,23,37,49,52,65,78,99array_enddw105ndw32movax,nmovarray_head-2,0ffffhmovsi,0compare:cmparray_end[s
i],axjleinsertmovbx,array_end[si]movarray_end[si+2],bxsubsi,2jmpshortcompareinsert:movarray_end[si+2],ax-135491552233710599
786532xn例5.5Zi=Xi+YiLOGIC_RULEDW00DCH……MOVBX,0MOVCX,10MOVDX,LOGIC_RULENEXT:MOVAX,X[BX]SHRDX,1JCSUBTRACTADDAX,Y[BX]
JMPSHORTRESULTSUBTRACT:SUBAX,Y[BX]RESULT:MOVZ[BX],AXADDBX,2LOOPNEXTRET……例5.6键入一行以空格开头以空格结束的字符串datareasegmentbufferdb80dup(?)flagdb?dat
areaendsleabx,buffermovflag,0next:movah,01;读键盘int21h;所读内容放入altestflag,01h;flag=1?jnzfollow;flag=0,zf=1不
转cmpal,20h;al是空格?jnzexit;不是,zf=0退出movflag,1;置标志flag=1jmpnextfollow:cmpal,20h;al是空格?jzexit;是,zf=1,退出mo
v[bx],al;不是,保存incbx;数组索引加1jmpnextexit:20abcdef20flag=01jzexit成立5.1.3多重循环程序设计基本方法与单重循环相同,但要注意:1、分别考虑各重循环的控制条件及其程
序实现,相互之间不能混淆2、每次从外层循环再次进入内层循环时,初始条件要重新设置例5.7将首地址为a的字数组从大到小排序(气泡算法,多重循环)adw100,30,78,99,15,-1,66,54,189,256movcx,10;待排序数的个数deccx;外循环的次数loo
p1:movdi,cx;暂存外循环次数movbx,0;数组下标loop2:movax,a[bx];取第bx个数cmpax,a[bx+2];与后一个数比较jgecontinue;[bx]>=[bx+2]xchgax,a[bx+2];<,则交换位置mova
[bx],axcontinue:addbx,2;指向下一个数looploop2movcx,di;恢复外循环次数looploop1例5.8附加段字数组首地址存于DI,第1字存放长度,从小到大排序extrasegmentadw10,10h,12h,32h,21h,11h,56
h,43h,33h,3h,67hextraendsdatasegmentstart_addrdw?save_cntdw?dataendsleadi,a;取有效地址movstart_addr,dimovcx,es:[di];取长
度movsave_cnt,cx;数组长度init:movbx,1;结束标志decsave_cntjzsorted;zf=1,转移movcx,save_cntmovdi,start_addrnext:adddi,2movax,es:[di];取数cm
pes:[di+2],ax;比较jaecont;>=,转移,不换xchges:[di+2],axmoves:[di],axsubbx,bx;排序标志cont:loopnextcmpbx,0;bx=1,已排好je
initsorted:movdi,start_addr练习5.11:从键盘输入一系列以$结束的字符串,统计数字字符的个数datasegmentcountdw0buffdb50dup(?)dataendsprogna
msegmentmainprocfarassumecs:prognamstart:pushdssubax,axpushaxmovax,datamovds,axleabx,buff;取缓冲地址input:movah,01;从键盘读串int21
H;存入al中mov[bx],al;保存字符incbx;buff数组下标cmpal,‘$‘;是不是$jnzinput;是,结束读leabx,buff;取串地址movax,0next:movcl,[bx];取串中字符incbx;指向下一字符cmp
cl,‘$’;是不是$jzdisp;是,zf=1,转移cmpcl,30h;与’0’比较jbcont;<‘0’,不计数cmpcl,39h;与’9’比较jnbenext;>’9’,不计数incax;计数cont:jmpn
extdisp:retmainendpprognamendsendstart练习5.11:测试一字符串是否存在数字,若存在,置CL第5位置1,否则置0datasegmentstringdb'abcqdefghijklmnopqrs'dataendsprognamsegmentmainprocfar
assumecs:prognam,ds:data,es:datastart:pushdssubax,axpushaxmovax,datamovds,axmoves,axbegin:movcx,20;字符个数movsi,0;数组下标aga
in:moval,string[si]cmpal,30h;与’0’比较jbgoon;<,转移cmpal,39h;与‘9’比较jagoon;>,转移orcl,20h;有数字,置5位jmpexitgoon:incsi;数组下标加1loop
againandcl,0dfh;无数字,清5位exit:retmainendpprognamendsendstart循环程序设计小结1、循环控制条件的选择:a.循环次数已知,采用LOOPb.循环次数已知,但有可能使用其他
特征或条件结束循环,可采用LOOPZ和LOOPNZc.循环次数未知,具体问题具体分析2、设立条件标志位的方法5.2分支程序设计5.2.1分支程序的结构形式双分支与多分支的共同特点:运行方向是向前的在某一种特定条件下,只能执行其中的一个分支5.2.1分支程序设计
方法1、使用CMP、TEST等运算型指令+条件转移指令2、使用逻辑尺的方法3、使用跳跃表法实现CASE结构例5.9折半查找:附加段有一个有序字数组,首字表示数组长度,AX是待查字,若找到CF=0,否则CF=1ds
egsegmentlow_idxdw?high_idxdw?listdw12,11,22,33,44,55,66,77,88,99,111,222,333targetdw77dsegendscsegsegmentmainprocfa
rassumecs:cseg,ds:dseg,es:dsegstart:pushdssubax,axpushaxmovax,dsegmovds,axmoves,ax例5.9折半查找:附加段有一个有序字数组,首字
表示数组长度,AX是待查字,若找到CF=0,否则CF=1movax,target;leadi,list;取数组首地址cmpax,es:[di+2];取第1个数jachk_last;>第1个,检查最后1个leasi,es:[
di+2];<=第1个jeexit;=,退出stc;CF=1,没找到jmpexitchk_last:movsi,es:[di];下面三条使SI指向shlsi,1;数组末元素addsi,dicmpax,es:[si];与末元素比较jbs
earch;<,搜索数组jeexit;=,退出stc;CF=1,没找到jmpexit0400list100102104106108例5.9折半查找:附加段有一个有序字数组,首字表示数组长度,AX是待查字,若找到CF=0,否则CF=1search:movlow_idx,1;搜索开始的地方movbx,
es:[di];数组长度movhigh_idx,bx;搜索结束的地方movbx,di;list地址mid:movcx,low_idx;movdx,high_idx;cmpcx,dx;比较’头’与’末’指针jano_match;>,’头’到’末’之后addcx,dx;以下三条计算shrcx,1;’
头’与’末’的中点movsi,cxhli1对准中间’字’0500100102104106108list10A(1+5)/2=33*2=6DI偏移6,即106,即第3字compare:cmpax,es:[bx+s
i];比较,bx指向数组首元素jeexit;=,找到,退出jahighter;>,调节搜索’头’deccx;<=movhigh_idx,cx;调节搜索’末’jmpmidhighter:inccxmovlow_idx,cx;调节搜索’头’jmpmidno_match:
stcexit:ret例5.9折半查找:附加段有一个有序字数组,首字表示数组长度,AX是待查字,若找到CF=0,否则CF=1例5.10根据AL寄存器中哪一位为1(从低位到高位)把程序转移到8个不同的程序分支去。branch_tabledwroutine1dwroutine2
dwroutine3dwroutine4dwroutine5dwroutine6dwroutine7dwroutine8注意:DW标号的使用寄存器间接寻址cmpal,0jecontinueleabx,branch_tab
leL:shral,1;逻辑右移,最低位进入CF位jnbnot_yet;jnb=jnc,CF=0,转移jmpwordptr[bx];段内间接转移not_yet:addbx,typebranch_tablejmpLcontinue:……routine1:……routine
2:…………调试源程序变址寻址方式实现cmpal,0jecontinuemovsi,0L:shral,1;逻辑右移,最低位进入CF位jnbnot_yet;jnb=jnc,CF=0,转移jmpbranch_table[si];段内间接转移not_yet:addsi,t
ypebranch_tablejmpLcontinue:……routine1:……routine2:…………调试源程序基址变址寻址cmpal,0jecontinueleabx,branch_tablemovsi,7*t
ypebranch_tablemovcx,8L:shlal,1;逻辑左移,最高位进入CF位jnbnot_yet;jnb=jnc,CF=0,转移jmpwordptr[bx][si];段内间接转移not_yet:subsi,typebranch_tableloopLcontinu
e:……routine1:……routine2:…………调试源程序习题5.21试写一程序,要求比较数组ARRAY中的三个16位补码数,并根据比较结果在终端上显示如下信息:(1)如果三个数都不相等,则显示0(2)如果有两个相等则显示1
(3)如果都相等,则显示2dsegsegmentarraydw3dup(?)dsegendscsegsegment……movcx,3leasi,arraybegin:pushcxmovcl,4movdi,4movdl,
’‘movah,02int21hinput:movah,01hint21handal,0fhshldx,clordl,aldecdijneinputmov[si],dxaddsi,2popcxloopbegincompa:leasi,arraymovdx,0movax,[si]movbx,
[si+2]cmpax,bxjnenext1incdxnext1:cmp[si+4],axjnenext2incdxnext2:cmp[si+4],bxjnenumincdxnum:cmpdx,3jldispdecdxdisp:movah,2addd
l,30hint21hmainendpcsegendsendstart习题5.23已定义整型变量A、B(1)若只有一个奇数,奇数存入A,偶数存入B(2)若两个奇数,A=A+1B=B+1(3)若两个偶数,A、B值不变begin:movax,amovbx,bxora
x,bxtestax,1hjzclass;同奇同偶,转移textbx,1hjzexitxchgbx,amovb,bxjmpexitclass:testbx,1hjzexit;若同偶,退出incbincaexit:ret5.3
如何在实模式下发挥80386及其后继机型的优势80386及其后继机型不但兼容8086的程序,运行速度更快;而且还有其它的一些优势:5.3.1充分利用高档机的32位字长特征5.3.2通用寄存器可作为指针寄存器5.3.3与比例因子有关的寻址方式调试源程序例5.11通用寄存器作指针寄存器
8个32位通用寄存器都可以作为基址或变址寄存器使用,但注意它们的高16位应为0。32位字长特征计算机一次能够处理32位的数据,可以访问32位的8个通用寄存器,但EIP和EFLAGS在实模式下只有低16位可以使用。比例因子
方便了表格处理和多位数组处理实模式段的大小限于64K实模式下的程序是一种混合的16位和32位代码纯16位模块(1)所有段长都小于64KB;(2)数据项主要是8位或16位的(3)指向代码或数据的指针只有16位偏移地址(4)只有16位段之间传送控制
纯32模块(1)段长可大于64KB(0-4GB);(2)数据项主要是8位或32位的(3)指向代码或数据的指针有32位偏移地址(4)只有32位段之间传送控制8086/80286实模式80386+保护模式386+实模式下的程序(1)在同一模块中,允许同时使用16位和32位的
操作数和寻址方式(2)段必须实16位的,但段中的指令可以是混合的16位和32位代码奔腾4第五章作业Page193~1955.105.21