⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hanio_tower.asm

📁 汇编语言实现的层数任意可调的汉诺塔演示程序
💻 ASM
字号:
;       AUTHOR          emu8086
;       DATE            2007.5.1
;       VERSION         3.00
;       FILE            Hanoi tower.ASM

; 8086 Code Template

; Directive to make EXE output:
       #MAKE_EXE#
       
DSEG    SEGMENT 'DATA'

           platenum dw ? ;盘子数目
           first  dw 20
           second  dw 40
           third  dw 60 ;三个轴线的横坐标
 
           ahas  dw 0
           bhas  dw 0
           chas  dw 0 ;三个轴上现在有的盘子数
 
           bottom  dw 0 ;在盘子向下运动时,停止的位置
           width  dw 0 ;运动的盘子的宽度
 
           row db ?
           column db ? ;画盘子时其坐标
           
           mess db 'How many plates do you want to play?',0ah,0dh,'$'
        
DSEG    ENDS

SSEG    SEGMENT STACK   'STACK'
  tos    DW      100h    DUP(?)
SSEG    ENDS


 
;画轴线宏定义
axis macro column
 local lop
 push ax
 push di
 push dx
 
 mov di,15
 xor ax,ax
 mov ax,column
 mov dl,al
 mov dh,05h
 mov bh,00h
 
lop:mov ah,2
    inc dh
    int 10h
    mov al,124
    mov bl,0fh
    mov cx,1
    mov ah,9
    int 10h
    dec di
    jnz lop
    
    pop dx
    pop di
    pop ax 
endm

;画盘子宏定义
plate  macro row,column,width,character
local time
push di
push ax
push dx
push cx

mov di,width
mov dh,row
mov dl,column
mov bh,00h
time:mov ah,2
     inc dl
     int 10h
     mov al,character 
     mov bl,0Fh
     mov cx,1
     mov ah,9
     int 10h
     dec di
     jnz time
pop cx
pop dx
pop ax
pop di
endm

;垂直移动时消除盘子宏定义
vdplate  macro row,column,width
local time ,route,done 
push di
push ax
push dx
push cx

mov di,width
mov ax,di
inc ax
mov bl,2
div bl
mov dl,column
mov dh,row
mov bh,00h
mov si,ax
time:mov ah,2
     cmp si,di
     je route
     inc dl
     int 10h
     mov al,32
     mov bl,0Fh
     mov cx,1
     mov ah,9
     int 10h
     dec di
     jnz time
     jmp short done
route:inc dl
     int 10h
     mov al,124
     mov cx,1
     mov ah,9
     int 10h
     dec di
     jmp short time
done:pop cx
pop dx
pop ax
pop di
endm

;水平移动盘子宏定义(向左direction=0,向右direction=1)
hplate macro row,column,width,direction
local right,done
push di
push ax
push dx
push cx

mov dh,row
mov dl,column
mov bh,00h
mov ah,2
mov al,direction
test al,1
jnz right
int 10h 
mov al,42 
mov bl,0Fh
mov cx,1
mov ah,9
int 10h
add dx,width
mov ah,2
int 10h
mov al,32
mov ah,9
int 10h
jmp short done

right:
  inc dl
  int 10h 
  mov al,32 
  mov bl,0Fh
  mov cx,1
  mov ah,9
  int 10h
  add dx,width
  mov ah,2
  int 10h
  mov al,42
  mov ah,9
  int 10h

done:  
  pop cx
  pop dx
  pop ax
  pop di
endm

CSEG    SEGMENT 'CODE'

;*******************************************

;////////////////////////////////////
;主函数MAIN
;本程序将演示完成任意层数的汉诺塔游戏
;////////////////////////////////////

MAIN   PROC    FAR

jmp start

start:mov ax,SSEG
      mov ss,ax             ;送堆栈段地址
      mov sp,offset tos     ;设置栈顶
 
      mov ax,DSEG
      mov ds,ax             ;送数据段地址
 
      mov dx,offset mess
      mov ah,9              ;DOS9号功能调用,显示字符串
      int 21h
      
      mov ah,1
      int 21h               ;从键盘上输入字符,并显示
      sub al,30h            
      mov ah,0
      mov platenum,ax       ;将盘子数放入platenum
      mov ahas,ax
 
      mov ah,0
      mov al,03h
      int 10h               ;设置屏幕为文本模式
   
      call init             ;调用初始化界面函数
 
      push platenum         ;通过堆栈传递参数
      push first
      push second
      push third
      
      call han              ;调用盘子移动的递归算法
 
      mov ax,4c00h          ;返回操作系统
      int 21h
 
MAIN endp 

;/////////////////////////////////////////////////
;过程名称:init
;功能:初始化界面
;所用寄存器:ax,bx,cx,dx
;调用其他子程序:cscreen 清屏 
;//////////////////////////////////////////////// 

init proc near

      push ax
      push bx
      push cx
      push dx
         
      call cscreen 

      axis first      ;画三根轴线
      axis second
      axis third

      xor cx,cx
      mov cx,platenum

;画出盘子
drawp: xor ax,ax
      mov al,cl  
      xor bx,bx
      mov bl,21   
      sub bl,al   
      mov row,bl      ;确定起始行
 
      push cx

      xor ax,ax
      mov ax,platenum  
      sub al,cl 
      inc al   
      inc al   
      mov cl,al  
      inc cl     
      mov bh,2    
      mul bh   
      inc ax 
      mov width,ax  
      xor dx,dx
      mov dx,first  
      sub dl,cl     
      mov column,dl   ;确定起始列
      
      pop cx
 
      plate row,column,width,42
  
      dec cl
      cmp cl,0 
      jle move
      jmp drawp

 move:mov ah,0
      int 16h         ;按任意键开始移动
      
      pop dx
      pop cx
      pop bx
      pop ax
      
      ret
      
init endp

;/////////////////////////////////////////////////
;过程名称:cscreen
;功能:清除屏幕,并将光标置于左上角
;所用寄存器:ax,bx,cx,ds,di
;调用其他子程序:无
;//////////////////////////////////////////////// 

cscreen proc near

    PUSH    AX      
    PUSH    DS      
    PUSH    BX      
    PUSH    CX      
    PUSH    DI       
      
    MOV     AX, 40h
    MOV     DS, AX  ; 得到屏幕属性
    MOV     AH, 06h ; 调用滚屏中断
    MOV     AL, 0   ; 全屏滚动
    MOV     BH, 0  ; 设置新生成行的属性
    MOV     CH, 0   
    MOV     CL, 0   
    MOV     DI, 84h 
    MOV     DH, [DI] 
    MOV     DI, 4Ah 
    MOV     DL, [DI]
    DEC     DL      
    INT     10h

    ; 将当前光标位置设在左上角
    MOV     BH, 0   ; 当前页
    MOV     DL, 0   
    MOV     DH, 0   
    MOV     AH, 02
    INT     10h
    
    POP     DI      
    POP     CX      
    POP     BX      
    POP     DS      
    POP     AX   
    ret
    
cscreen endp   
 
;/////////////////////////////////////////////////
;过程名称:han
;功能:利用递归来实现解决任意层数汉诺塔问题的算法
;所用寄存器:ax,bp
;调用其他子程序:platemov     
;//////////////////////////////////////////////// 

han proc near
  
  push ax
  push bp
  
  mov bp,sp
  mov ax,[bp+6]      ;用堆栈传递参数
  mov third,ax
  mov ax,[bp+8]
  mov second,ax
  mov ax,[bp+10]
  mov first,ax
  mov ax,[bp+12] 
  cmp ax,1
  jne han1
  jmp exit
  
han1: dec ax
  push ax
  push first
  push third
  push second
  call han
 
  pop second
  pop third
  pop first
  pop ax
 
  inc ax
  call platemov
 
  push ax
  mov ax,first
  cmp ax,20 ;是从一号轴线开始移动盘子吗
  je deca
  jmp noa3
deca: 
  dec ahas ;一号轴线减少盘子数目
  jmp ok3
noa3: 
  cmp ax,40 ;是从二号轴线开始移动盘子吗
  je decb
  jmp nob3
 
decb:
  dec bhas ;二号轴线减少盘子数目
  jmp ok3
nob3: 
  dec chas ;三号轴线减少盘子数目
ok3: 
  mov ax,third
  cmp ax,20 ;是将盘子移动到一号轴线吗
  je inca
  jmp noa4
 
inca: 
  inc ahas ;一号轴线增加盘子数目
  jmp ok4
 
noa4: 
  cmp ax,40 ;是将盘子移动到二号轴线吗
  je incb
  jmp nob4
  
incb: 
  inc bhas ;二号轴线增加盘子数目
  jmp ok4
 
nob4: inc chas ;三号轴线增加盘子数目
ok4: 
  pop ax
  dec ax
  push ax
  push second
  push first
  push third
  call han
 
  pop third
  pop first
  pop second
  pop ax
  jmp a
  
exit: call platemov 
 
  push ax
  mov ax,first
  cmp ax,20 ;同上,每次移动盘子后都要更改轴线上盘子的数目
  je deca2
  jmp noa32
deca2: 
  dec ahas
  jmp ok32
noa32: 
  cmp ax,40
  je decb2
  jmp nob32 
decb2: 
  dec bhas
  jmp ok32
nob32: 
  dec chas
ok32: 
  mov ax,third
  cmp ax,20
  je inca2
  jmp noa42 
inca2: 
  inc ahas
  jmp ok42 
noa42: 
  cmp ax,40
  je incb2
  jmp nob42 
incb2: 
  inc bhas
  jmp ok42 
nob42: 
  inc chas
ok42: 
  pop ax 
  
a:pop bp
  pop ax
  
  ret
  
han endp

;//////////////////////////////////////
;过程名称:platemov
;功能:实现盘子移动的屏幕演示
;所用寄存器:ax,bx,cx,dx
;调用其他子程序:无
;/////////////////////////////////////

platemov proc near
 
  push ax  
  push bx
  push cx
  push dx
          
  mov width,ax      
  xor ax,ax
  cmp first,20 
  je firsta  
  jmp noa
 
firsta: mov ax,ahas 
  jmp ok
noa: cmp first,40
  je firstb
  jmp nob
firstb: mov ax,bhas
  jmp ok
  
nob: mov ax,chas  
ok: push ax      
  xor bx,bx        
  mov bl,21
  sub bl,al
  mov row ,bl     ;确定行
  pop ax           
  mov ax,platenum 
  sub ax,width    
  inc ax          
  mov bx,platenum  
  sub bx,ax        
  mov ax,bx        
  inc ax          
  push cx
  inc al   
  mov cl,al  
  inc cl    
  mov bh,2    
  mul bh   
  inc ax 
  mov width,ax  
  xor dx,dx
  mov dx,first 
  sub dl,cl     
  mov column,dl   ;确定起始列
 
  pop cx
 
up: vdplate row,column,width
  dec row
  
  plate row,column,width,42

  cmp row,5
  jle horizon
  jmp up
  
horizon: 
  push ax
  mov ax,first
  cmp ax,third
  pop ax
  jg left
  
  hplate row,column,width,1
  
  inc column
  jmp right
 
left: 
  hplate row,column,width,0
  dec column
  
right:
  push ax
  push cx
  mov ax,width 
  inc ax
  mov bl,2
  div bl
  mov cx,ax
  mov ax,third
  sub ax,cx
  cmp column,al
  
  pop cx
  pop ax
  
  je down
  jmp horizon
 
down:
  plate row,column,width,32
  inc row
  plate row,column,width,42
 
down1: vdplate row,column,width
  inc row
  
  plate row,column,width,42
 
  push ax
  mov ax,third
  cmp ax,20
  je thirda
  jmp noa2
 
thirda: 
  mov ax,ahas 
  mov bottom,ax
  jmp ok2
  
noa2: 
  cmp ax,40
  je thirdb
  jmp nob2
thirdb: 
  mov ax,bhas
  mov bottom,ax
  jmp ok2
 
nob2: 
  mov ax,chas 
  mov bottom,ax
  
ok2:
  mov ax,bottom
  mov bx,ax
  mov ax,20
  sub ax,bx
  cmp row,al
  pop ax
  jge nodown
  jmp down1
 
nodown: 
  pop dx
  pop cx
  pop bx
  pop ax
  
  ret 
  
platemov endp
 
;*******************************************
 CSEG    ENDS 

        END    START    ; set entry point.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -