(一)、子程序框架
PROC_NAME PROC [NEAR/FAR] //如果不加以指定类型,汇编程序默认解释为NEAR类型....RET //最后一条被执行的必然是RET指令,RET具体格式由子程序的类型确定...PROC_NAME ENDP(二)、传参方式:
1.种类:
高级语言程序多使用堆栈传递方式与数据区传递方式。
2.传参时程序员在主函数与子函数之间需要约定的:
(三)、子程序进行主程序的现场保护:
CPU现场(执行现场):当主程序调用子程序时,有关寄存器、标志位当时的状态。
习惯用 PUSH指令保护现场,用POP指令恢复现场。
二、设计示例
题目:试设计一程序,完成两个长补码的加法,其中两个长补码的长度是相同的,并且采用低地址存放低位,
高地址存放高位的方式存储。对于加法功能,使用子程序实现,两个长补码的起始地址、长补码的长度(以字为单位)、
运算结果的起始地址均有由主程序以入口参数的形式传给子程序;运算是否溢出使用一个字节标志来表示,
00H表示运算无溢出,0FFH表示运算溢出,子程序将此溢出标志以出口参数的形式传递给主程序。
(一)寄存器传递方式
约定:(具体约定寄存器与参数间的对应关系)本例中约定,SI、DI寄存器传递两个长补码的起始偏移量(认为两个
长补码位于同一数据段,且段基值保存到DS中),CX寄存器传递补码长度,BX寄存器传递运算结果的起始偏移量
(认为段基值已保存在DS中),约定使用DL寄存器传递溢出标志。
DATA SEGMENTVAR1 DW 5482H,669EH,02C7H,14B2H,0C254HVAR2 DW 8C2BH,0C24CH,0AB12H,357AH,41A5HLEN EQU $-VAR2SUM DW LEN DUP(0) ;用于保存运算结果OVR DB ? ;用于保存溢出标志DATA ENDSSTACK1 SEGMENT STACK ;子程序设计必须使用堆栈 DW 40H DUP(0)STACK1 ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK1BEGIN:MOV AX,DATA MOV DS,AX MOV SI,VAR1 ;传递入口参数 MOV DI,VAR2 MOV CX,LEN MOV BX,SUM CALL LONGADD MOV OVR,DL ;保存出口参数(这行我出错) MOV AH,4CH INT 21HLONGADD PROC PUSH AX PUSHF CLCL1: MOV AX,[SI] ADC AX,[DI] MOV [BX],AX PUSHF ADD SI,2 ADD DI,2 ADD BX,2 POPF LOOP L1 JO L2 MOV DL,0 JMP L3L2: MOV DL,0FFHL3: POPF POP AX RNTLONGADD ENDPCODE ENDSEND BEGIN(二)堆栈传递方式
约定:(只需要约定入口参数的入栈顺序与出口参数的出栈顺序)约定主程序按照被加数起始偏移量、
加数起始偏移量、被加数与加数的长度、运算结果起始偏移量的顺序将入口参数入栈。
约定子程序的出口参数覆盖最先入栈的入口参数(因为只有一个出口参数)
DATA SEGMENTVAR1 DW 5482H,669EH,02C7H,14B2H,0C254HVAR2 DW 8C2BH,0C24CH,0AB12H,357AH,41A5HLEN EQU $-VAR2SUM DW LEN DUP(0) ;用于保存运算结果OVR DB ? ;用于保存溢出标志DATA ENDSSTACK1 SEGMENT STACK ;子程序设计必须使用堆栈 DW 40H DUP(0)STACK1 ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK1BEGIN:MOV AX,DATA MOV DS,AX LEA SI,VAR1 PUSH SI ;-2 LEA SI,VAR2 PUSH SI ;-2 LEA SI,LEN PUSH SI ;-2 LEA SI,SUM PUSH SI ;-2 CALL LONGADD POP DX MOV OVR,DL MOV AH,4CH INT 21HLONGADD PROC PUSH BP ;-2 MOV BP,SP PUSHF PUSH AX PUSH BX PUSH CX PUSH SI PUSH DI MOV BX,[BP+4] ;加4的原因请看下面图解 MOV CX,[BP+6] MOV DI,[BP+8] MOV SI,[BP+10] CLCL1: MOV AX,[SI] ADC AX,[DI] MOV [BX],AX PUSHF ADD SI,2 ADD DI,2 ADD BX,2 POPF LOOP L1 JO L2 MOV [BP+10],0 JMP L3L2: MOV [BP+10],0FFHL3: POP DI POP SI POP CX POP BX POP AX PUSHF POP BP RET 6 ;返回参数覆盖了最高地址的入口参数,使用堆栈传参时务必使用RET N 清楚堆栈内的参数 LONGADD ENDP CODE ENDS END BEGIN图解+4原因:
(三)数据区传递方式
约定:(需指明各参数在数据区的顺序、占据的空间)约定按照变量定义的顺序,子程序也按照这个顺序获得入口参数。
各参数均占一个字的空间。
DATA SEGMENTVAR1 DW 5482H,669EH,02C7H,14B2H,0C254HVAR2 DW 8C2BH,0C24CH,0AB12H,357AH,41A5HLEN EQU $-VAR2SUM DW LEN DUP(0) ;用于保存运算结果OVR DB ? ;用于保存溢出标志IPAR DW 4 DUP(0) ;入口参数数据区OPRA DW 1 ;出口参数数据区DATA ENDSSTACK1 SEGMENT STACK ;子程序设计必须使用堆栈 DW 40H DUP(0)STACK1 ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK1BEGIN:MOV AX,DATA MOV DS,AX LEA SI,IPAR LEA DI,OPRA MOV WORD PTR [SI],OFFSET VAR1 MOV WORD PTR 02H[SI],OFFSET VAR2 MOV WORD PTR 04H[SI],OFFSET LEN MOV WORD PTR 06H[SI],OFFSET SUM CALL LONGADD MOV DL,BYTE PTR [DI] MOV OVR,DL MOV AH,4CH INT 21HLONGADD PROC PUSHF PUSH AX PUSH BX PUSH CX PUSH DX PUSH SI PUSH DI MOV DI,02H[SI] MOV CX,04H[SI] MOV BX,06H[SI] MOV SI,[SI] CLCL1: MOV AX,[SI] ADC AX,[DI] PUSHF MOV [BX],AX ADD SI,2 ADD DI,2 ADD BX,2 POPF LOOP L1 JO L2 MOV DL,0 JMP L3L2: MOV DL,0FFHL3: POP DI MOV [DI],DX POP SI POP DX POP CX POP BX POP AX POPF RETLONGADD ENDPCODE ENDSEND BEGIN