📄 hanio_tower.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 + -