| 过程定义语句:PROC 和ENDP必须有名字,两者成对出现. procedure_name PROC [ NEAR | FAR ] ;要说明是NEAR过程或FAR过程. ... RET ;RET 返回指令必须与[ NEAR | FAR ] 对应 procedure_name ENDP 注:主程序和所调用的过程在同一代码段中,则定义说明为NEAR属性 主程序和所调用的过程不在同一代码段中,则定义说明为FAR属性 过程文档说明: 1.过程名 2.功能说明 3.占用寄存器、工作单元说明 4.输入参数说明 5.输出参数说明 现场保护及现场恢复的两种方法: 1.利用PUSH指令将过程要占用的寄存器的内容保存在堆栈中,恢复时用POP指令从栈中取出. 如果在主程序用PUSH指令保护寄存器,则要在主程序中用POP指令恢复寄存器. 如果在过程中用PUSH指令保护寄存器,则要在过程中用POP指令恢复寄存器. SUB1 PROC NEAR ;本例在过程中使用PUSH和POP PUSH AX ;入栈保护 [into stack to protect] PUSH BX PUSH DX ... POP DX ;出栈恢复 [out stack to restore] POP BX POP AX RET SUB1 ENDP 2.利用数据传送指令将过程要占用的寄存器的内容保存到指定的内存单元,恢复时再取回到相应的寄存器中. BUFFER DW 10 DUP(?) ;指定的内存单元 [specified memory block] ... SUB1 PROC NEAR MOV DI , OFFSET BUFFER ;将寄存器存入到内存单元保护 [save memory block to protecte register] MOV [DI] , AX MOV [DI+2] , BX MOV [DI+4] , DX ... MOV SI , OFFSET BUFFER ;从内存单元取回到相应的寄存器[restored register from memory block] MOV AX , [SI] MOV BX , [SI+2] MOV DX , [SI+4] RET SUB1 ENDP 主程序和过程间参数传递的三种方法:寄存器传递、堆栈传递、存储器传递 调用过程前,必须把操作中的加工处理数据传送给过程,这些加工处理数据称为输入参数. 返回主程序前,把本次操作的最终结果传递给主程序,这些加工处理所得的结果称为输出参数.
A:寄存器传递 <详细信息> | SOURCE DB d1,d2,...,dn ;源数据 [source data block] LENT EQU $ - SOURCE ;源数据长度 [length of souce data] DEST DB LENT DUP(?) ;目的内存单元 (无数据) code SEGMENT ;程序演示将SOURCE中的内容逐个传送到DEST中,以下主程序及过程均在同一个代码段内. PUSH SI、DI、CX ;入栈保护 SI、DI、CX等寄存器 [into stack to protect SI、DI、CX register] LEA SI , SOURCE ;设置参数值 [set parameters] LEA DI , DEST MOV CX , LENT CALL MOVTOR ;段内直接调用 [call procedure] POP SI、DI、CX ;出栈恢复SI、DI、CX等寄存器 [restore SI、DI、CX register from stack] RET ; 过程名:MOVTOR. ; 功能:完成数据块传递. ; 输入参数:SI=源块首地址 DI=目的块首地址 CX=数据块长度. ; 输出参数:在内存单元DEST开始存放传入的数据. MOVTOR PROC NEAR ;because the procedure define in same code_segment, so use NEAR property LOP1: MOV AL , [SI] ;循环体,每次通过AL传递一个字节[pass AL move one byte to destination once] MOV [DI] , AL INC SI INC DI LOOP LOP1 ;CX=CX-1, LOOP instruction compare CX register, if not zero then jump,else quit cycle RET MOVTOR ENDP ... code ENDS |
B:堆栈传递 <详细信息> | data SEGMENT ARYA DB a1,a2,...,an SUMA DW ? data ENDS stack SEGMENT PARA STACK 'STACK' TAK DB 100 DUP(?) TOP DB ? stack ENDS code SEGMENT ;程序演示将数组ARYA元素加和后存入SUMA中. ASSUME CS: code , DS: data , SS:stack main: ... MOV AX , (SUMA-ARYA) ;参数1进栈: ARAY数组元素个数. PUSH AX ;SP-2←参数1, SP=SP-2 MOV AX , OFFSET ARYA ;参数2进栈: ARAY数组首地址. PUSH AX ;SP-2←参数2, SP=SP-2 ;段间直接调用intersegmental call [First protect CS and IP register (4Bytes) to stack, whereafter call SUM] CALL FAR PTR SUM ;SP-2←CS, SP=SP-2; SP-2←IP, SP=SP-2 ... code ENDS ; Procedure Name:SUM /*因不在同一个代码段内,所以过程定义使用FAR属性*/ ; Function:完成对数组元素求和 ; Input parameters:保存主程序所定义的堆栈中 ; Output parameters:求和的结果保存在指定的数据区SUMA存储单元中. proce SEGMENT ASSUME CS : proce , DS : data , SS : stack SUM PROC FAR ;because the procedure define in different code_segment, so use FAR property ;into stack to protect register, [With the addition of 1 Flags ,it's Total 10 Bytes] SP=SP-10 PUSH AX、BX、CX、BP PUSHF ;because arithmetic sum will effect Flag,so protect Flag. MOV BP , SP ;取得当前SP栈顶地址,即BP指向栈顶. MOV CX ,[BP+16] ;取得参数1:数组个数 [注:0~2:Flag,2~10:REG,10~12:IP,12~14:CS,14~16:参2,16~18:参1] MOV BX ,[BP+14] ;取得参数2: 数组ARYA首地址. MOV AX , 0 LOP1: ADD AL , [BX] INC BX ADC AH,0 LOOP LOP1 MOV [BX] , AX ;循环加和完后, [BX]即指向SUMA变量地址. POPF ;restore Flag from stack,FLAG←(SP),SP=SP+2 POP BP、CX、BX、AX ;restore register from stack,REG←(SP),SP=SP+8 RET 4 ; 恢复IP及CS, IP←(SP), SP=SP+2,CS←(SP),SP=SP+2,然后SP=SP+4,即清理参数所占的4个字节. SUM ENDP ; SUM过程结束. proce ENDS ; proce段结束. END main ; 源程序结束 |
|