TITLE   Variable # of parameters passed via stack   VARPARA.ASM
COMMENT |
        Objective: To show how variable number of parameters 
                   can be passed via the stack
            Input: Requests variable number of non-zero integers.
                   A zero terminates the input.
|          Output: Outputs the sum of input numbers.
CRLF   EQU   0DH,0AH    ; carriage return and line feed
.MODEL SMALL
.STACK 100H
.DATA
prompt_msg  DB  'Please input a set of non-zero integers.',CRLF
            DB  'You must enter at least one integer.',CRLF
            DB  'Enter zero to terminate the input.',0
sum_msg     DB  'The sum of the input numbers is: ',0

.CODE
INCLUDE io.mac

main  PROC
      .STARTUP
      PutStr  prompt_msg     ; request input numbers
      nwln
      sub     CX,CX          ; CX keeps number count
read_number:
      GetInt  AX             ; read input number
      nwln
      cmp     AX,0           ; if the number is zero
      je      stop_reading   ; no more numbers to read
      push    AX             ; place the number on stack
      inc     CX             ; increment number count
      jmp     read_number
stop_reading:
      push    CX             ; place number count on stack
      call    variable_sum   ; returns sum in AX
      ; clear parameter space on the stack
      inc     CX             ; increment CX to include count
      add     CX,CX          ; CX := CX * 2 (space in bytes)
      add     SP,CX          ; update SP to clear parameter 
                             ; space on the stack      
      PutStr  sum_msg        ; display the sum
      PutInt  AX
      nwln
done:
      .EXIT
main  ENDP

;-----------------------------------------------------------
;This procedure receives variable number of integers via the
; stack. The last parameter pushed on the stack should be
; the number of integers to be added. Sum is returned in AX.
;-----------------------------------------------------------
variable_sum  PROC
      push    BP             ; save BP - procedure uses BP
      mov     BP,SP          ; copy SP to BP
      push    BX             ; save BX and CX
      push    CX 
      
      mov     CX,[BP+4]      ; CX := # of integers to be added
      mov     BX,BP
      add     BX,6           ; BX := pointer to first number
      sub     AX,AX          ; sum := 0
add_loop:
      add     AX,SS:[BX]     ; sum := sum + next number
      add     BX,2           ; BX points to the next integer
      loop    add_loop       ; repeat count in CX

      pop     CX             ; restore registers
      pop     BX
      pop     BP
      ret                    ; parameter space cleared by main
variable_sum  ENDP
      END     main
