TITLE	ACK.ASM	  ackermann function
; ack (0,n) = n+1
; ack (m,0) = ack (m-1,1)
; ack (m,n) = ack (m-1,ack(m,n-1))
;**************************************************
datarea	 segment	;define data segment
  mm	     dw	    ?
  nn	     dw     ?
  result     dw     ?
  temp       dw     ?
  mess       db    'Error in input data!',0ah,0dh,'$'
datarea	 ends
;**************************************************
prognam  segment	;define code segment
main	 proc	 far
	 assume  cs:prognam,ds:datarea
;
frame	 struc
  save_bp	 dw	?
  save_cs_ip	 dw	2 dup(?)
  n		 dw	?
  m		 dw	?
  result_addr	 dw	?
frame	 ends
;
start:			;starting execution address
;set up stack for return
	push	ds	   ;save old data segment
	sub	ax,ax	   ;put zero in ax
	push	ax	   ;save it on stack

;set DS register to current data segment
	mov	ax,datarea ;datarea segment  addr.
	mov	ds,ax	   ;  into DS register
;
	call	input	   ;input m
	mov	ax,temp
	mov	mm,ax
	call	crlf	   ;CR/LF
;
	call	input	   ;input n
	mov	bx,temp
	mov	nn,bx
	call	crlf	   ;CR?LF
;
	cmp	ax,0	   ;m < 0 ?
	jl	error	   ;yes,display error mess
	cmp	bx,0	   ;n < 0 ?
	jl	error	   ;yes,display error mess
	lea	si,result
	push	si
	mov	ax,mm
	push	ax
	mov	bx,nn
	push	bx
	call	far ptr ack ;computing ack function
	jmp	exit
error:	lea	dx,mess	    ;display error message
	mov	ah,09h
	int	21h
exit:
	ret		    ;return to DOS
main	endp
;--------------------------------------------------
input	proc	near	    ;define subprocedure
	push	ax
	push	bx
	push	cx
	push	dx
	mov	bx,0
newchar1:
	mov	ah,1	    ;reguest kbd input
	int	21h
	sub	al,30h	    ;ASCII to digit
	jl	exit1	    ; < 0,exit
	cmp	al,9d
	jg	exit1	    ; > 9,exit
	cbw
	xchg	ax,bx	    ;convert to binary
	mov	cx,10
	mul	cx
	xchang	ax,bx
	add	bx,ax
	jmp	newchar1
exit1:	mov	temp,bx
	pop	dx	    ;restore registers
	pop	cx
	pop	bx
	pop	ax
	ret
input	endp		    ;end subprocedure
;--------------------------------------------------
crlf	proc	near
	mov	dl,0ah	    ;display  CR/LF
	mov	ah,02h
	int	21h
;
	mov	dl,0dh
	mov	ah,02h
	int	21h
	ret
crlf	endp
;--------------------------------------------------
ack	proc	far
	push	bp
	mov	bp,sp	   ;BP is pointer of struct
	mov	si,[bp].result_addr
	mov	ax,[bp].m
	mov	bx,[bp].n
	cmp	ax,0	   ;m>0?
	jg	testn	   ;if so, jump to test n
	inc	bx	   ;m=0, put n+1
	mov	[si],bx	   ;  to result
	jmp	exit2
;
testn:	cmp	bx,0	   ;n>0?
	jg	mn	   ;if so, jump to do ack(m,n)
	dec	ax	   ;n=0
	mov	bx,1
	push	si
	push	ax
	push	bx
	call	ack	   ;ack( m-1,1 )
A:	jmp	exit2
;
mn:	push	si
	push	ax
	dec	bx
	push	bx
	call	ack	   ;ack( m,n-1 )
;
B:	push	si
	mov	ax,[bp].m  ;push m-1
	dec	ax
	push	ax
	mov	dx,[si]	   ;and ack(m-1,result)
	push 	dx	   ;    to stack
	call	ack	   ;ack(m-1,ack(m,n-1))
;
exit2:	pop	bp
	ret	6
ack	endp
;--------------------------------------------------
prognam ends		   ;end of code segment
;**************************************************
	end	start	   ;end assembly
