第5章汇编语言程序设计_第1页
第5章汇编语言程序设计_第2页
第5章汇编语言程序设计_第3页
第5章汇编语言程序设计_第4页
第5章汇编语言程序设计_第5页
已阅读5页,还剩48页未读 继续免费阅读

下载本文档

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

文档简介

1、第第5章章 汇编语言程序设计汇编语言程序设计主要内容主要内容l顺序、分支、循环结构程序设计顺序、分支、循环结构程序设计l子程序设计子程序设计l转移指令、循环指令和子程序伪指令转移指令、循环指令和子程序伪指令教学要求教学要求l掌握:掌握:(1)分支程序的概念、结构和设计(2)循环程序的概念、结构和设计(3)子程序的概念、结构和设计l了解:了解: 转移表法和地址表法多分支程序的设计原理;多重循环程序的结构形式,内层循环与外层循环遵守的层次结构规则,参数修改对各层的相互影响;汇编递归程序方法。 编制一个汇编语言程序的步骤编制一个汇编语言程序的步骤 (1)分析题意,确定算法。(2)根据算法,确定程序流

2、程或画出程序框图。(3)根据流程或框图编写程序。(4)上机调试程序。5.1 顺序程序设计顺序程序设计l顺序结构是最简单的程序结构,程序的执行顺序就是指令的编写顺序,所以,安排指令的先后次序就显得至关重要。 【例】【例】 设置光标到屏幕左上角设置光标到屏幕左上角set_cur procmov ah,2 ;设置光标位置功能mov bh,0 ;页号mov dx,0 ;行dh,列dlint 10h ;bios输出字符中断 retset_cur endp 这个程序段是顺序执行的,一条指令执行后顺序执行紧接其后的另一条指令。【例】【例】 设在设在x单元中存放一个单元中存放一个07之间的整数,用查表法求出其

3、平之间的整数,用查表法求出其平方值,并将结果存入方值,并将结果存入y单元。单元。l分析:根据题意,首先将07所对应的平方值存入连续的8个单元中,构成一张平方值表,其首地址为sqtab。l由表的存放规律可知:表首址sqtab与x单元中的数i之和,正是i2所在单元的地址。data segment ;数据段定义sqtab db 0,1,4,9,16,25,36,49 ;平方值表x db 5y db ?data endsstack segment para stack stacktapn db 100 dup (?)top equ length tapnstack endscode segmentas

4、sume cs:code,ds:data,ss:stacksqrtsub proc farpush dssub ax,axpush axmov ax,datamov ds,axmov ax,stackmov ss,axmov al,x ;取数imov ah,0mov bx,offset sqtab ;bx表首址add bx,axmov al,bx ;取i2并保存mov y,alretsqrtsub endpcode endsend sqrtsub5.2 分支程序设计分支程序设计l分支结构是一种非常重要的程序结构,也是实现程序功能选择所必要的程序结构。l由于汇编语言需要用转移指令来实现分支结构,

5、而转移指令肯定会破坏程序的结构,所以,编写清晰的分支结构是掌握该结构的重点。l计算机可根据不同条件进行逻辑判断,从而选择不同的程序流向。程序的流向是由cs和ip值决定的,当程序的转移仅在同一段内进行时,只需修改偏移地址ip的值;如果程序的转移是在不同段之间进行的,则段基址cs和偏移地址ip的值均需要修改。 5.2.1 转移指令转移指令l转移指令是汇编程序员经常要用到的一组指令。在高级语言中,时常有“尽量不要使用转移指令语句”的劝告。但是,在汇编语言程序中,不但要使用转移指令,而且还要灵活运用,因为指令系统中有大量的转移指令。l转移指令分为无条件转移指令和有条件转移指令。 无条件转移指令无条件转

6、移指令jmp l无条件转移指令jmp指令是从程序当前执行的地方无条件地转移到另一个地方执行。 指令格式jmp 地址表达式指令功能无条件地转移到由地址表达式所确定的目标单元,本指令对标志位无影响4种方式段内直接转移段内间接转移段间直接转移段间间接转移说 明这是一种相对寻址方式。它转移的目标地址是当前ip内容加上一个8位相对位移量(disp), disp是汇编程序在汇编源程序时,根据目标地址和当前ip之间的距离自动生成的它转移的目标地址可通过寄存器或存储单元来寻址 当一条无条件转移指令中的地址表达式是一个段间(far)标号或段间标号加减一常量(必须在该标号所在段内)时,则该指令被汇编成一个段间直接

7、转移指令代码它转移的目标地址由存储器寻址方式指定的内存中的连续两个字来决定,低地址的字取代ip,高地址的字取代cs无条件转移指令无条件转移指令jmpljmp指令转移可以是短(short)转移(偏移量在-128b,127b之内)、近(near)转移(偏移量在-32kb,32kb之内)、远(far)转移(在不同的代码段之间转移)。l短转移和近转移都是段内转移,jmp指令只将目标指令位置处的偏移量赋值给指令指针寄存器ip,从而实现转移功能l远转移属于段间转移,jmp指令不仅会把目标指令位置处的偏移量赋值给指令指针寄存器,同时还会把目标指令所处的代码段的段地址赋值给当前代码段寄存器cs。 有条件转移指

8、令有条件转移指令 l有条件转移指令是一组及其重要的转移指令,它根据标志寄存器中的一个(或多个)标志位来决定是否需要转移,这就为实现多功能程序提供了必要的手段 有条件转移指令的格式和类型有条件转移指令的格式和类型 指令格式 指令说明当满足条件而发生转移的指令,称为条件转移指令。它们以某些标志位或这些标志位的逻辑运算作为依据,若满足指令所规定条件,则程序转移,否则顺序执行根据单个标志位的条件转移指令用于无符号数的条件转移指令用于带符号数的条件转移指令(1)有进位转移(jc)或无进位转移(jnc)(2)等于/为零转移(je/jz)或不等于/非零转移(jnz)(3)负数转移(js)或正数转移(jns)

9、(4)溢出转移(jo)或不溢出转移(jno)(5)偶校验转移(jp/jpe)或奇校验转移(jnp/jpo)(6)寄存器cx为零转移(jcxz) (1)高于转移(ja)/不低于且不等于转移(jnbe)(2)高于或等于转移(jae)/不低于转移(jnb)(3)低于转移(jb)/不高于且不等于转移(jnae)(4)低于或等于转移(jbe)/不高于转移(jna)(1)大于转移(jg)/不小于且不等于转移(jnle)(2)大于或等于转移(jge)/不小于转移(jnl)(3)小于转移(jl)/不大于且不等于转移(jnge)(4)低于或等于转移(jle)/不高于转移(jng)5.2.2 分支程序的结构分支程

10、序的结构l分支程序结构有两种形式:双分支结构和多分支结构。分支程序设计要点分支程序设计要点 l(1)首先根据处理的问题用比较、测试、算术运算、逻辑运算等方式,使标志寄存器产生相应的标志位。例如,比较两个单元地址的高低、两个数的大小,测试某个数据是正还是负,测试数据的某位是“0”还是“1”等,将处理的结果反映在标志寄存器的cf、zf、sf、df和of位上。l(2)根据转移条件选择适当的转移指令。通常一条条件转移指令只能产生两路分支,因此要产生n路分支需n-1条条件转移指令。l(3)各分支之间不能产生干扰,如果产生干扰,可用无条件转移语句进行隔离。【例】【例】 设有单字节无符号数设有单字节无符号数

11、x、y、z,若,若x+y255,求,求x+z;否则;否则求求x-z,运算结果放在,运算结果放在f1中(中(x、y、z、f1均为字节变量名)。均为字节变量名)。l分析:这是一个双分支结构。因为x、y均为无符号数,当x+y255时会产生进位即cf=1,所以可以用进位标志来判断 mov al,xmov bl,aladd al,yjnc let ;若无进位 则转letadd bl,z done: mov f1,blhlt let: sub bl,z jmp donel【例】 已知符号函数,假设任意给定x值,存放在内存rs1单元中,求出函数y的值,存放在内存rs2单元中。ldata segmentlrs

12、1 db x ; 存放自变量xlrs2 db ? ; 函数y值的存储单元ldata endslcode segmentlassume cs: code, ds: datalstart: mov ax, datal mov ds, axl mov al, rs1 ; alxl cmp al, 0 ; 将x与0比较l jge big ; 若x0bigl mov rs2, 0ffh ; 若x0, (rs2)-1补0ffhl jmp donelbig: je equl ; 若x0equll mov rs2, 1 ; 若x0, (rs2)1l jmp donelequl: mov rs2, 0 ; 若x

13、0, (rs2)0ldone: mov ah, 4chl int 21hlcode endslend start5.3 循环程序设计循环程序设计l在实际工作中,有时要求对某一问题进行多次重复处理,而仅仅只是初始条件不同,这种计算过程称为具有循环特征的,而循环程序设计是解决这类问题的一种行之有效的方法。循环程序是采用重复执行某一段程序来实现要求完成计算的编程方法。5.3.1 循环指令循环指令l循环语句当然可以用条件转移指令来实现,除此之外,在80 x86系统中还有专门的循环控制指令来简化循环程序的设计。循环控制指令包括重复控制指令和串操作指令。重复循环控制指令重复循环控制指令 指令名称指令名称l

14、oop指令loopz/loope指令loopnz/loopne指令jcxz指令指令功能指令功能将cx内容减1,若cx不等于0,则循环至目标地址处(即ip+disp),否则顺序执行后续指令将cx内容减1,若cx不等于0,且标志位zf=1时,才循环至目标地址处,否则顺序执行后续指令将cx内容减1,若cx不等于0,且标志位zf=0时,才循环至目标地址处,否则顺序执行后续指令这条指令是条件转移指令,经常用于重复循环控制注意:注意:在执行此类重复控制指令前必须把重复次数送入寄存器cx中。串操作指令串操作指令 l串操作指令能对存储区中一块(串)字节或字进行操作,其块的长度可达64kb。这些指令分别是:串复

15、制指令movs、串取出指令lods、串存储指令stos、串比较指令cmps和串搜索(扫描)指令scas。 循环程序的结构循环程序的结构 循环程序一般包括以下5个部分:(1)初始化部分:)初始化部分:为循环做准备工作,如设置地址指针、计数器及其他变量的初值等。(2)循环工作部分:)循环工作部分:它是循环程序的主体,用来完成循环的基本操作。(3)修改部分:)修改部分:为循环参数做必要的修改,如修改操作数地址、计数器,为下一次执行循环体做好准备。(4)控制部分:)控制部分:根据循环条件来判断、控制循环的继续和终止。(5)结束部分:)结束部分:主要是对循环的结果进行必要的处理,如将结果送入某一寄存器或

16、内存区域。循环程序的结构循环程序的结构 常见的循环程序结构有两种形式:“先处理后判断”和“先判断后处理” 【例】【例】 计算计算 。假设这。假设这10个已知数为字类型,已连续存放在内个已知数为字类型,已连续存放在内存中以存中以aa为首址的存储区域中,其相加的和仍为字数据,存放在为首址的存储区域中,其相加的和仍为字数据,存放在bb字单元。字单元。 l分析:求a1+a2+a10的和,要用10条加法指令来完成,这样程序太长,书写麻烦。由于数据是有规律存放的,并且每加一项所用的指令都一样,只是数据的地址不同,所以可用间接寻址的方法,将数据地址放在寄存器中,用寄存器加1指令修改地址来取得每个待加的数据,

17、将相加的程序作为一个公共执行的程序段,重复执行10次来实现本题的累加过程 101iiyadata segment ;定义数据aa dw 100h,200h,300h,400h,500h,600h,700h,800h,900h,1000hbb db 4 dup(?)mes1 db aa: 100h, 200h, 300h, 400h, 500h, 600h, 700h, 800h, 900h,1000h, 0dh, 0ah, $mes2 db bb:,0dh,0ah,$data endscode segmentassume cs:code, ds:datastart: mov ax,data m

18、ov ds,ax mov dx,offset mes1 mov ah,09h int 21h mov dx,offset mes2 mov ah,09h int 21h mov ax, 0 ; 累加器ax清0 mov cx, 10 ; 设置计数器初始值 mov bx, offset aa ; bx数据首地址 mov di, offset bb ; di存放结果地址lop: add ax, bx ; 累加一个数据 inc bx ; 修改地址指针指向下一个数据 inc bx loop lop ; cx-10,继续循环累加mov bx,ax lea di,bb call disp mov ah,4c

19、h int 21hdisp proc near ;输出 mov ch,4conv: mov cl,4 rol bx,cl mov al,bl and al,0fh cmp al,09h jle asci add al,37h jmp doneasci: add al,30hdone: mov di,al inc di dec ch jnz conv mov cx,4 lea di,bbdis: mov dl,di mov ah,02h int 21h inc di loop dis retdisp endp hltcode ends end start【例】 设有两个字数组xx和yy,各包含1

20、0个元素x0 x9及y0y9,试编制程序计算:z0 x0y0 z5x5y5z1x1y1 z6x6y6z2x2y2 z7x7y7z3x3y3 z8x8y8z4x4y4 z9x9y9并将运算结果存入zz数组。l分析:这是个循环次数已知的过程,每循环一次,由xx和yy数组各取一个数据进行相应的运算,并将运算结果存入zz数组。由于每次循环所做的运算不同,有加法也有减法,就必须建立一个标志位,若为“0”做加法,为“1”则做减法,这样一来,只要判断标志位就可确定本次循环该做什么操作了。另外,题目要求进行10次运算,应该建立10个标志位,并存放在一个存储单元中,称为逻辑尺。根据z0z9的运算类型,设定逻辑尺

21、如下: 0000000011011100 其中,最末位的状态对应z0的操作,应做加法,其余位依次类推,最高的6位无意义。5.4 子程序设计子程序设计l为了程序共享或模块化设计的需要,把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序。l子程序可以实现源程序的模块化,简化源程序结构,提高编程效率。5.4.1 子程序概念子程序概念l子程序又称过程,相当于高级语言中的过程和函数。在一个程序的不同部分,往往要用到“类似”的程序段,即这些程序段的功能和结构形式都相同,只是某些变量赋值不同。此时就可以把这些程序段写成子程序形式,以便需要时调用它。子程序伪指令子程序伪指令

22、l子程序的相关伪指令包括子程序的定义指令、调用指令和返回指令等 子程序定义指令子程序定义指令 子程序就是过程。过程定义伪指令的格式如下: proc 类型属性类型属性 ret endp过程和主程序在同一代码段时,过程定义和调用格式如下:code segment subt proc near ret subt endp call subt code ends当过程和主程序不在同一代码段时,过程定义和调用格式如下:code1 segment subt proc far retsubt endp call subtcode1 endscode2 segment call subt code2 ends

23、子程序调用指令子程序调用指令call lcall指令用在主程序中,实现子程序的调用。子程序和主程序可以在同一个代码段内,也可以在不同段内。类似无条件转移指令jmp,子程序调用指令call也可以分成段内调用(近调用)和段间调用(远调用)lcall目标地址也可以采用直接寻址或间接寻址方式。但是子程序执行结束后是要返回的,所以,call指令不仅要同jmp指令一样改变cs:ip以实现转移,而且还要保留下一条要执行指令的地址,以便返回时重新获取它。保护cs:ip值的方法是压入堆栈,获取cs:ip值的方法就是弹出堆栈。 call 指令的指令的4种格式种格式(1)call label。段内调用,直接寻址:s

24、psp-2,ss:spip,ipip+16位位移量。(2)call reg16/mem16。段内调用,间接寻址:spsp-2, ss:spip, ipreg16/mem16。(3)call far ptr label。段间调用,直接寻址:spsp-2, ss:spcs, spsp-2,ss:spip,iplabel偏移地址,cslabel段地址。(4)call far ptr mem。段间调用,间接寻址:spsp-2, ss:spcs, spsp-2,ss:spip,ipmem,csmem+2。子程序返回指令子程序返回指令ret l子程序执行完后,应返回主程序中继续执行,这一功能由ret指令完

25、成。要回到主程序,只需获得离开主程序时,由call指令保存于堆栈的指令地址即可。根据子程序与主程序是否同处于一个段内,返回指令分为段内返回和段间返回。ret指令的指令的4种格式种格式 (1)ret。无参数段内返回:ipss:sp,spsp+2。(2)ret imm16。有参数段内返回:ipss:sp,spsp+2,spsp+imm16。(3)ret。无参数段间返回:ipss:sp,spsp+2,csss:sp,spsp+2。(4)ret imm16。有参数段间返回:ipss:sp,spsp+2,csss:sp,spsp+2,spsp+imm16。子程序的调用子程序的调用 l对于一个子程序,应该

26、注意它的入口参数和出口参数。入口参数是由主程序传给子程序的参数,而出口参数是子程序运算完传给主程序的结果。另外,子程序所使用的寄存器和存储单元往往需要保护,以免影响返回后主程序的运行。保护寄存器保护寄存器 l由于调用程序(即主程序)和子程序经常是分别编制的,所以它们所使用的寄存器往往会发生冲突。如果主程序在调用子程序之前的某个寄存器内容在从子程序返回后还有用,而子程序又恰好使用了同一个寄存器,这就破坏了该寄存器的原有内容,因而会造成程序运行错误,这是不允许的。为避免这种错误的发生,在一进入子程序后,就应该把子程序所需要使用的寄存器内容保存在堆栈中,而在退出子程序前把寄存器内容恢复原状。 寄存器

27、保护实例subt proc nearpush axpush bxpush cxpush dx pop dxpop cxpop bxpop axretsubt endp 一般说来,子程序中用到的寄存器是应该保存的。但是,如果使用寄存器在主程序和子程序之间传送参数的话,则这种寄存器就不一定需要保存,特别是用来向主程序回送结果的寄存器,就更不应该因保存和恢复寄存器而破坏了应该向主程序传送的信息 。子程序的参数传递子程序的参数传递 l调用程序在调用子程序时,经常需要传送一些参数给子程序;子程序运行完后也经常要回送一些信息给调用程序。这种调用程序和子程序之间的信息传送称为参数传送(或称变量传送或过程通信

28、)。l参数传递一般有3种方法 利用寄存器利用寄存器 l这是一种最常见方法,把所需传递的参数直接放在主程序的寄存器中传递给子程序。这种方法的特点是编程方便,速度快,节省存储单元,但只适合参数较少的情况,因为寄存器是有限的。利用存储单元利用存储单元 l这种参数传递方法是把所需传递的参数直接放在子程序调用指令代码之后。这种方法的特点是每个子程序都有独立的工作单元,工作时不易引起紊乱,但它占用了存储空间。这种方法不适合递归子程序。 利用堆栈利用堆栈 l这种方法将参数压入堆栈,在子程序运行时从堆栈中取参数。由于堆栈操作不占用寄存器,并且堆栈单元使用后可自动释放,反复使用,便于实现数据隔离和模块化设计。使用这种方法时,当子程序返回后,这些参数就不再有用了,应当丢弃。这时可以利用带立即数的返回指令修改

温馨提示

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

评论

0/150

提交评论