本章学习要点: (1)子程序的编写格式 (2)子程序调用时的参数传递方法 (3)嵌套及递归子程序 一、过程定义语句(process) 利用过程定义伪指令语句,可把程序片段说明为具有 近类型或远类型的过程,并且能给过程取一个名字。 过程定于语句的格式如下: 过程名 PROC [NEAR | FAR] … 过程名 ENDP 过程的类型在过程定义开始语句PROC中指定; 过程可以被指定位近(NEAR)类型,也可以被指定为 远类型。如果不指定,则通常默认为近类型; 定义一个过程的开始语句PROC和结束语句ENDP前 使用的过程名称必须一致,从而保持配对。
像普通标号一样,过程名具有段值、偏移和类型这三个属性。 过程名的段值和偏移是对应过程入口(过程定义开始伪指令语 句后的指令语句)的段值和偏移。 例:下面程序片段运行后,AL=?,BL=?。 XOR AL , AL CALL SUBS MOV BL , AL CALL SUBS RCR AL , 1 HLT ;停机,halt SUBS PROC NEAR NOT AL JS NEXT STC ;CF=1, SeT Cf = 1 NEXT : RET SUBS ENDP
例:用程序调用的方法,完成一个把16位二进制数转换为4位 十六进制ASCII码的转换程序。 子程序说明:入口参数:DX=欲转换的二进制数; DS:BX=存放转换所得ASCII码串的缓冲区首地址,转换后的 ASCII码串按照高位到低位的次序存放在指定的缓冲区中。 HTASCS PROC RET MOV CX , 4 HTASCS ENDP HTASCS1: ROL DX , 1 HTOASC PROC NEAR ROL DX , 1 AND AL , 0FH ROL DX , 1 ADD AL , 30H ROL DX , 1 CMP AL , 39H MOV AL , DL JBE HTOASC1 CALL HTOASC ADD AL , 7 MOV [BX] , AL HTOASC1: RET INC BX HTOASC ENDP LOOP HTASCS1
二、主程序与子程序间的参数传递 主程序在调用子程序时,往往要向子程序传递一些参数;同样 地,子程序运行后夜经常要把一些结果传会给主程序。主程序 和子程序之间的这种信息传递称为参数传递。 有多种参数传递的方法: (1)寄存器传递法 (2)约定内存单元传递法 (3)堆栈传递法 (4)其它方法 1.利用寄存器传递参数 利用寄存器传递参数就是把参数放在约定的寄存器中。这种方 法适用于传递参数较少的情况。
例:写一个大写字母转换为小写字母的子程序 ;子程序名:UPTOLW ;功能:大写字母转换为小写字母 ;入口参数:AL=字符的ASCII码 ;出口参数:AL=字符的ASCII码 ;说明:如字符为大写字母,则转换为小写,其它字符不变。 UPTOLW PROC PUSHF ;保护各标志 CMP AL , A JB UPTOLW1 CMP AL , Z JA UPTOLW1 ADD AL , 20H UPTOLW1:POPF ;恢复各标志 RET UPTOLW ENDP
2.利用约定存储单元传递参数 在传递参数较多的情况下,可利用约定的内存变量来传递参数。 例:写一个实现32位数相加的子程序 ;子程序名:MADD ;功能:32位数相加 ;入口参数:DATA1和DATA2缓冲区中分别存放要相加的数 ;出口参数:DATA3
缓冲区存放结果 ;说明: ;(1)32位数据的存放次序采用“高高低低”原则 ;(2)可能产生的进位放在DATA3开始的第5字节中
MADD PROC PUSH AX ;为什么会把AX,CX,SI压入栈? PUSH CX PUSH SI MOV CX , 2 XOR SI , SI ;CF也会被清0 MADD1:MOV AX , WORD PTR DATA1[SI] ADC AX , WORD PTR DATA2[SI] MOV WORD PTR DATA3[SI] , AX INC SI INC SI POP SI LOOP MADD1 POP CX MOV AL , 0 POP AX ADC AL , 0 RET MOV BYTE PTR [DATA3 + 4] , AL MADD ENDP
3.利用堆栈传递参数 (1)如果利用堆栈传递入口参数,那么主程序在调用子程序 之前,把需要传递的参数依次压入堆栈,子程序从堆栈中取入 口参数; (2)如果使用堆栈传递出口参数,那么子程序返回前,把需 要返回的参数存入堆栈,主程序在堆栈中取出口参数。 例:写一个测量字符串长度的子程序,设字符串以0为结束标 志。 ;子程序名:STRLEN ;功能:测量字符串长度 ;入口参数:字符串起始地址的段值和偏移放在堆栈中 ;出口参数:AX=字符串长度。
STRLEN PROC PUSH BP MOV BP , SP PUSH DS PUSH SI MOV DS , [BP + 6] MOV SI , [BP + 4] MOV AL , 0 STRLEN1 : CMP AL , [SI] JZ STRLEN2 INC SI JMP STRLEN1 STRLEN2: MOV AX , SI SUB AX , [BP + 4] POP SI
POP DS POP BP RET STRLEN ENDP
主程序调用这个子程序的代码片段如下: MOV AX , SEG STR PUSH AX MOV AX , OFFSET STR PUSH AX CALL STRLEN MOV LEN , AX
当然,除了上面提及的3种方式外, 如果过程和调用程序在同一文件(同 一程序块中,则过程可直接访问模块 中的变量。
随着指令的丰富、子程序的引入,汇编语言的表达也越来越灵 活。为了方便地组织数据,引入了结构伪操作STRUC。 STRUC可以把不同类型的数据放在同一个结构里,方便处理。 a). 结构类型说明格式为: structure_name STRUC … ;DB、DW、DD等伪操作 structure_name ENDS 注意:ENDS之前为结构名,注意与段结束相区别。 例如:下列语句说明了一个名STUDENT的结构类型: STUDENT STRUC ID DW ? SCORE DB 0 NAME DB ABCDEFGH STUDENT ENDS 但是,定义一个结构类型的时候不进行任何存储器分配,只有 在定义结构变量时才进行存储分配。
b). 结构变量的定义 格式是: [变量名] 结构名 < [字段值表]> 例:Lisi STUDENT <103 , 88 , LI > ;三个字段重新赋值 Wangwu STUDENT <104 ,, WANG > ;字段SCORE仍用缺省 值 Zhangsan STUDENT <> ;三个字段均用缺省初值 Team STUDENT 50 DUP (<>) ;定义50个结构变量,初值不变 在定义结构变量时,如果某个字段有多值,就不能给该字段重 新赋初值(定义时存在“DUP”, “ , , , ”等)。 c). 访问方式 访问方式:结构变量名.结构字段名 该变量的地址实质少年宫是结构变量地址的偏移与相应字段偏 移值之和。 例:Zhangsan.ID ;访问张三的学号,实际上是直接寻址 还可 …… 此处隐藏:1462字,全部文档内容请下载后查看。喜欢就下载吧 ……