第1节 子程序结构
推荐给好友
打印
加入收藏
更新于2009-06-01 11:03:53


1.1 子程序的定义

过程名 PROC 属性
.
.
.
过程名 ENDP
属性: NEAR, FAR

1.主程序与子程序在同一代码段内
例 6.1.1
CODE SEGMENT ‘code’
;-----------Main过程---------------
MAIN PROC FAR

CALL SUB1

RET
MAIN ENDP
;------------------------------------------
;-----------SUB1子过程---------------
SUB1 PROC NEAR

CALL SUB2

RET
SUB1 ENDP
;--------------------------------------------
;-----------SUB2子过程---------------
SUB2 PROC NEAR

RET
SUB2 ENDP
;--------------------------------------------
;--------------------------------------------
CODE ENDS
END MAIN


2.主程序与子程序不在同一个代码段
例6.1.2
;---------CODE1段----------------------
CODE1 SEGMENT ‘code’
;-----------Main过程---------------
MAIN1 PROC FAR

RET
MAIN1 ENDP
;------------------------------------------
;-----------SUB3子过程---------------
SUB3 PROC FAR

RET
SUB3 ENDP
;--------------------------------------------
CODE1 ENDS
;---------CODE2段----------------------
CODE2 SEGMENT ‘code’
MAIN2 PROC FAR

CALL SUB3

RET
MAIN2 ENDP
CODE2 ENDS
END MANI1


1.2 子程序的调用和返回

CALL RET 对堆栈的使用。

1.3 现场的保存与恢复

为什么要保存现场与恢复现场?

1. 利用堆栈指令进行现场的保存与恢复
例6.1.3
SUB4 PROC NEAR
            PUSH AX
            PUSH BX
            PUSH CX
           …子程序体
            POP CX
            POP BX
            POP AX
            RET 
            SUB4 ENDP
             **注意保存与恢复的顺序.

2. 利用数据传送指令进行现场的保存与恢复
DATA SEGMENT
           BUFFER DW 4 DUP(?)
DATA ENDS
SUB5 PROC NEAR
            LEA DI, BUFFER 
            MOV [DI], AX
            MOV [DI+2], BX
            MOV [DI+4], CX
            Mov [DI+6], DX 
            …子程序体
             LEA DI, BUFFER
            MOV AX, [DI]
            MOV BX, [DI+2] 
            MOV CX, [DI+4] 
            MOV DX, [DI+6]
            RET
SUB5 ENDP
**现场保存在子程序的数据空间.
**有什么问题? DI?

3. 利用PUSHA和POPA进行现场的保存与恢复(286以上)
SUB6 PROC NEAR
            PUSHA
            …子程序体
            POPA
            RET
SUB6 ENDP

4. 利用PUSHAD和POPAD指令进行现场的保存与恢复(386以上)
SUB7 PROC NEAR 
            PUSHAD
            …子程序体
            POPAD
            RET
SUB7 ENDP
**保存的原则:子程序使用的寄存器,这些寄存器要保存与恢复.

1.4 子程序的参数传送


传送参数方法: (1)通过通用寄存器(RC); (2)通过存储单元; (3)通过堆栈

1.通过通用寄存器传送参数
例6.1.7 用寄存器传送参数方式, 编制5位10进制加法程序。
要求(1)SUB8子程序把键入5位以内的10进制数转(<65536)换成2进制数年存入CX,键入非数字键返主程序。
(2)SUB9子程序完成把CX中的2进制数转换成10进制数显示在CRT上.
(3)在主程序MAIN中求和,两数之和小于等于65535.
(4)MAIN,SUB8,SUB9在同一代码段中.

CODE SEGMENT
             ASSUME CS:CODE
//主程序
MAIN PROC FAR 
          CALL SUB8 ;取被加数 
          MOV BX,CX 
          CALL SUB8 ;取加数 
          ADD CX, BX ;求和 
          CALL SUB9 ;显示 
          MOV AH, 4CH 
          INT 21H
MAIN ENDP
//子程序把键入5位以内的10进制数转(<65536)换成2进制数年存入CX,键入非数字键返主程序。
SUB8 PROC NEAR 
            PUSH AX
            PUSH BX
           PUSH DX 
           XOR CX,CX ; mov cx, 0 CX中保存结果
AA2:   MOV AH, 1
           INT 21H
//界限0~9
         CMP AL, 30H
         JC AA1
        CMP AL, 3AH
        JNC AA1
//x10
        ADD CX, CX
        MOV BX, CX
        ADD CX, CX
        ADD CX, CX 
        ADD CX, BX
        AND AX, 0FH
        ADD CX, AX ;键入的值加到CX中。
        JMP AA2
AA1: POP DX
        POP BX
        POP AX
        RET
SUB8 ENDP
//把CX中的2进制数转换成10进制数显示在CRT上 
SUB9 PROC NEAR
            PUSH AX
            PUSH BX
            PUSH DX
//最高位不显示0
            CMP CX,10000 
            JNC AA12 ;JAE AA12 大于等于1000时显示万位 
            CMP CX, 1000 
            JNC AA4 
            CMP CX, 100 
            JNC AA6 
            CMP CX, 10 
            JNC AA8 
            JMP AA10
//万位计数,并显示
AA12:  MOV DL, -1
AA3:    SUB CX, 10000 
            INC DL 
            JNC AA3 
            ADD CX, 10000 
            OR DL, 30H 
            MOV AH, 2 
            INT 21H
//千位计数,并显示
AA4:    MOV DL, -1
AA5:    SUB CX, 1000 
            INC DL 
            JNC AA5 
            ADD CX, 1000 
            OR DL, 30H 
            MOV AH, 2 
            INT 21H
//百位计数,并显示
AA6:    MOV DL, -1
AA7:    SUB CX, 100 
            INC DL 
            JNC AA7 
            ADD CX, 100 
            OR DL, 30H 
            MOV AH, 2 
            INT 21H
//十位计数,并显示
AA8:    MOV DL, -1
AA9:    SUB CX, 10 
            INC DL 
            JNC AA9 
            ADD CX, 10 
            OR DL, 30H 
            MOV AH, 2 
            INT 21H
//个位计数, 并显示
AA10: MOV DL, CL 
            OR DL, 30H 
            MOV AH, 2 
            INT 21H 
            POP DX 
            POP BX 
            POP AX 
            RET
SUB9 ENDP
CODE ENDS
END MAIN
**以上的程序子程序中用到AX,BX,CX,DX. 其中CX用于传送参数及结果,而AX,BX,DX用于中间运算, 内部使用,为了不修改主程序中的AX,BX,DX,要保存现场.

2.通过存储单元传送参数
利用存储单元存放调用子程序的输入参数, 子程序把运算结果(输出参数)也用存储单元保存.

例6.1.8 用存储单元传送参数方式,编写求无符号多字节2进制数的和,然后以16进制数形式显示在CRT上.
要求:
NUMBER1放8个字节的数.
NUMBER2放8个字节的数.
NUMBER3放求和结果,8个字节单元
SUB10 求和子子程序
SUB11 显示子程序.

DATA SEGMENT
NUMBER1 DB 99, 22, 33, 44, 99, 77, 88, 11
NUMBER2 DB 99, 88, 77, 66, 55, 44, 33, 22
NUMBER3 DB 8 DUB(?)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS: DATA
//主程序
MAIN PROC FAR
MOV AX, DATA
MOV DS, AX
CALL SUB10
LEA BX, NUMBER3+7
CALL SUB 11
MOV AH, 4CH
INT 21H
//8字节求和子程序
SUB10 PROC NEAR
PUSH AX
PUSH CX
PUSH BX
PUSH SI
PUSH DI

LEA SI, NUMBER1
LEA DI, NUMBER2
LEA BX, NUMBER3
MOV CX, 8
AND AL, AL ; CLC C0
AA1: MOV AL,[SI]
ADC AL,[DI]
MOV [BX], AL
INC SI
INC DI
INC BX
LOOP AA1

POP DI
POP SI
POP BX
POP CX
POP AX
RET
SUB10 ENDP

//显示子程序
SUB11 PROC NEAR
PUSH DX
PUSH CX
PUSH AX

MOV DH, 8 ; 循环次数
//一个字节的高4位显示
AA4: MOV DL,[BX] ; 从高位NUMBER3+7开始计数
MOV CL, 4
SHR DL, CL ;高4位
OR DL, 30H ; 30H~3FH
CMP DL, 3AH
JC AA2 ; jb AA2
ADD DL, 7 ; 3AH+7 = 41H
AA2: MOV AH, 2
INT 21H

//一个字节的低4位显示
MOV DL, [BX]
AND DL, 0FH
OR DL, 30H
CMP DL, 3AH
JC AA3
ADD DL, 7
AA3: MOV AH, 2
INT 21H

DEC BX
DEC DH
JNZ AA4 ;循环8次

MOV DL, ‘H’
MOV AH, 2
INT 21H

POP AX
POP CX
POP DX
SUB11 ENDP
MAIN ENDP
CODE ENDS
END MAIN

3.通过堆栈传送参数或参数表地址

例 6.1.9用堆栈传送参数和参数表地址方式,编制键入8位的非压缩BCD码加法并显示的源程序。
要求: NUMBER1~NUMBER1+7存放键入的被加数(非压缩BCD码);
NUMBER2~NUMBER2+7存放键入的加数(非压缩BCD码);
NUMBER3~NUMBER3+8存放和(非压缩BCD码);
SUB12接收8位非压缩BCD码,接收被加数、加数(输出:接收结果存入堆栈中)
SUB13显示9位非压缩BCD码,显示和(输入:参数地址表在堆栈中)

DATA SEGMENT
NUMBER1 DB 8 DUB(0) ;被加数
NUMBER2 DB 8 DUB(0) ;加数
NUMBER3 DB 9 DUB(0) ;和
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA
MAIN PROC FAR
MOV AX, DATA
MOV DS, AX
//1.取被加数
CALL SUB12
POP CX
LEA BX, NUMBER1
AA3: POP AX
MOV [BX], AL
INC BX
LOOP AA3
//2.取加数
CALL SUB12
POP CX
LEA BX, NUMBER2
AA4: POP AX
MOV [BX], AL
INC BX
LOOP AA3
//3.计算和
LEA SI, NUMBER1
LEA DI, NUMBER2
LEA BX, NUMBER3
MOV CX, 8 ; 计数次数
OR CX, CX ; CLC
AA5: MOV AL, [SI]
ADC AL, [DI]
AAA
MOV [BX], AL
INC SI
INC DI
INC BX
LOOP AA5

ADC CL, AH
MOV [BX], CL
//4.显示和
  LEA AX, NUMBER3+8
        PUSH AX
CALL SUB13
//5.清被加数与加数单元为0
         MOV CX, 16
         LEA BX, NUMBER1
         XOR AL, AL ;MOV AL, 0
QQQ2: MOV [BX], AL
        INC BX
        LOOP QQQ2
//6.退出
         MOV AH, 4CH 
         INT 21H
//7. 接收8位非压缩BCD码子程序, 接收被加数、加数(输出:接收结果存入堆栈中)
SUB12 PROC NEAR
POP BX ;保存子程序返回地址
SUB CX, CX ; MOV CX, 0
AA1: MOV AH, 1 
         INT 21H
         CMP AL, 30H
         JC AA2
        CMP AL, 3AH
         JNC AA2
         INC CX ;个数加1
         PUSH AX ;键入的数压入栈
         JMP AA1


AA2: PUSH CX ; 键入数字的个数
         PUSH BX; 子程序返回地址入栈
         RET
SUB12 ENDP
//8. 显示9位非压缩BCD码子程序, 显示和(输入:参数地址表在堆栈中)
SUB13 PROC NEAR 
        POP AX ;子程序返回地址出栈
        POP BX ;参数表地址出栈
        PUSH AX ;子程序返回地址入栈
         MOV CX, 9 ;和数是9位,循环计数次数
AA6: MOV DL, [BX]
         ADD DL, 30H ;OR DL, 30H
         MOV AH, 2
         INT 21H
         DEC BX
         LOOP AA6
         RET
SUB13 ENDP
        MAIN ENDP
CODE ENDS
         END MAIN

 

上一节                    下一节

相关链接


 
关于我们 | 诚邀加盟 | 客户服务 | 相关法律 | 网站地图 | 友情链接 | 服务信箱:service@eefocus.com
© 2006 与非门科技信息咨询(北京)有限公司 All Rights Reserved.