;PROGRAM TITLE GOES HERE -- HANOI
;Solves tower of hanoi puzzle.Printout sequence of moves
;of N discs from initial spindle X to final spindle Z.
;using spindle Y for temporery storage
;
datarea segment 			;define data segment
    message1    db  'N=?',0ah,0dh,'$'
    message2    db  'What is the name of spindle X ?'
                db  0ah,0dh,'$'
    message3    db  'What is the name of spindle Y ?'
                db  0ah,0dh,'$'
    message4    db  'What is the name of spindle Z ?'
                db  0ah,0dh,'$'            
    flag        dw  0
    constant    dw  10000,1000,100,10,1
datarea ends
;*****************************************************
prognam  segment		;define code segment
;-----------------------------------------------------
main proc far 
        assume cs:prognam, ds:datarea
start:
;set up stack for return 
        push    ds
        sub     ax,ax
        push    ax
;set DS register to current data segment
        mov     ax,datarea
        mov     ds,ax
;main part of program goes here 
        lea     dx,message1		;N=7?
        mov     ah,09h
        int     21h
        call    decibin			;read N into BX
        call    crlf

        cmp     bx,0			;if N=0
        jz      exit			;exit

        lea     dx,message2		;X=?
        mov     ah,09h
        int     21h
        mov     ah,01h			;read X's name into CX
        int     21h
        mov     ah,0
        mov     cx,ax
        call    crlf

        lea     dx,message3				;Y=?
        mov     ah,09h
        int     21h
        mov     ah,01h					;read Y'name into SI
        int     21h
        mov     ah,0
        mov     si,ax
        call    crlf

        lea     dx,message4				;Z=?
        mov     ah,09h
        int     21h
        mov     ah,01h					;read Z's name into DI
        int     21h
        mov     ah,0
        mov     di,ax
        call    crlf

        call    hanoi					;call HANOI(N,X,Y,Z)
exit:   ret								;return to DOS
main    endp
;---------------------------------------------------
hanoi proc near							;define  subprocedure
;SOlves tower of hanoi puzzle
;Argement :(BX)=N,(CX)=X,(SI)=Y,(DI)=Z.
        cmp     bx,1			;if N=1,execute basis
        je      basis
        call    save			;save N,X,Y,Z
        dec     bx
        xchg    si,di
        call    hanoi			;call HANOI(N-1,X,Z,Y)
        call    restor			;restore N,X,Y,Z
        call    print			;print XNZ
        dec     bx
        xchg    cx,si
        call    hanoi			;call HANOI(N-1,Y,X,Z)
        jmp     return
basis:  call    print			;print X1Z
return: ret						;return 
hanoi   endp					;end subprocedure
;-------------------------------------------------------
print proc  near
        mov     dx,cx				;print X
        mov     ah,02h
        int     21h
        call    binidec				;print N
        mov     dx,di				;print Z
        mov     ah,02h
        int     21h
        call    crlf				;skip to next line
        ret
print   endp
;-----------------------------------------------------------
save  proc  near
        pop     bp
        push    bx
        push    cx
        push    si
        push    di
        push    bp
        ret
save    endp
;-----------------------------------------------------------
restor proc near
        pop     bp
        pop     di
        pop     si
        pop     cx
        pop     bx
        push    bp
        ret
restor  endp
;------------------------------------------------------------
decibin proc near 
;prodecure to convert decimal on keyboard to binary.
;result is left in BX register
        mov     bx,0
;get digit from keyboard ,convert to binary 
newchar:
        mov     ah,1		;keyboard input
        int     21h			;call DOS
        sub     al,30h		;ASCII to binary 
        jl      exit1		;jump if<0
        cmp     al,9d		;is it >9d?
        jg      exit1		;yes,not dec digit
        cbw					;BYTE in AL to WORD in AX
;(digit is now in AX)
;multiply number in BX by 10 decimal
        xchg    ax,bx		;trade digit&number 
        mov     cx,10d		;put 10 dec in CX
        mul     cx			;number times 10
        xchg    ax,bx		;trade number &digit
;add digit in AX to number in BX
        add     bx,ax		;add digit to number 
        jmp     newchar		;get next digit
exit1:  ret					;return from decibin
decibin endp				;end of decibin proc
;------------------------------------------------------------
binidec proc near
;procedure to convert binary number in BX to decimal
;on console screen
        push    bx
        push    cx
        push    si
        push    di
        mov     flag,0
        mov     cx,5
        lea     si,constant
dec_div:
        mov     ax,bx			;number high half 
        mov     dx,0			;zero out low half 
        div     word ptr[si]	;divide by contant
        mov     bx,dx			;reminder into BX
        mov     dl,al			;quotient into DL

        cmp     flag,0			;have not leading zero
        jnz     print1
        cmp     dl,0
        je      skip
        mov     flag,1
;print the contents of DL on screen 
print1: add     dl,30h			;convert to ASCII
        mov     ah,02h			;display fuction
        int     21h				;call DOS
skip:   add     si,2
        loop    dec_div
        pop     di
        pop     si
        pop     cx
        pop     bx
        ret					;return from dec_div
binidec endp
;-------------------------------------------------------------
crlf proc near
        mov     dl,0ah		;linefeed
        mov     ah,02h		;display function
        int     21h
;
        mov     dl,0dh		;carriage return 
        mov     ah,02h		;display function
        int     21h
;
        ret
crlf    endp
;-----------------------------------------------------------
prognam ends				;end of code segment
;*************************************************************
end     start				;end assembly