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

下载本文档

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

文档简介

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功能IP=IP+DISPIP=Reg16 或 P=Mem16无条件转移指令无条件转移指令JMPlJMP指令转移可以是短(short)转移(偏移量在-128B,127B之内)、近(near)转移(偏移量在-32KB,32KB之内)、远(far)转移(在不同的代码段之间转移)。l短转移和近转移都是段内转移,JMP指令只将目标指令位置处的偏移量赋值给指令指针寄存器IP,从而实现转移功能l远转移属于段间转移,JMP指令不仅会把目标指令位置处的偏移量赋值给指令指针寄存器,同时还会把目标指令所

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

9、非零转移(JNZ)(3)负数转移(JS)或正数转移(JNS)(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)低于或等于转移(J

10、LE)/不高于转移(JNG)5.2.2 分支程序的结构分支程序的结构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的

12、值,存放在内存RS2单元中。lDATA SEGMENTlRS1 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 R

13、S2, 1 ; 若若X0, (RS2)1l JMP DONElEQUL: MOV RS2, 0 ; 若若X0, (RS2)0lDONE: MOV AH, 4CHl INT 21HlCODE ENDSlEND START5.3 循环程序设计循环程序设计l在实际工作中,有时要求对某一问题进行多次重复处理,而仅仅只是初始条件不同,这种计算过程称为具有循环特征的,而循环程序设计是解决这类问题的一种行之有效的方法。循环程序是采用重复执行某一段程序来实现要求完成计算的编程方法。5.3.1 循环指令循环指令l循环语句当然可以用条件转移指令来实现,除此之外,在80 x86系统中还有专门的循环控制指令来简化循环

14、程序的设计。循环控制指令包括重复控制指令和串操作指令。重复循环控制指令重复循环控制指令 指令名称指令名称指令功能指令功能LOOP指令将CX内容减1,若CX不等于0,则循环至目标地址处(即IP+DISP),否则顺序执行后续指令LOOPZ/LOOPE指令将CX内容减1,若CX不等于0,且标志位ZF=1时,才循环至目标地址处,否则顺序执行后续指令LOOPNZ/LOOPNE指令将CX内容减1,若CX不等于0,且标志位ZF=0时,才循环至目标地址处,否则顺序执行后续指令JCXZ指令这条指令是条件转移指令,经常用于重复循环控制注意:注意:在执行此类重复控制指令前必须把重复次数送入寄存器CX中。串操作指令串

15、操作指令 l串操作指令能对存储区中一块(串)字节或字进行操作,其块的长度可达64KB。这些指令分别是:串复制指令MOVS、串取出指令LODS、串存储指令STOS、串比较指令CMPS和串搜索(扫描)指令SCAS。 循环程序的结构循环程序的结构 循环程序一般包括以下5个部分:(1)初始化部分:)初始化部分:为循环做准备工作,如设置地址指针、计数器及其他变量的初值等。(2)循环工作部分:)循环工作部分:它是循环程序的主体,用来完成循环的基本操作。(3)修改部分:)修改部分:为循环参数做必要的修改,如修改操作数地址、计数器,为下一次执行循环体做好准备。(4)控制部分:)控制部分:根据循环条件来判断、控

16、制循环的继续和终止。(5)结束部分:)结束部分:主要是对循环的结果进行必要的处理,如将结果送入某一寄存器或内存区域。循环程序的结构循环程序的结构 常见的循环程序结构有两种形式:“先处理后判断”和“先判断后处理” (BX)1 2 3 4把BX中的二进制数以十六进制的形式显示在屏幕上。l D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 功能指令 mov ch, 4Rotate : mov cl, 4 rol bx, cl mov al, bl and al, 0fh add al, 30h ;0-9 ASCII cmp al, 3ah j

17、l printit add al, 7h ;A-F ASCII Printit : mov dl, al mov ah, 2 int 21h dec ch jnz rotate例例6设数组设数组X、Y中分别存有中分别存有10个字型数个字型数据。试实现以下计算并把结果存入据。试实现以下计算并把结果存入Z单元。单元。Z1X1+Y1 Z2X2+Y2 Z3X3-Y3Z4X4-Y4 Z5X5+Y5Z6X6-Y6 Z7X7-Y7 Z8X8-Y8Z9X9+Y9 Z10X10+Y10分析:虽然该例对分析:虽然该例对10个式子都存在取数、运算和存数的操作,但操作个式子都存在取数、运算和存数的操作,但操作符不同,

18、且无规律可循。设想按符不同,且无规律可循。设想按Z10、Z9Z1的计算顺序把它们的的计算顺序把它们的操作符自左至右排列起来,并把加用操作符自左至右排列起来,并把加用0表示,减用表示,减用1表示,则十个操表示,则十个操作符数字化后得到一串二进制位作符数字化后得到一串二进制位0011011100,把它放入一个字型,把它放入一个字型内存变量中,其高内存变量中,其高6位无意义,这种存储单元一般被叫做逻辑尺。位无意义,这种存储单元一般被叫做逻辑尺。计算时按照计算时按照Z1Z10顺序,先求顺序,先求Z1的值。每次把逻辑尺右移一位,的值。每次把逻辑尺右移一位,对移出位进行判断,若该位为对移出位进行判断,若该

19、位为0则加,为则加,为1则减。于是就可以用一个则减。于是就可以用一个分支加循环的混合程序实现所要求的功能。分支加循环的混合程序实现所要求的功能。在字型无序表中找出最大数和最小数,在字型无序表中找出最大数和最小数,并分别存入并分别存入MAX和和MIN单元。单元。l算法分析:把表中第一个元素分别作为最大数和最小数,与下一个元素比较,若下一个元素比该元素大,则把下一个元素作为最大数,继续进入下一轮比较;若下一个元素比该元素小,则把下一个元素作为最小数,继续进入下一轮比较直至遍历整个表,最后保留下来的两个数就分别是表中的最大数和最小数。本例采用DO_UNTIL结构实现。DATA SEGMENT BUF

20、 DW 500,30,56,77,999,67,433,5675DW 0,99993455,6578,32766,8DW 0,32560,45,889,5665,0,9CN DW ($-BUF)/2;元素个数MAX DW ?;存放最大数单元MIN DW ? ;存放最小数单元DATA ENDSCODE SEGMENTMAIN PROC FAR ASSUME CS:CODE,DS:DATA查表初始化查表初始化lPUSH DSMOV AX,0PUSH AXMOV AX,DATAMOV DS,AXLEA SI,BUFFER ;初始化地址指针MOV CX,CN ;元素个数MOV AX,SI ;取第一数M

21、OV MAX,AX ;初始化最大数MOV MIN,AX ;初始化最小数COMP:ADD SI,2 ;修改地址指针MOV AX,SI;取下一个数CMP AX,MAX;与当前的最大数比较 JL NEXT;若小于转 MOV MAX,AX;若大于则把此数作为最大数保存 JMP LOPNEXT:CMP AX,MIN;与当前的最小数比较 JG LOP;若大于转 MOV MIN,AX;若小于则把此数作为最小数保存LOP: LOOP COMP;决定循环继续还是终止 RETMAIN ENDPCODE ENDSEND MAINYN初始化循环计数值初始化循环计数值i=0RULEi=1?Xi+YiXiYiYZi结果结

22、果i=i+1,循环次数减,循环次数减1N循环计数值循环计数值=0?例例6题解题解aDATA SEGMENTX DW 12H,34H,56H,78H,90HDW 0ABH,0CDH,0EFH,0F1H,023HY DW 9,8,7,6,5,4,3,2,1,0Z DW 10 DUP(?)RULE DW 0000000011011100B;逻辑尺DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATAMAIN PROC FAR MOV AX,DATA MOV DS,AX MOV BX,0;地址指针 MOV CX,10;循环次数 MOV DX,RULE;逻辑尺例例6题解

23、题解bNEXT: MOV AX,XBX ;取X中的一个数 SHR DX,1 ;逻辑尺右移一位 JC SUBS ;分支判断并实现转移ADD AX,YBX;两数加JMP RESULTSUBS: SUB AX,YBX ;两数减RESULT: MOV ZBX,AX;存结果 ADD BX,2 ;修改地址指针 LOOP NEXT MOV AX,4C00H INT 21HMAIN ENDPCODE ENDS END MAIN 讨论: 这种设置逻辑尺的方法非常有用。例如要传输一批数据(定义为一个数组),该数组中含有多个0元素,为了节省存储空间和传输时间,可以选用合适的数据结构。比如可以使用压缩数据及逻辑尺的方

24、法,把所有元素按下标顺序排列,并各用1个bit表示。设0元素用0表示,非0元素用1表示。存储时只需保存非0元素(压缩数组)和逻辑尺,当进行数据传输时,若逻辑尺相应位为1,则从压缩数组中取到非0数据并传送。若逻辑尺相应位为0时,只送一个标志,在接收方直接生成数字0,这样可以提高传输效率。5.4 子程序设计子程序设计l为了程序共享或模块化设计的需要,把功能相对独立的程序段单独编写和调试,作为一个相对独立的模块供程序使用,就形成子程序。l子程序可以实现源程序的模块化,简化源程序结构,提高编程效率。5.4.1 子程序概念子程序概念l子程序又称过程,相当于高级语言中的过程和函数。在一个程序的不同部分,往

25、往要用到“类似”的程序段,即这些程序段的功能和结构形式都相同,只是某些变量赋值不同。此时就可以把这些程序段写成子程序形式,以便需要时调用它。子程序伪指令子程序伪指令 l子程序的相关伪指令包括子程序的定义指令、调用指令和返回指令等 子程序定义指令子程序定义指令 子程序就是过程。过程定义伪指令的格式如下: PROC 类型属性类型属性 RET ENDP过程和主程序在同一代码段时,过程定义和调用格式如下:CODE SEGMENT SUBT PROC NEAR RET SUBT ENDP CALL SUBT CODE ENDS当过程和主程序不在同一代码段时,过程定义和调用格式如下:CODE1 SEGME

26、NT SUBT PROC FAR RET SUBT ENDP CALL SUBTCODE1 ENDSCODE2 SEGMENT CALL SUBT CODE2 ENDS子程序调用指令子程序调用指令CALL lCALL指令用在主程序中,实现子程序的调用。子程序和主程序可以在同一个代码段内,也可以在不同段内。类似无条件转移指令JMP,子程序调用指令CALL也可以分成段内调用(近调用)和段间调用(远调用)lCALL目标地址也可以采用直接寻址或间接寻址方式。但是子程序执行结束后是要返回的,所以,CALL指令不仅要同JMP指令一样改变CS:IP以实现转移,而且还要保留下一条要执行指令的地址,以便返回时重

27、新获取它。保护CS:IP值的方法是压入堆栈,获取CS:IP值的方法就是弹出堆栈。 CALL 指令的指令的4种格式种格式(1)CALL LABEL。段内调用,直接寻址:SPSP-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:S

28、PCS, SPSP-2,SS:SPIP,IPMEM,CSMEM+2。子程序返回指令子程序返回指令RET l子程序执行完后,应返回主程序中继续执行,这一功能由RET指令完成。要回到主程序,只需获得离开主程序时,由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

29、)RET Imm16。有参数段间返回:IPSS:SP,SPSP+2,CSSS:SP,SPSP+2,SPSP+Imm16。子程序的调用子程序的调用 l对于一个子程序,应该注意它的入口参数和出口参数。入口参数是由主程序传给子程序的参数,而出口参数是子程序运算完传给主程序的结果。另外,子程序所使用的寄存器和存储单元往往需要保护,以免影响返回后主程序的运行。保护寄存器保护寄存器 l由于调用程序(即主程序)和子程序经常是分别编制的,所以它们所使用的寄存器往往会发生冲突。如果主程序在调用子程序之前的某个寄存器内容在从子程序返回后还有用,而子程序又恰好使用了同一个寄存器,这就破坏了该寄存器的原有内容,因而会

30、造成程序运行错误,这是不允许的。为避免这种错误的发生,在一进入子程序后,就应该把子程序所需要使用的寄存器内容保存在堆栈中,而在退出子程序前把寄存器内容恢复原状。 寄存器保护实例寄存器保护实例SUBT PROC NEARPUSH AXPUSH BXPUSH CXPUSH DX POP DXPOP CXPOP BXPOP AXRETSUBT ENDP 一般说来,子程序中用到的寄存器是应该保存的。但是,如果使用寄存器在主程序和子程序之间传送参数的话,则这种寄存器就不一定需要保存,特别是用来向主程序回送结果的寄存器,就更不应该因保存和恢复寄存器而破坏了应该向主程序传送的信息 。设计子程序应注意的问题设

31、计子程序应注意的问题1子程序说明子程序说明为便于引用,子程序应在开头对其功能、调用参数和为便于引用,子程序应在开头对其功能、调用参数和返回参数等予以说明,例如参数的类型、格式及存放返回参数等予以说明,例如参数的类型、格式及存放位置等。位置等。2寄存器的保存与恢复寄存器的保存与恢复为了保证调用程序的寄存器内容不被破坏,应在子程为了保证调用程序的寄存器内容不被破坏,应在子程序开头保存它要用到的寄存器内容,返回前再恢复它序开头保存它要用到的寄存器内容,返回前再恢复它们。通常用们。通常用PUSH指令保存指令保存,用用POP恢复。进出堆栈的恢复。进出堆栈的顺序相反。顺序相反。设计子程序应注意的问题设计子

32、程序应注意的问题3密切注意堆栈状态密切注意堆栈状态 在设计含有子程序的源程序时,要密切注意一切与在设计含有子程序的源程序时,要密切注意一切与堆栈有关的操作。例如堆栈有关的操作。例如 CALL调用类型和子程序定义类型的一致性调用类型和子程序定义类型的一致性;PUSH和和POP指令的匹配;通过堆栈传递参数时子程序返回指令的匹配;通过堆栈传递参数时子程序返回使用使用RET n指令指令等;以确保堆栈平衡,否则后果不可等;以确保堆栈平衡,否则后果不可预料。预料。子程序参数传递子程序参数传递可以通过给子程序传递参数使其更通用。可以通过给子程序传递参数使其更通用。入口参数入口参数(输入参数):主程序(输入参

33、数):主程序 提供给提供给 子程序子程序出口参数出口参数(输出参数):子程序(输出参数):子程序 返回给返回给 主程序主程序 数据本身数据本身( (传值传值) ) 数据的地址数据的地址( (传址传址) ) 寄存器寄存器 地址表地址表 堆栈堆栈通过寄存器传递单个变量或者地址;通过寄存器传递单个变量或者地址;通过地址表传递多个参数地址(存储单元);通过地址表传递多个参数地址(存储单元);通过堆栈传递参数或参数地址。通过堆栈传递参数或参数地址。这种传递方式使用方便,适用于参数较少的情况。这种传递方式使用方便,适用于参数较少的情况。把参数存于约定的寄存器中,可以传值,也可以传地址。把参数存于约定的寄存

34、器中,可以传值,也可以传地址。子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)。情况进行保护)。子程序对带有入口参数的寄存器可以保护,也可以不保护;但最子程序对带有入口参数的寄存器可以保护,也可以不保护;但最好统一。好统一。例例 把把BX中的二进制数转换成十进制并显示在屏幕上。中的二进制数转换成十进制并显示在屏幕上。分析:本例采用从高到低逐个除以十进制位权的方法。分析:本例采用从高到低逐个除以十进制位权的方法。题解:题解:MAINPROCFAR。MOV BX,162EHCALL TERN ;转换并显示转换并显示MOV

35、 AX,4C00H ;安全退出程序安全退出程序 INT 21HMAINENDP1通过寄存器传递参数通过寄存器传递参数TERN PROC ;二二十并显示。十并显示。 MOV CX,10000CALL DEC_DIV;转换万位数转换万位数 MOV CX,1000CALL DEC_DIV;转换千位数转换千位数 MOV CX,100CALL DEC_DIV;转换百位数转换百位数 MOV CX,10CALL DEC_DIV;转换十位数转换十位数 MOV CX,1CALL DEC_DIV;转换个位数转换个位数RETTERN ENDP例解bDEC_DIVPROC;CX中为十进制的位权中为十进制的位权MOV

36、AX,BXMOV DX,0 DIV CX;商为转换后的一位十进制数商为转换后的一位十进制数MOV BX,DX ;保留余数输出,做下次转换保留余数输出,做下次转换MOV DL,AL ADD DL,30H;转换成转换成ASCII码显示码显示 MOV AH,2INT 21H RETDEC_DIVENDPCODE ENDS END MAIN例解c例实现数组求和功能。要求数组求和(不考虑溢出例实现数组求和功能。要求数组求和(不考虑溢出情况)由子程序实现,其数组元素及结果均为字型数情况)由子程序实现,其数组元素及结果均为字型数据。据。例例6.2 解解a:DATA SEGMENTARY DW 1,2,3,4

37、,5,6,7,8,9,10COUNT DW ($-ARY)/2;数组元素个数数组元素个数SUM DW ?;数组和的地址数组和的地址DATAENDS2若调用程序和子程序在同模块中,子程序可以若调用程序和子程序在同模块中,子程序可以直接访问模块中的变量直接访问模块中的变量CODE1 SEGMENTMAIN PROC FAR ASSUME CS:CODE1,DS:DATA MOV AX,DATA MOV DS,AX CALL FAR PTR ARY_SUMMOV AX,4C00HINT 21HMAIN ENDPCODE1 ENDS例例6.2 解解bCODE2 SEGMENT ASSUME CS:CO

38、DE2ARY_SUM PROC FAR;数组求和子程序数组求和子程序 PUSH AX;保存寄存器保存寄存器 PUSH CX PUSH SI LEA SI,ARY;取数组起始地址取数组起始地址 MOV CX,COUNT;取元素个数取元素个数 XOR AX,AX;清清0累加器累加器NEXT: ADD AX,SI;累加和累加和 ADD SI,2;修改地址指针修改地址指针 LOOP NEXT MOV SUM,AX;存和存和 ;恢复寄存器恢复寄存器RET ARY_SUM ENDP。例例6.2 解解c3通过地址表传递参数地址通过地址表传递参数地址 适用于参数较多的情况。方法是先建立一适用于参数较多的情况。

39、方法是先建立一个地址表,该表由参数地址构成。然后把表个地址表,该表由参数地址构成。然后把表的首地址通过寄存器或堆栈传递给子程序。的首地址通过寄存器或堆栈传递给子程序。 例例 编写一个数组求和子程序,其数组元编写一个数组求和子程序,其数组元素及结果均为字型数据。另定义两个数组,素及结果均为字型数据。另定义两个数组,并编写一个主程序,通过调用数组求和子程并编写一个主程序,通过调用数组求和子程序分别求出两个数组的和。序分别求出两个数组的和。分析:虽然主、子程序在同模块中,但由于分析:虽然主、子程序在同模块中,但由于在一个程序中要分别求出两个数组的和,因在一个程序中要分别求出两个数组的和,因此子程序不

40、能直接引用数组变量名。本例用此子程序不能直接引用数组变量名。本例用数组首地址数组首地址、元素个数的地址、和数地址元素个数的地址、和数地址构构成地址表,通过地址表传送这些参数的地址,成地址表,通过地址表传送这些参数的地址,以便子程序能够访问到所需参数以便子程序能够访问到所需参数。数组的首地址数组长度存放单元的地址数组累加和存放单元的地址地址表地址表解解aDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10;数组数组1COUNT DW ($-ARY)/2;数组数组1的元素个数的元素个数SUM DW ?;数组数组1的和地址的和地址NUM DW 10,20,30,40,50;

41、数组数组2CT DW ($-NUM)/2;数组数组2的元素个数的元素个数TOTAL DW ?;数组数组2的和地址的和地址TABLE DW 3 DUP(?);地址表地址表DATA ENDSCODE1 SEGMENTMAINPROC FAR ASSUME CS:CODE1,DS:DATA。 MOV TABLE,OFFSET ARY ;构造数组构造数组1的地址表的地址表 MOV TABLE+2,OFFSET COUNT MOV TABLE+4,OFFSET SUM LEA BX,TABLE;传递地址表首地址传递地址表首地址 CALL FAR PTR ARY_SUM ;段间调用数组求和子段间调用数组求

42、和子程序程序MOV TABLE,OFFSET NUM;构造数组构造数组2的地址表的地址表MOV TABLE+2,OFFSET CTMOV TABLE+4,OFFSET TOTALLEA BX,TABLE ;传递地址表的首地址传递地址表的首地址CALL FAR PTR ARY_SUM。MAIN ENDPCODE1 ENDS解解bCODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;数组求和子程序数组求和子程序 PUSH AX;保存寄存器保存寄存器 PUSH CX PUSH SI PUSH DI MOV SI,BX;取数组起始地址取数组起始地址 MOV DI,

43、BX+2;取元素个数地址取元素个数地址 MOV CX,DI;取元素个数取元素个数 MOV DI,BX+4;取结果地址取结果地址 XOR AX,AX;清清0累加器累加器解解cNEXT:ADD AX,SI;累加累加 ADD SI,2;修改地址指针修改地址指针 LOOP NEXT MOV DI,AX;存和存和 POP DI;恢复寄存器恢复寄存器 POP SI POP CX POP AX RET ARY_SUM ENDPCODE2 ENDS END MAIN解解d这种方式适用于参数较多,或子程序有多层嵌套、这种方式适用于参数较多,或子程序有多层嵌套、递归调用的情况。递归调用的情况。实现步骤:实现步骤:

44、p主程序把主程序把参数参数或或参数地址参数地址压入堆栈;压入堆栈;p子程序使用堆栈中的参数或通过栈中参数地址取子程序使用堆栈中的参数或通过栈中参数地址取到参数;到参数;p子程序返回时使用子程序返回时使用RET n指令调整指令调整SP指针,以指针,以便删除堆栈中已用过的参数,保持堆栈平衡,保便删除堆栈中已用过的参数,保持堆栈平衡,保证程序的正确返回。证程序的正确返回。4通过堆栈传递参数或参数地址通过堆栈传递参数或参数地址例题解a:STACK SEGMENT STACK STKDW 16 DUP(?)STACK ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10

45、COUNT DW ($-ARY)/2SUM DW ?DATA ENDSCODE1 SEGMENTMAIN PROC FAR ASSUME CS:CODE1,DS:DATA,SS:STACK例例.完成数组求和功能,求和由子程序实现,完成数组求和功能,求和由子程序实现,要求通过堆栈传递参数地址。要求通过堆栈传递参数地址。MOV AX,DATA MOV DS,AXMOV AX,STACKMOV SS,AXLEA BX,ARY PUSH BX;压入数组起始地址 LEA BX,COUNT PUSH BX;压入元素个数地址 LEA BX,SUM PUSH BX;压入和地址 CALL FAR PTR ARY

46、_SUM ;调用求和子程序 INT 20H;例题解例题解bCODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;数组求和子程序数组求和子程序 PUSH BP;保存保存BP值值 MOV BP,SP ;BP是堆栈数据的地址指针是堆栈数据的地址指针 PUSH AX;保存寄存器内容保存寄存器内容 PUSH CX; PUSH SI; PUSH DI; MOV SI,BP+10;得到数组起始地址得到数组起始地址 MOV DI,BP+8;得到元素个数地址得到元素个数地址 MOV CX,DI;得到元素个数得到元素个数 MOV DI,BP+6;得到和地址得到和地址 XOR

47、AX,AX例题解cNEXT: ADD AX,SI ;累加累加 ADD SI,2;修改地址指针修改地址指针 LOOP NEXT MOV DI,AX;存和存和 POP DI;恢复寄存器内容恢复寄存器内容 POP SI; POP CX; POP AX; POP BP; RET 6;返回并调整返回并调整SP指针指针ARY_SUM ENDPCODE2 ENDS END MAIN例题解d本例通过本例通过BP访问堆栈中的参数。访问堆栈中的参数。程序的堆栈变化情况参见图程序的堆栈变化情况参见图a,指示了程序指示了程序中所有入栈操作对堆栈的影响随入栈数据的增中所有入栈操作对堆栈的影响随入栈数据的增加加,SP的值

48、不断减小,堆栈可用空间也随之减的值不断减小,堆栈可用空间也随之减少。少。图图b为已从子程序返回、而主程序为已从子程序返回、而主程序RET指指令执行前的堆栈状态,其中的灰色部分表示执令执行前的堆栈状态,其中的灰色部分表示执行语句行语句时已弹出的数据。时已弹出的数据。 从以上分析可以看出,通过堆栈传递参数从以上分析可以看出,通过堆栈传递参数时子程序的返回指令必须是时子程序的返回指令必须是RET N形式,当堆形式,当堆栈操作是栈操作是16位时位时N值应该是压入堆栈的参数个值应该是压入堆栈的参数个数的数的2倍倍,只有这样保证程序的正常运行。只有这样保证程序的正常运行。用结构形式访问堆栈中的参数,这种方

49、法用结构形式访问堆栈中的参数,这种方法更简便及规范化。更简便及规范化。利用堆栈传递秋和子程序需要的参数利用堆栈传递秋和子程序需要的参数(DI)(SI)(CX)(AX)(BP)数组长度存放单元的地址数组的起始地址堆栈操作前栈顶数组和数存放单元的地址子程序返回地址CS子程序返回地址IP+2 -10+4 -8+6 -6+8 -4+10 -2(sp) (BP) (SP)-12(BP) (SP)-12返回返回语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈

50、状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态语句语句执行后堆栈状态执行后堆栈状态SSSSSPSPBPBPDIDI值值SISI值值CXCX值值AXAX值值BPBP值值IPIP值值CSCS值值SUMSUM的地址的地址COUNTCOUNT地址地址ARYARY首地址首地址初始栈顶初始栈顶PSPPSP段基址段基址图a 程序中所有入栈操作对堆栈的影响返回返回SPSP语句语句执行后堆栈状态执行后堆栈状态SSSSDIDI值值SISI值值CXCX值值AXAX值值BPBP值值IPIP值值CSCS值

51、值SUMSUM的地址的地址COUNTCOUNT地址地址ARYARY首地址首地址初始栈顶初始栈顶PSPPSP段基址段基址图b 程序中主程序的RET执行前堆栈状态 例完成数组求和功能,其中求和由子程序例完成数组求和功能,其中求和由子程序实现,要求使用结构访问堆栈中的参数。实现,要求使用结构访问堆栈中的参数。 图图c给出了堆栈及给出了堆栈及结构数据定义结构数据定义。注意这些结。注意这些结构字段的顺序为其值压入的逆序。实际上构字段的顺序为其值压入的逆序。实际上,它它只只是给图是给图a中由主程序压入的数据、返回地址及子中由主程序压入的数据、返回地址及子程序压入的程序压入的BP值起了个名字而已,值起了个名

52、字而已,而字段值的而字段值的预置是通过预置是通过PUSH和和CALL指令实现的。当子程指令实现的。当子程序用到堆栈中的参数时,只需使用序用到堆栈中的参数时,只需使用BP作为基地作为基地址、通过结构字段名访问就可以了。编码见程序。址、通过结构字段名访问就可以了。编码见程序。使用堆栈传递结构数据返回返回SSSSSPSPBPBPDIDI值值堆栈数据SISI值值结构字段名CXCX值值AXAX值值BPBP值值SAVE_BPIPIP值值SAVE_CS_IPCSCS值值SUMSUM的地址的地址SUM_ADDRCOUNTCOUNT地址地址COUNT_ADDRARYARY首地址首地址ARY_ADDR0 0PSP

53、PSP段基址段基址结构结构图c 程序的堆栈及结构数据示意图程序源码程序源码STACK SEGMENT STACK STKDW 16 DUP(?)TOPEQU $STACK ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW ($-ARY)/2SUM DW ?DATA ENDSCODE1 SEGMENTASSUME CS:CODE1,DS:DATA,SS:STACKMAINPROCFARMOV AX,DATAMOV DS,AX程序源码程序源码aMOV AX,STAKMOV SS,AXMOV SP,TOP;设置栈顶指针设置栈顶指针LEA BX,A

54、RY PUSH BX;压入数组起始地址压入数组起始地址 LEA BX,COUNT PUSH BX;压入元素个数地址压入元素个数地址 LEA BX,SUM PUSH BX;压入和地址压入和地址 CALL FAR PTR ARY_SUMMOV AX,4C00HINT 21HMAIN ENDPCODE1 ENDS CODE2 SEGMENT ASSUME CS:CODE2STACK_STRC STRUC;定义结构定义结构SAVE_BP DW ?SAVE_CS_IP DW 2 DUP(?)SUM_ADDR DW ?COUNT_ADDR DW ?ARY_ADDR DW ?STACK_STRC ENDS

55、程序源码程序源码bARY_SUMPROC FAR;数组求和子程序数组求和子程序 PUSH BP;保存保存BP值,值, MOV BP,SP;(BP) 结构数据指针结构数据指针PUSH AX PUSH CX PUSH SI PUSH DI MOV SI,BP.ARY_ADDR;取数组首地址取数组首地址 MOV DI,BP.COUNT_ADDR;取数组长度;取数组长度 MOV CX,DI MOV DI,BP.SUM_ADDR;取数组和数地址取数组和数地址程序源程序源cXOR AX,AXNEXT: ADD AX,SI;累加累加 ADD SI,2;修改地址指针修改地址指针 LOOP NEXT MOV D

56、I,AX;存和存和 POP DI POP SI POP CX POP AX POP BP RET 6;返回并调整返回并调整SP指针指针ARY_SUM ENDP。程序源程序源d1分析:由于题目要求从外设输入输出数分析:由于题目要求从外设输入输出数据,而在内存中用二进制数形式实现乘法,所以涉据,而在内存中用二进制数形式实现乘法,所以涉及到代码转换问题。步骤如下:及到代码转换问题。步骤如下:l从键盘输入两个十进制乘数(从键盘输入两个十进制乘数(ASCII码)码)l分别转换成二进制形式分别转换成二进制形式l二进制数乘二进制数乘l把二进制乘积转换成十进制数的把二进制乘积转换成十进制数的ASCII码形式码

57、形式l输出到屏幕。输出到屏幕。例例. 编写两个四位无符号十进制数乘法程序。要求:乘数编写两个四位无符号十进制数乘法程序。要求:乘数从键盘输入;二进制乘;用十进制数形式显示乘积。从键盘输入;二进制乘;用十进制数形式显示乘积。本例中的输入、输出、十进制到二进制的本例中的输入、输出、十进制到二进制的转换、以及二进制到十进制的转换均采用子程序转换、以及二进制到十进制的转换均采用子程序形式实现。形式实现。* 十十二转换算法:二转换算法:Y=Y*10+Xi(Y的初始值为的初始值为0,i =n,n-1,0)ASC_BIN是实现四位十进制数转换成二进是实现四位十进制数转换成二进制数的子程序。程序中制数的子程序

58、。程序中Y值在值在AX中,中,i值由值由CL控控制。制。2设计:设计: 十十二转换算法二转换算法除除10取余法。即用取余法。即用32位的二进制乘积作为被位的二进制乘积作为被除数,除数,10作为除数,每次除后所得到的余数就是作为除数,每次除后所得到的余数就是本位的十进制数本位的十进制数,并把它转换成并把它转换成ASCII码存放在输码存放在输出缓冲区的相应位置,直到整个转换结束,最后出缓冲区的相应位置,直到整个转换结束,最后输出。输出。实现该算法的子程序是BIN_ASC。考虑到32位的被除数除以10很容易产生超过16位的商,从而产生除法错中断无法得到正确结果,因此需要采用一种避免产生除法错中断的技

59、术。本例采用的方法是把32位被除数扩展成48位,其中最高16位为0,然后进行除法运算。示意图如下:* 二十转换算法: * 二十转换算法: 全全0 0CR EQU 0DHLF EQU 0AHSTACKSG SEGMENT STACK S DW 64 DUP(ST)STACKSG ENDS3编码编码DATA SEGMENTPROMPT1 DBCR,LF,INPUTNUM1:$PROMPT2 DBCR,LF,INPUTNUM2:$ ASCIN1 DB5 , ? , 5 DUP(?)ASCIN2 DB5 , ? , 5 DUP(?)BIN1 DW?;乘数乘数1二进制值二进制值BIN2 DW?;乘数乘数

60、2二进制值二进制值RSLTHI DW0;32位二进制乘积的高位二进制乘积的高16位位RSLTLO DW0;32位二进制乘积的低位二进制乘积的低16位位ASCOUT0 DBCR,LF,RESULT:ASC_OUT DB10DUP(0),$DATA ENDS数据段定义数据段定义CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKSGMAIN PROC FAR MOV AX,DATA MOV DS,AXMOV AX, STACKSG MOV SS,AX LEA DX,PROMPT1 CALL DISP;显示提示信息显示提示信息1 LEA DX,ASCIN1 CAL

温馨提示

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

评论

0/150

提交评论