本文通过堆栈传递参数方法,完成将ARY为首地址的COUNT个字数据累加,不考虑溢出,并将结果保存在SUM中

STSTACKS   SEGMENT  STACK
    DW     200H DUP(?)
    TOP    LABEL WORD
    STACKS ENDS                --定义栈大小

    DATAS    SEGMENT
    ARY     DW      123,-54,267,251,55,9  --定义一串数字
    COUNT   EQU  ($-ARY)/2              --表示ARY串的changdu
    SUM     DW      ?                      --定义SUM变量存放累加和
    DATAS  ENDS

    CODES    SEGMENT
    ASSUME CS:CODE,SS:STACKS,DS:DATAS

    MAIN    PROC    NEAR
    MOV     BX,OFFSET ARY                   --ARY的首地址传入BX
    PUSH    BX                              --BX进栈
    MOV     BX,COUNT                        --COUNT的值送入BX
    PUSH    BX                              --BX进栈
    MOV     BX,OFFSET SUM                   --SUM的首地址传入BX
    PUSH    BX                              --BX进栈
    CALL    PROADD                          --调用子程序PROADD
    INT     20H
    MAIN    ENDP

    PROADD  PROC    NEAR
    PUSH    BP                              --保存现场
    MOV     BP,SP                           --将SP的值送入BP中,用于后面通过BP读取数据,不改变SP的值
    PUSH    AX
    PUSH    CX
    PUSH    SI
    PUSH    DI                              --保存现场
    MOV     SI,[BP+8]                       --BP+8地址为ARY的首地址
    MOV     CX,[BP+6]                       --BP+6地址里存的是COUNT的值
    MOV     DI,[BP+4]                       --BP+4地址存着SUM的首地址
    XOR     AX,AX                           --AX清零,用于累加
    NEXT:   ADD     AX,[SI]                         --进行累加
    ADD     SI,2                            --地址后移
    LOOP    NEXT
    MOV     [DI],AX                         --将累加和存入SUM中
    POP     DI
    POP     SI
    POP     CX
    POP     AX
    POP     BP                              回复现场
            RET
    PROADD  ENDP

    CODES  ENDS
    END   MAINACKS  SEGMENT  STACK
    DW    100 DUP(?)
    TOP   LABEL WORD
    STACKS ENDS

    DATAS   SEGMENT
    NUM1 DW 9,9,8,7,4,5,6,7,8,9
    NUM2 DW 6,4,5,6,7,8,9          ;定义两个数字,首位存放num的长度,这两个数字将用于做乘法运算
    S    DW  300H DUP(0)           ;s用于存放结果
    DATAS ENDS

    CODES   SEGMENT
    ASSUME  CS:CODES,DS:DATAS,SS:STACKS
    MAIN  PROC FAR
    MOV  AX,STACKS
    MOV  SS,AX
    LEA  SP,TOP
    MOV  AX,DATAS
    MOV  DS,AX

    LEA   SI,NUM1
    LEA   DI,NUM2
    LEA   BX,S
    ADD   SI,2
    ADD   DI,2         ;加2的原因是因为第一位是数字的个数,从第二个数字开始才是真正的数,因为是DW的所以需要+2

    MOV   CX,NUM1
    JIN1:     PUSH  [SI]
    ADD   SI,2
    LOOP  JIN1

    LEA   SI,NUM1
    ADD   SI,2
    MOV   CX,NUM1
    CHU1:     POP   [SI]
    ADD   SI,2
    LOOP  CHU1          ;进栈出栈的目的是为了倒置该字符串用于乘法运算

    MOV   CX,NUM2
    JIN2:     PUSH  [DI]
    ADD   DI,2
    LOOP  JIN2

    LEA   DI,NUM2
    ADD   DI,2
    MOV   CX,NUM2
    CHU2:     POP   [DI]
    ADD   DI,2
    LOOP  CHU2          ;同上

    LEA   SI,NUM1
    LEA   DI,NUM2
    LEA   BX,S
    ADD   SI,2
    ADD   DI,2

    MOV   CX,NUM1       ;二重循环,把每个数都相乘,并存在s的对应位置,如果该位置里有值,则加上该值
    L1:          PUSH  CX
    MOV   CX,NUM2
    PUSH  BX
    PUSH  DI
    L2:      MOV   DX,[SI]
    MOV   AX,[DI]
    MUL   DX
    ADD   DI,2
    ADD   AX,[BX]
    MOV   [BX],AX
    ADD   BX,2

    LOOP L2
    POP  DI
    POP  BX
    ADD  BX,2
    POP  CX
    ADD  SI,2
    LOOP L1

    XOR   DX,DX
    LEA    BX,S
    MOV    CX,NUM1
    ADD    CX,NUM2          ;将s中每一个数除以10,余数放回原位,商作为进位
    L4:      MOV    AX,[BX]
    ADD    AX,DX
    MOV    DL,10
    DIV    DL
    MOV    DL,AH
    MOV    [BX],DX
    MOV    DL,AL

    ADD    BX,2
    LOOP L4

    MOV    CX,NUM1
    ADD    CX,NUM2

    L5:  SUB    BX,2                ;逆序,输出结果
    MOV    DX,[BX]
    ADD    DX,30H
    MOV    AH,2
    INT    21H

    LOOP L5

    L10:  MOV   AH,4CH
    INT   21H
    MAIN  ENDP
    CODES ENDS
    END MAIN

这里面最难的地方是怎么判断栈里面的内容,我简单解释一下:

比如有一个栈,初始化的时候,SP指向的是栈顶同时也是最底部,当开始PUSH数据的时候,SP就会向上移动,我们可以知道程序中,最开始PUSH的元素是ARY的首地址其次是COUNT的值所以在调用子程序之前sp指向的是SUM的首地址。

然后调用子程序,首先要存源程序的下一条指令的地址值,然后再存其他的你想要存的内容。这时,我们把SP指向的地址位置送入BP,相当于BP用来标记这个位置,方便SP后面指向其他的位置。

这时我们就可以很轻易的得出,BP+8即为ARY的首地址、BP+6为COUNT的值、BP+4为SUM的首地址了