




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、5.1子程序子程序 5.2参数的传递参数的传递 5.3嵌套和递归子程序嵌套和递归子程序 5.4多模块程序设计多模块程序设计 5.5汇编语言与汇编语言与C语言混合编程语言混合编程5.6DOS和和BIOS调用调用IPCSn指令存放在内存中指令存放在内存中,处理器从内存取指令分析执行处理器从内存取指令分析执行n指令一般是从前到后顺序执行的指令一般是从前到后顺序执行的nCPU执行当前指令时,执行当前指令时,IP被更改为下条指令的地址,被更改为下条指令的地址,CS和和IP不能用不能用MOV等传送指令直接修改等传送指令直接修改n跳转类指令可以通过修改跳转类指令可以通过修改IP和和CS实现程序的不同流程实现
2、程序的不同流程n本章的本章的子程序调用和返回指令也是通过修改子程序调用和返回指令也是通过修改IP和和CS实现的实现的。回顾:专用寄存器回顾:专用寄存器下一条指令的段地址下一条指令的段地址下一条指令的偏移地址下一条指令的偏移地址 把程序需要完成的任务分解为若干个把程序需要完成的任务分解为若干个“子任子任务务”,每个,每个“子任务子任务”由一段相对独立的程序完成,由一段相对独立的程序完成,称为称为“子程序子程序”。 子程序也称为子程序也称为“过程过程”(ProcedureProcedure),在高级),在高级语言里还称作语言里还称作“函数函数”(FunctionFunction)。)。子程序(子程
3、序(Subroutine )概念)概念一个简单子程序一个简单子程序;显示回车换行的子程序显示回车换行的子程序dispcrlf proc nearmov ah,02h; 2号子功能号子功能 mov dl, 0dh; 回车的回车的ascii码码int 21h; 显示显示mov ah,02h; 2号子功能号子功能 mov dl, 0ah; 换行的换行的ascii码码int 21h; 显示显示ret ;返回主程序返回主程序dispcrlf endpcode segmentassume cs:codestart: call dispcrlf ;调用子程序调用子程序mov ah, 4c00h int 21
4、h ; 返回返回DOScode ends end start1.1.程序结构清晰,提高了程序的可阅读性和可维护性。程序结构清晰,提高了程序的可阅读性和可维护性。2.2.每个子程序可以独立地进行调试,由于程序规模较小,降每个子程序可以独立地进行调试,由于程序规模较小,降低了调试难度。低了调试难度。3.3.每个子程序就是一个具有特定功能的独立的程序,提高程每个子程序就是一个具有特定功能的独立的程序,提高程序的序的“可重用性可重用性”,提高了软件开发效率。,提高了软件开发效率。 子程序结构程序的优点子程序结构程序的优点 主程序: CALLPROC1 MOVAX, BX 子程序 PROC1 RET把下
5、一条指令地址压入堆栈保存按照堆栈保存的地址返回子程序的调用和返回示意子程序的调用和返回示意近程子程序近程子程序:只能在同一个代码段内调用的子程序。只能在同一个代码段内调用的子程序。n由于主程序和子程序处于同一个代码段,调用和返回时只需要改变由于主程序和子程序处于同一个代码段,调用和返回时只需要改变IPIP寄存寄存器的值,器的值,CSCS寄存器的值保持不变。寄存器的值保持不变。n近程子程序的入口地址用近程子程序的入口地址用1616位段内偏移地址表示。位段内偏移地址表示。远程子程序远程子程序:能够被不同代码段的程序调用。能够被不同代码段的程序调用。n调用时,需要调用时,需要同时改变同时改变CSCS
6、和和IPIP寄存器寄存器的值,返回时,需要从堆栈里弹出的值,返回时,需要从堆栈里弹出3232位的返回地址送入位的返回地址送入IPIP,CSCS寄存器寄存器。n远程子程序的入口地址用远程子程序的入口地址用1616位段基址和位段基址和1616位段内偏移地址位段内偏移地址表示。表示。子程序的类型子程序的类型5.1.1 5.1.1 CALLCALL和和RETRET指令指令 5.1.2 5.1.2 子程序的定义子程序的定义 5.1.3 5.1.3 子程序文件子程序文件 5.1.4 5.1.4 子程序应用子程序应用 CALL(Call,调用)指令,调用)指令 段内直接调用段内直接调用格式:格式:CALL子
7、程序名子程序名 操作:操作:SP SP-2, SS:SP IP(保存(保存16位返回地址)位返回地址) IP 子程序入口的偏移地址子程序入口的偏移地址段内间接调用段内间接调用 格式:格式:CALLREG16/MEM16 操作:操作:SP SP-2, SS:SP IP(保护(保护16位返回地址)位返回地址) IP REG16/MEM16 段内调用段内调用段间直接调用段间直接调用 格式:格式:CALL FAR PTR子程序名子程序名操作:操作: SP SP-2, SS:SP CSSP SP-2, SS:SP IP (以上是保存(以上是保存32位返回地址,偏移地址保存在较小地址处)位返回地址,偏移地
8、址保存在较小地址处) IP 子程序入口的偏移地址,子程序入口的偏移地址,CS 子程序入口的段基址子程序入口的段基址段间间接调用段间间接调用格式:格式:CALL MEM32操作:操作:SP SP-2,SS:SP CS SP SP-2,SS:SP IP IP MEM32,CSMEM32+2 段间调用段间调用(1) CALLPROC1(2) LEACX,PROC1CALL CX(3) ADDR_PROC1 DW PROC1 ;子程序偏移地址;子程序偏移地址CALLADDR_PROC1;调用近程子程序;调用近程子程序PROC1(4)LEABX, ADDR_PROC1CALLWORD PTR BX;调用
9、近程子程序;调用近程子程序PROC1调用子程序的四种方法调用子程序的四种方法n 无参数段内返回无参数段内返回格式:格式:RET操作:操作:IP SS: SP,SP SP+2n 有参数段内返回有参数段内返回格式:格式:RET D16 ;其中;其中D16代表代表16位数据位数据操作:操作:IP SS:SP,SP SP+2 SP SP+D16 n无参数段间返回无参数段间返回 格式:格式:RET操作:操作:IP SS:SP, SP SP+2CS SS:SP, SP SP+2 n有参数段间返回有参数段间返回 格式:格式:RET D16 ;其中;其中D16代表代表16位数据位数据操作:操作:IP SS:S
10、P, SP SP+2CS SS:SP, SP SP+2 SP SP+D16 RETRET指令指令5.1.2 5.1.2 子程序的定义子程序的定义 子程序名子程序名PROC NEAR/FAR;子程序体子程序体RET子程序名子程序名ENDP n子程序名应该是合法的标识符。子程序名应该是合法的标识符。n用用NEARNEAR说明的是说明的是“近程子程序近程子程序”,只能在同一代码段内调用。,只能在同一代码段内调用。n用用FARFAR说明的是说明的是“远程子程序远程子程序”,能在其它代码段调用。,能在其它代码段调用。n子程序的远近属性选项可以省略(省略时为近程子程序)子程序的远近属性选项可以省略(省略时
11、为近程子程序)n子程序的定义要写在代码段内子程序的定义要写在代码段内例例5.1 子程序子程序FRACTOR用来计算一个数的阶乘。主程序利用它用来计算一个数的阶乘。主程序利用它 计算计算15的阶乘,存入的阶乘,存入FRA数组。数组。 DATASEGMENT FRA DW 5 DUP (?)DATAENDSCODESEGMENTASSUME CS: CODE, DS: DATASTART: MOV AX, DATAMOVDS, AXMOVBX, 1; BX中存放待求阶乘的数中存放待求阶乘的数MOV SI, 0MOVCX, 5; 求阶乘次数(循环次数)求阶乘次数(循环次数)LOOP0: CALL F
12、RACTOR; 调用调用FRACTOR求阶乘求阶乘MOVFRASI, AX; 保存结果(阶乘)保存结果(阶乘)ADDSI, 2INCBX; 产生下一个待求阶乘的数产生下一个待求阶乘的数LOOPLOOP0; 循环控制循环控制MOV AX, 4C00HINT21HCODEENDSENDSTART思考题:这个程序正确么?思考题:这个程序正确么?;输入参数:输入参数:BX:对哪个数求阶乘:对哪个数求阶乘;输出参数:输出参数:AX:结果:结果FRACTOR PROC NEARMOV CX, BX; 待求阶乘的数转待求阶乘的数转入入CX寄存器寄存器MOVAX, 1; “累乘器累乘器”置初值置初值1FRAL
13、OOP:MULCX; 累乘累乘LOOPFRALOOP; 循环控制循环控制RETFRACTORENDPFRACTOR PROC NEARPUSHCX; CX压入堆栈保护压入堆栈保护 MOV CX, BX; 待求阶乘的数转待求阶乘的数转入入CX寄存器寄存器MOVAX, 1; “累乘器累乘器”置初值置初值1FRALOOP:MULCX; 累乘累乘LOOPFRALOOP; 循环控制循环控制POPCX ; 从堆栈里弹出从堆栈里弹出CX的原值的原值 RETFRACTORENDP子程序名子程序名PROC NEAR/FARPUSH; 保护现场(寄存器保护现场(寄存器/存储器)存储器)PUSH; 个数根据具体情况
14、决定个数根据具体情况决定;子程序主体;子程序主体POP ;恢复现场,注意出栈次序;恢复现场,注意出栈次序POP ; 先进栈的寄存器后出栈先进栈的寄存器后出栈RET;返回;返回子程序名子程序名ENDP 在子程序入口处把相关寄存器的值入栈保护,程序返回前再在子程序入口处把相关寄存器的值入栈保护,程序返回前再恢复它们的值,这个操作称为恢复它们的值,这个操作称为“保护现场保护现场”和和“恢复现场恢复现场”。子程序的一般格式子程序的一般格式5.1.3 5.1.3 子程序文档子程序文档设计一个子程序之前,首先应该明确:设计一个子程序之前,首先应该明确:子程序的名字子程序的名字;子程序的功能子程序的功能;入
15、口参数入口参数:为了运行这个子程序,主程序为它准备了哪几个为了运行这个子程序,主程序为它准备了哪几个“已知条件已知条件”?这些参数存放在什么地方?这些参数存放在什么地方?出口参数出口参数:这个子程序的运行结果有哪些?存放在什么地方?这个子程序的运行结果有哪些?存放在什么地方?影响寄存器影响寄存器:执行这个子程序会改变哪几个寄存器的值?执行这个子程序会改变哪几个寄存器的值?其它需要说明的事项其它需要说明的事项。 上述内容连同子程序源代码等合称为上述内容连同子程序源代码等合称为“子程序文档子程序文档”。 常常把上述内容以常常把上述内容以“程序注释程序注释”的方式书写在一个子程序的首部。的方式书写在
16、一个子程序的首部。给使用者提供调用信息。给使用者提供调用信息。; 名称:名称: Square; 功能:求功能:求16Bit无符号数的平方根无符号数的平方根; 入口参数:入口参数:16Bit无符号数在无符号数在AX中中; 出口参数:出口参数:8Bit平方根数在平方根数在AL中中; 影响寄存器:影响寄存器:AX ( AL ) ;方法:方法: 利用公式:利用公式:N2=1+3+ + (2N-1) 求平方根求平方根SQUARE PROC NEARPUSHCX;保护现场保护现场PUSHBXMOVBX, AX;要求平方根的数送要求平方根的数送BXMOVAL, 0; AL中存放平方根,初值中存放平方根,初值
17、0 MOVCX, 1; CX置入第一个奇数置入第一个奇数1; 利用公式:利用公式:N2=1+3+ + (2N-1) 求平方根求平方根NEXT:SUBBX, CXJBDONEADDCX, 2; 形成下一个奇数形成下一个奇数INCAL;AL存放已减去奇数的个数存放已减去奇数的个数JMPNEXTDONE:POPBX;恢复现场恢复现场POPCXRET;返回返回SQUARE ENDP“SQUARE”的子程序,求一个数的平方根的子程序,求一个数的平方根5.1.4 5.1.4 子程序应用子程序应用每调用一次子程序,主程序需要做三件事:每调用一次子程序,主程序需要做三件事:(1)为子程序准备入口参数)为子程序
18、准备入口参数(2)调用子程序)调用子程序(3)处理子程序的返回参数)处理子程序的返回参数DATA SEGMENTX DW 59, 3500, 139, 199, 77 ;欲求平方根的数组;欲求平方根的数组ROOTDB5 DUP(?);存放平方根内存区;存放平方根内存区DATA ENDS CODESEGMENTASSUME CS: CODE, DS: DATASTART: MOVAX, DATAMOVDS, AXLEABX, X;初始化指针;初始化指针LEASI, ROOTMOVCX, 5;设置计数器初值;设置计数器初值ONE:MOVAX, BX;设置入口参数;设置入口参数CALLSQUARE;
19、调用子程序;调用子程序MOVSI, AL ;保存返回参数(平方根);保存返回参数(平方根)ADDBX, 2;修改指针;修改指针INCSI;修改指针;修改指针LOOPONE;循环控制;循环控制MOVAX, 4C00H;返回;返回DOSINT21H 例例 求求5 5个无符号数的平方根。个无符号数的平方根。子程序子程序; 名称:名称: Square; 功能:求功能:求16Bit无符号数的平方根无符号数的平方根; 入口参数:入口参数:16Bit无符号数在无符号数在AX中中; 出口参数:出口参数:8Bit平方根数在平方根数在AL中中; 影响寄存器:影响寄存器:AX ( AL ) ;方法:方法: 利用公式
20、:利用公式:N2=1+3+ + (2N-1) 求平方根求平方根SQUARE PROC NEARPUSHCX;保护现场保护现场PUSHBXMOVBX, AX;要求平方根的数送要求平方根的数送BXMOVAL, 0; AL中存放平方根,初值中存放平方根,初值0 MOVCX, 1; CX置入第一个奇数置入第一个奇数1NEXT:SUBBX, CXJBDONEADDCX, 2; 形成下一个奇数形成下一个奇数INCAL;AL存放已减去奇数的个数存放已减去奇数的个数JMPNEXTDONE:POPBX;恢复现场恢复现场POPCXRET;返回返回SQUARE ENDPCODE ENDSEND START传递的参数
21、有两种类型传递的参数有两种类型:(1 1)值传递值传递:把参数的值放在约定的寄存器或存储单元传递给把参数的值放在约定的寄存器或存储单元传递给子程序,或者,由子程序返回给主程序。子程序,或者,由子程序返回给主程序。 如果一个入口参数是用值传递的,子程序使用这个值,但是如果一个入口参数是用值传递的,子程序使用这个值,但是不改变它自身的值。不改变它自身的值。(2 2)地址传递地址传递:把参数事先存放在某个存储单元,把这个存储把参数事先存放在某个存储单元,把这个存储单元的地址作为参数传递给子程序。单元的地址作为参数传递给子程序。 如果一个参数使用它的地址来传递,子程序可以改变这个参如果一个参数使用它的
22、地址来传递,子程序可以改变这个参数的值。例如,把存放结果的存储单元的地址作为数的值。例如,把存放结果的存储单元的地址作为“入口参数入口参数”传递给子程序,子程序可以把运算结果直接存入这个单元。传递给子程序,子程序可以把运算结果直接存入这个单元。n利用寄存器传递参数利用寄存器传递参数 n利用主、子程序利用主、子程序“共享共享”的数据段传递参数的数据段传递参数 n利用堆栈传递参数利用堆栈传递参数三种常用的参数传递方法:三种常用的参数传递方法: 用寄存器传递参数用寄存器传递参数 例例5.35.3求菲波那契数列的前求菲波那契数列的前n n项。项。分析:分析: 菲波那契数列的前两项为菲波那契数列的前两项
23、为1 1,1 1,以后的每一项都是其前两,以后的每一项都是其前两项之和。项之和。 X 0=1 , X 1=1, X i=X i-1+X i-2 ( i=2 ) 。方法方法1:利用寄存器传递参数的值。:利用寄存器传递参数的值。方法方法2:利用寄存器传递参数的地址。:利用寄存器传递参数的地址。.MODEL SMALL.DATAFIBLST DW 1, 1, 18 DUP (?)NDW20.CODESTART:MOV AX, DATAMOV DS, AXLEASI, FIBLSTMOV CX, NSUBCX, 2ONE:MOVAX, SIMOVBX, SI+2CALL FIBMOV SI+4, AX
24、ADD SI, 2LOOP ONEMOV AX, 4C00HINT 21H方法方法1:利用寄存器传递参数的值。:利用寄存器传递参数的值。;子程序FIB;功能:求菲波那契数列数列的一项;入口参数:AXX i-1,BXX i-2;出口参数:AX X i X i-1+ X i-2FIBPROCADDAX, BXRET FIBENDPEND START.MODEL SMALL.DATAFIBLST DW 1, 1, 18 DUP (?)NDW20.CODESTART:MOV AX, DATAMOV DS, AXLEASI, FIBLSTMOV CX, NSUBCX, 2ONE:CALL FIBADD
25、SI, 2LOOP ONEMOV AX, 4C00HINT 21H方法方法2:利用寄存器传递参数的地址。:利用寄存器传递参数的地址。; 子程序FIB; 功能:求菲波那契数列数列的一项;入口参数:SIX i-2的段内偏移地址;出口参数:无(结果已由子程序存入数组内) FIBPROCPUSHAXMOVAX, SI;取XI-2ADDAX, SI+2;加XI-1MOVSI+4, AX;存入XIPOPAXRET FIBENDPEND START26. MODEL SMALL. DATAFIBLST DW 1, 1, 18 DUP(?)NDW20XI1DW?;存放存放XI-1XI2DW?;存放存放XI-2
26、XIDW?;存放存放XI. CODESTART:MOV AX, DATAMOV DS, AXLEA SI, FIBLST; 设置地址指针设置地址指针MOV CX, NSUBCX, 2; 设置计数器初值设置计数器初值ONE:MOVAX, SI+2MOVXI1, AX; X i-1置入置入XI1MOVAX, SIMOVXI2, AX; X i-2置入置入XI2CALL FIB; 调用子程序调用子程序MOVAX, XI; 取出计算结果取出计算结果X iMOV SI+4, AX; 置入置入FIBLST数组数组ADD SI, 2; 修改地址指针修改地址指针LOOP ONE; 循环控制循环控制MOV AX
27、, 4C00HINT 21H2变量(共享数据段)传递参数变量(共享数据段)传递参数 ;子程序子程序FIB;功能:计算菲波那契数列数列的一项;功能:计算菲波那契数列数列的一项;入口参数:;入口参数:XI1XI-1,XI2X I-2;出口参数:;出口参数:XIXI-1+X I-2FIBPROCPUSHAX;保护现场保护现场MOVAX, XI1 ;AXXI-1ADDAX, XI2;AXXI-1+XI-2MOVXI, AX;XI AXPOPAX;恢复现场恢复现场RET FIBENDPEND START . MODEL SMALL. DATA FIBLST DW 1, 1, 18 DUP(?) N DW
28、20.CODESTART: MOV AX, DATA MOV DS, AX LEA SI, FIBLST MOV CX, N SUB CX, 2ONE: PUSHAX ;为保存结果,在堆栈为保存结果,在堆栈“预留预留”单元单元 PUSH WORD PTR SI;XI-2入栈入栈 PUSH WORD PTR SI+2 ;XI-1入栈入栈 CALL FIB ;调用子程序,执行后堆栈状态调用子程序,执行后堆栈状态1 POPAX;从堆栈弹出结果,执行后堆栈状态从堆栈弹出结果,执行后堆栈状态4 MOV SI+4, AX ;把结果存入把结果存入FIBLST数组数组 ADD SI, 2 LOOP ONE M
29、OV AX, 4C00H INT 21H 3. 堆栈传递参数堆栈传递参数;子程序子程序FIB;功能:计算菲波那契数列数列的一项;功能:计算菲波那契数列数列的一项;入口参数:;入口参数: XI-1,X I-2在堆栈中在堆栈中;出口参数:;出口参数: X I在栈顶在栈顶FIBPROCPUSH BPMOV BP, SP;堆栈状态堆栈状态2 PUSH AXMOV AX, BP+4; 从堆栈取出从堆栈取出X I-1ADD AX, BP+6;AXX I-1+X I-2MOV BP+8, AX ; 结果存入堆栈结果存入堆栈 POP AXPOP BP; 恢复恢复BPRET 4; 返回,返回,SP+4, 执行后
30、堆栈状态执行后堆栈状态3FIBENDPEND START思考:思考:1。修改参数压栈的顺序,程序如何修改?。修改参数压栈的顺序,程序如何修改?2。改用堆栈传入参数,寄存器返回参数,程序如何修改?。改用堆栈传入参数,寄存器返回参数,程序如何修改?5.3.1 子程序嵌套 5.3.2 递归子程序 5.3.1 子程序嵌套 被调用的子程序在返回前又调用了其他子程序,称被调用的子程序在返回前又调用了其他子程序,称为为子程序嵌套子程序嵌套。 (也称过程嵌套(也称过程嵌套 Nest Procedure Call ) ;主程序主程序 . CALLSUBA ; .;子程序;子程序SUBA . CALLSUBB;
31、. RET; 子程序子程序SUBB . RET5.3.2 递归子程序 递归过程递归过程(Recursive Procedure):):一个直接或间接调用一个直接或间接调用自身的过程。自身的过程。如果一个问题可以分解为几个子问题,而这些子问如果一个问题可以分解为几个子问题,而这些子问题又和原问题有相同的算法时,递归过程是非常方便的表题又和原问题有相同的算法时,递归过程是非常方便的表达方式。达方式。递归过程可以使用递归过程可以使用堆栈传递参数堆栈传递参数,也可以用,也可以用寄存器寄存器传递参数传递参数或存储单元传递参数。或存储单元传递参数。 计算计算1 1N N自然数之和可以定义为:自然数之和可以
32、定义为:SUM(N)= SUM(N)= N=1N=1时,时,SUMSUM函数直接返回函数直接返回1 1。N1N1时,计算时,计算SUMSUM(N N)分成两步:)分成两步:(1)(1)计算计算SUMSUM(N-1N-1):设置入口参数为):设置入口参数为N-1N-1, 调用调用SUMSUM函数(调用自身)函数(调用自身) (2)(2)进行加法运算:进行加法运算:N+SUMN+SUM(N-1N-1) 也可以定义为:SUM( N ) = 1+2+3+ +N. MODELSMALL. STACK100;定义;定义100字节用作堆栈字节用作堆栈. CODETOTALDW?START:MOVCX, 3;
33、为子程序准备参数;为子程序准备参数CALLSUM;调用子程序;调用子程序SUMMOVCS: TOTAL, AX;保存结果;保存结果MOVAX, 4C00HINT21H;返回;返回;递归过程;递归过程SUM;入口参数;入口参数: CXN,出口参数,出口参数: AX=1N的和的和SUMPROCPUSHCX;保存入口参数(;保存入口参数(N)CMPCX, 1;判;判CX(N)是否为)是否为1JEBACK;CX(N)为)为1,转,转BACKDECCX;CX-1,为下一次调用准备参数,为下一次调用准备参数CALLSUM;递归调用,计算;递归调用,计算1N-1的和的和INCCX;恢复;恢复CX为为NADD
34、AX, CX;加到;加到AX中中JMPEXITBACK: MOVAX, 1;N=1时,通过时,通过AX返回返回1EXIT:POPCX;恢复入口参数;恢复入口参数RETSUMENDPENDSTART 这个程序使用寄存器进行参数的传递。这个程序使用寄存器进行参数的传递。 主程序中的主程序中的“CALL SUM”指令执行了一次。指令执行了一次。 子程序子程序SUM中的指令中的指令“CALLSUM”执行了执行了2次。次。 CALL指令先后共执行了指令先后共执行了3次,先后次,先后3次进入同一个子程序次进入同一个子程序 SUM。递归调用和返回示意图递归调用和返回示意图 编写递归程序时,必须保证要有一个终
35、止条件,而且,编写递归程序时,必须保证要有一个终止条件,而且,经过有限次执行这个子程序,这个终止条件能够实现。否则,经过有限次执行这个子程序,这个终止条件能够实现。否则,程序将产生程序将产生“死循环死循环”或者其它的错误状态。或者其它的错误状态。 主程序-MOV CX, 3CALL SUMMOV CS:TOTAL, AX-DEC CXCALL SUMINC CXADD AX, CX-RET子程序SUM(1)-DEC CXCALL SUMINC CXADD AX, CX-RET子程序SUM(2)子程序SUM(3)-MOV AX, 1-RETAX=6CX=3AX=?CX=3AX=?CX=2AX=?
36、CX=1AX=1CX=1AX=3CX=2. MODELSMALL. STACK100;定义;定义100字节用作堆栈字节用作堆栈. CODETOTAL DW?START:PUSHAX; 为返回结果预留单元,为返回结果预留单元,; AX中内容无意义中内容无意义MOVCX, 3;为子程序准备参数;为子程序准备参数PUSHCX;入口参数压入堆栈;入口参数压入堆栈CALLSUM;调用子程序;调用子程序SUMPOPCS: TOTAL;保存结果保存结果MOVAX, 4C00HINT21H;返回;返回高级语言中的递归程序普遍使用堆栈传递参数。高级语言中的递归程序普遍使用堆栈传递参数。上面的例子改写如下:上面的
37、例子改写如下:;递归过程递归过程SUM;入口参数:;入口参数:SP+2N,出口参数:,出口参数:1N的和在堆栈栈顶的和在堆栈栈顶;影响寄存器:;影响寄存器:BP, AX,CXSUMPROCPUSHBPMOVBP, SP;根据;根据BP访问堆栈中的参数访问堆栈中的参数 PUSH AX PUSH CXMOVCX, BP+4;取出入口参数;取出入口参数N,存入,存入CXCMPCX, 1;N=1 ?JEBACK;N=1,转,转BACKDECCX;CX-1,为下一次调用准备参数,为下一次调用准备参数PUSHAX ;为保留下一次调用结果预留单元,;为保留下一次调用结果预留单元,AX中内容无意义中内容无意义
38、PUSHCX;入口参数(;入口参数(N-1)压入堆栈)压入堆栈CALLSUM;递归调用,计算;递归调用,计算1N-1的和的和POPAX ;从堆栈弹出子程序运算结果;从堆栈弹出子程序运算结果(1N-1的和的和)ADDAX, BP+4;把;把N加到加到AX中,得到中,得到1N的和的和MOVBP+6, AX;1N的和存入堆栈预留单元的和存入堆栈预留单元JMPEXIT BACK: MOVWORD PTRBP+6, 1;N=1时,返回时,返回1 EXIT: POP CX POP AX POPBPRET2 SUMENDP ENDSTART例:将字符串反序输出例:将字符串反序输出 mov bx, offse
39、t strmov bx, offset str push bxpush bx call reverscall revers pop bxpop bx mov dl, bx mov dl, bx mov ah, 2 mov ah, 2 int 21h int 21h revers proc near revers proc near push bp push bp mov bp, sp mov bp, sp mov bx, bp+4 mov bx, bp+4 mov al, bx mov al, bx cmp al, $ cmp al, $ je return je return inc bx
40、inc bx push bxpush bx call reverscall revers pop bxpop bx mov dl, bx mov dl, bx mov ah, 2 mov ah, 2 int 21h int 21h return: return: pop bppop bpret ret ;不能写成:;不能写成: ret 2 (ret 2 (?) ) revers endp revers endpn上机上机4:按照学号的顺序输入:按照学号的顺序输入20个学生的成个学生的成绩(绩(0100)存入一维数组)存入一维数组SCORE,然后,然后统计每一个学生的名次并在屏幕输出。统计每一个
41、学生的名次并在屏幕输出。要求:要求:1、显示形式为、显示形式为“ 学号学号 :名次:名次 ”; 2、输入每个成绩、统计每个成绩的名、输入每个成绩、统计每个成绩的名次、显示结果数据(学号或名次)分别定义次、显示结果数据(学号或名次)分别定义为子程序;为子程序; 3、传参方式:寄存器或堆栈。、传参方式:寄存器或堆栈。5.4.15.4.1 段的完整定义段的完整定义 5.4.2 5.4.2 简化段定义简化段定义 5.4.3 5.4.3 创建多模块程序创建多模块程序1.一个应用程序的开发由一个小组,而不是一个人完成的。 每个程序员编制的源程序自然地构成一个(或者是多个)源程序文件。每个程序员编制的源程序
42、自然地构成一个(或者是多个)源程序文件。 每个源程序文件内包括了一个或多个每个源程序文件内包括了一个或多个“子程序子程序”。这些源程序文件常常被称为。这些源程序文件常常被称为模块模块(Module)。)。 有时候也把位于同一个源程序有时候也把位于同一个源程序文件内的各个文件内的各个“子程序子程序”,或者一个,或者一个“数据段数据段”定定义等称为模块。义等称为模块。 一个可供实际使用的应用程序,它的源程序基本上都是由若干个程序文件组成的。2.源程序文件规模过大,会造成管理,维护上的困难。源程序文件规模过大,会造成管理,维护上的困难。 即便是一个人开发的应用程序,也应把一个大的程序分解成多个源代码
43、文件。即便是一个人开发的应用程序,也应把一个大的程序分解成多个源代码文件。 这样,每个文件长度适中,容易阅读和维护,如果修改了某个模块,只需对该模块重这样,每个文件长度适中,容易阅读和维护,如果修改了某个模块,只需对该模块重新汇编,然后再和其他模块链接,无须把每个模块重新汇编一次。新汇编,然后再和其他模块链接,无须把每个模块重新汇编一次。 3.许多许多“子程序子程序”可以重复使用,独立为一个源程序文件便于可以重复使用,独立为一个源程序文件便于“子程序库子程序库”的管理。的管理。 5.4.15.4.1 段的完整定义段的完整定义段名段名SEGMENT 对齐方式对齐方式 组合方式组合方式 使用类型使
44、用类型类类语句语句段名段名ENDS完整的段定义格式如下: 方括号括起来的内容称为方括号括起来的内容称为“可选项可选项”,可以由使用者根据,可以由使用者根据需要决定。需要决定。 1. 对齐方式对齐方式一个新的段开始时,对齐方式通知连接程序怎样确定这个段一个新的段开始时,对齐方式通知连接程序怎样确定这个段的起始地址。对齐方式可以有下面几种选择:的起始地址。对齐方式可以有下面几种选择:nBYTE 使本段从前面段结束之后的下一个字节地址开始。使本段从前面段结束之后的下一个字节地址开始。nWORD使本段从前面段结束之后的下一个字地址开始。使本段从前面段结束之后的下一个字地址开始。nDWORD使本段从前面
45、段结束之后的下一个双字地址开始。使本段从前面段结束之后的下一个双字地址开始。nPARA使本段从前面段结束之后的下一个节的地址(使本段从前面段结束之后的下一个节的地址(16的的整数倍)开始存放,是默认的对齐方式。如果没有出现对齐方式整数倍)开始存放,是默认的对齐方式。如果没有出现对齐方式说明,自动按照说明,自动按照“PARA”来对齐。来对齐。nPAGE使本段从前面段结束之后的下一个页地址(使本段从前面段结束之后的下一个页地址(256的整的整数倍)开始。数倍)开始。对齐方式对齐方式段基址段基址起始偏移地址起始偏移地址段间空隙(字节)段间空隙(字节)BYTE3020H0005H0WORD3020H0
46、006H1DWORD3020H0008H3PARA3021H0000H11PAGE3030H0000H251 假设前面一个段的结束地址为假设前面一个段的结束地址为30204H,用不同对齐方式的结果如下表所示。用不同对齐方式的结果如下表所示。2. 组合方式组合方式通知连接程序以何种方式处理组合方式通知连接程序以何种方式处理不同程序文件中不同程序文件中名称相名称相同的段。组合方式可以有下面几种选择:同的段。组合方式可以有下面几种选择:lPRIVATEPRIVATE这个段不与其他同名段合并,每个段都有自己的段基这个段不与其他同名段合并,每个段都有自己的段基地址,是默认的组合方式。地址,是默认的组合方
47、式。lPUBLICPUBLIC将该段和其他名称相同,组合方式同为将该段和其他名称相同,组合方式同为“PUBLIC”PUBLIC”的的段前后连接在一起,合并成一个段,产生一个新的段基地址,所有段前后连接在一起,合并成一个段,产生一个新的段基地址,所有标号的偏移地址都进行调整。标号的偏移地址都进行调整。lSTACKSTACK将所有的将所有的STACKSTACK段连接为一个新的段连接为一个新的STACKSTACK段,类似于段,类似于PUBLICPUBLIC。lCOMMON COMMON 所有同名的段使用相同的起始地址,这样,这些段所有同名的段使用相同的起始地址,这样,这些段“共享共享”这一片共同的存
48、储区间。这一片共同的存储区间。lAT AT 表达式表达式段的起始地址由表达式的值来指定,用于设定一些特段的起始地址由表达式的值来指定,用于设定一些特殊的段。殊的段。使用(USE)类型 使用类型仅仅使用于使用使用类型仅仅使用于使用8038680386以上指令系统的汇编程序(例如,以上指令系统的汇编程序(例如,在程序首部使用在程序首部使用.386.386说明符)说明符) 使用使用1616位寻址方式时,段内偏移地址位寻址方式时,段内偏移地址1616位,每个段最大位,每个段最大64KB64KB。运。运行在实模式下的程序使用行在实模式下的程序使用1616位段。位段。 使用使用3232位寻址方式时,段内偏
49、移地址为位寻址方式时,段内偏移地址为3232位,一个段最大可达位,一个段最大可达4GB4GB。运行在保护模式下的程序使用运行在保护模式下的程序使用3232位段。位段。 使用使用8038680386以上以上CPUCPU并且工作在实模式下的程序不能遗漏并且工作在实模式下的程序不能遗漏“USE16”USE16”说明。说明。例如:例如: mul ax, 5 imul ax, bx, -14.类名称一个段除了有一个段名之外,还可以有一个类名称。一个段除了有一个段名之外,还可以有一个类名称。类名称是以引号引起来的任意字符串。类名称是以引号引起来的任意字符串。类名称相同的段被放在一片相邻的存储区间,但不会类
50、名称相同的段被放在一片相邻的存储区间,但不会合并成同一个段。合并成同一个段。 52CSEG SEGMENT CODE ASSUME CS: CSEG, DS: DATA1 ASSUME SS: MYSTACKMAINPROCMOVAX, DATA1 MOVDS, AXMOVAX, SEG VAL2 MOVES, AX MOVAX, VAL1 LEASI, VAL2 MOVBX, ES:SI CMP AX, BXJB L1 CALLFAR PTR SUB1 L1:MOV AX, 4C00H INT21HMAINENDPCSEGENDS 例例5.5 本例中有两个代码段、两个数据段和一个堆栈段,本例
51、中有两个代码段、两个数据段和一个堆栈段,SUBCODESEGMENTCODEASSUME CS:SUBCODE,DS:DATA2,SS: MYSTACKSUB1PROCFAR;过程体RETSUB1ENDPSUBCODEENDS; = DATA1SEGMENTDATA ; 类名称为DATAVAL1 DW1001HDATA1ENDS; = DATA2SEGMENTDATA ; 类名称为DATAVAL2 DW1002HDATA2ENDS; =MYSTACK SEGMENT PARA STACK STACKDB100H DUP(?)MYSTACK ENDS; = END MAIN经过链接,从对应的经过
52、链接,从对应的MAP文件中可以看到程序有两个代码段、文件中可以看到程序有两个代码段、两个数据段和一个堆栈段:两个数据段和一个堆栈段: Start Stop Length Name Class 00000H 00022H 00023H CSEG CODE 00030H 00030H 00001H SUBCODE CODE 00040H 00041H00002H DATA1 DATA 00050H 00051H 00002H DATA2 DATA 00060H 0015FH 00100H MYSTACK STACK由于使用默认的由于使用默认的“PARA”对齐方式,段间有间隙。对齐方式,段间有间隙。
53、同类型名的段相邻存放。同类型名的段相邻存放。 如果将如果将SUBCODE的段名改为的段名改为CSEG,将,将DATA2段名改为段名改为DATA1,则链接器创建的则链接器创建的MAP文件是这样的:文件是这样的: Start Stop Length Name Class 00000H 00023H00024HCSEG CODE 00030H 00033H00004H DATA1 DATA 00040H 0013FH 00100H MYSTACK STACK 由此可见,在同一个程序文件中,相同段名的代码段合并成一个段,由此可见,在同一个程序文件中,相同段名的代码段合并成一个段,两个同名的数据段也合并
54、成一个段。两个同名的数据段也合并成一个段。5.4.25.4.2 简化段定义简化段定义 1 内存模式定义伪指令使用简化段定义时,需要首先定义所使用的内存模式等参数。使用简化段定义时,需要首先定义所使用的内存模式等参数。格式如下:格式如下:.MODEL .MODEL 内存模式内存模式 ,语言类型,语言类型 ,操作系统类型,操作系统类型 , ,堆栈选项堆栈选项 2 近数据段定义伪指令.DATA .DATA?.CONSTl.DATA .DATA 创建一个数据段,段名是创建一个数据段,段名是_DATA_DATA,主要定义有初值的变量。,主要定义有初值的变量。l.DATA? .DATA? 用来定义没有初值
55、的变量,段名为用来定义没有初值的变量,段名为_BSS_BSS。定义在。定义在.DATA?.DATA?段段的无初值变量不占用可执行文件的空间。的无初值变量不占用可执行文件的空间。l.CONST .CONST 定义只读数据段,段名是定义只读数据段,段名是_CONST_CONST。 一个源文件中可以包含多个由一个源文件中可以包含多个由.DATA.DATA、.DATA?.DATA?和和.CONST.CONST定义的数定义的数据段,据段,TASMTASM自动将其合并为一个物理段,使它们具有相同的段基址。自动将其合并为一个物理段,使它们具有相同的段基址。 3 远数据段定义伪指令 .FARDATA 段名和.
56、FARDATA? 段名分别用来定义已有初值的数据段和没有初值的数据段。如果段分别用来定义已有初值的数据段和没有初值的数据段。如果段名缺省,默认段名分别为名缺省,默认段名分别为FAR_DATA和和FAR_BSS。通过指定段名,。通过指定段名,可在源文件中定义多个独立的数据段。远数据段不会被合并。可在源文件中定义多个独立的数据段。远数据段不会被合并。 4 代码段定义伪指令.CODE 段名 如果内存模式为如果内存模式为SMALL,.CODE伪指令不需要给出伪指令不需要给出“段名段名”,编译器生成一个名为编译器生成一个名为_TEXT的代码段,对于多个代码段的内存模式,的代码段,对于多个代码段的内存模式
57、,则应该指明段名。则应该指明段名。 5 堆栈段定义伪指令.STACK堆栈大小定义一个堆栈段,缺省大小为定义一个堆栈段,缺省大小为1024字节,段名为字节,段名为STACK。6 TASM预定义符号 CODE和DATACODE表示由表示由.CODE定义的代码段的段名,在指令中表示段基址。定义的代码段的段名,在指令中表示段基址。DATA表示由表示由.DATA、.DATA?和和.CONST定义的数据段的段名,在定义的数据段的段名,在指令中表示段基址。指令中表示段基址。注意:使用简化段定义时,没有段结束伪指令。一个新的段开始,就注意:使用简化段定义时,没有段结束伪指令。一个新的段开始,就意味着上一个段到
58、此结束。意味着上一个段到此结束。 59.MODEL MEDIUM ; 内存模式为中型内存模式为中型.STACK 100H.DATA MSG1 DB FIRST MESSAGE”, 0DH, 0AH, $.DATA?;定义第二个数据段,未初始化定义第二个数据段,未初始化XDB10 DUP (?).CODEMAIN PROCMOVAX, DATAMOVDS, AXLEA DX, MSG1CALLFAR PTR DISP; 远调用远调用MOV AX, 4C00HINT 21HMAIN ENDP例例5.6 本例中有两个代码段。本例中有两个代码段。.CODE OTHER ;再定义一个代码段再定义一个代码
59、段DISP PROC FAR MOVAH, 9 INT21H RETDISP ENDPEND MAIN ; 入口地址入口地址MAIN 经过链接,从对应的经过链接,从对应的MAP文件中可以看到程序有两个代码文件中可以看到程序有两个代码段、两个数据段和一个堆栈段:段、两个数据段和一个堆栈段:Start Stop Length Name Class00000H 00011H 00012H EX506_TEXT CODE00012H 00016H 00005H OTHER CODE00020H 0002FH 00010H _DATA DATA00030H 0012FH 00100H STACK STA
60、CK00130H 00130H 00001H _BSS BSS 用用TD观察这个程序,发现观察这个程序,发现_DATA 和和_BSS段使用相同的段使用相同的段基址,被合并为一个物理段。段基址,被合并为一个物理段。5.4.3创建多模块程序创建多模块程序 模块模块 :由不同的程序员编写,以不同的文件名存放在磁盘中,由不同的程序员编写,以不同的文件名存放在磁盘中,这样的源程序文件称为这样的源程序文件称为“模块模块” 模块内部由若干个段的定义组成,其中仅有一个模块包含模块内部由若干个段的定义组成,其中仅有一个模块包含有主程序,其它的模块包含了一些子程序和数据段、堆栈有主程序,其它的模块包含了一些子程序
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《麦克利夫综合症》课件
- (3)-专题17 梳理说明顺序(讲义)
- 《理论探讨》课件
- 贯彻领导力提升组织效能讲义
- 南方科技大学《影视创作实践》2023-2024学年第二学期期末试卷
- 昆明艺术职业学院《建筑历史与文化》2023-2024学年第二学期期末试卷
- 山东省博兴县2024-2025学年高三下4月模拟考试语文试题含解析
- 西北政法大学《市政工程估价课程设计》2023-2024学年第一学期期末试卷
- 玛纳斯县2025届三年级数学第二学期期末经典试题含解析
- 乌鲁木齐职业大学《GMDSS英语听力与会话》2023-2024学年第一学期期末试卷
- Q∕GDW 12154-2021 电力安全工器具试验检测中心建设规范
- 第四章 金融监管(商业银行管理-复旦大学)
- 初中文言文专项训练十篇(含答案)
- 中波发射台搬迁建设及地网铺设、机房设备的安装与调整实践
- 煤矿顶板事故防治(1)
- 影像诊断学-—-总论PPT课件
- 漏电保护器试跳记录表
- (完整word版)古籍样式排版模板
- 调Q技术与锁模技术(课堂PPT)
- 快速制作会议座次表、会场座位安排
- 公司财务报表模板(word版本)
评论
0/150
提交评论