📄 w.asm
字号:
.286 ;采用286指令系统。原因后述。
data segment ;各变量的含义与VC版完全相同,
num1 db 0 ;声明的先后顺序也完全一致。
num2 db 0
num3 db 0
n db 0
char_a dw 0 ;char_a、char_b和char_c就是VC
char_b dw 0 ;版中的a、b和c三个字符型变量,
char_c dw 0 ;详见VC版子程序hanoi的声明。
x dw 0
y dw 0
data ends
code segment
main proc far ;void main()
assume cs:code,ds:data
mov ax,data ;{
mov ds,ax ; (int n;)
; cin>>n;
mov ah,1 ;输入第1个数。
int 21h
cmp al,'0' ;如果无效,则退出。
jb exit
cmp al,'9'
ja exit
sub al,30h
mov n,al ;将第1个数暂存到n中。
int 21h ;输入第2个数,如果是回车,就把第1个数
cmp al,0dh ;当成个位,直接开始(jmp begin)。
je begin
cmp al,'0' ;如果无效,则退出。
jb exit
cmp al,'9'
ja exit ; if(n<1 || n>99){exit(1);}
sub al,30h
mov bl,n ;如果第2个数有效,那么就把第1个数(已
imul bx,bx,10 ;暂存到n中)乘以10,加上第2个数。
mov ah,0 ;由于前面的imul是286指令,所以前面要
add ax,bx ;写.286,以免出错。
mov n,al
mov ah,2 ;回车换行。
mov dl,0ah
int 21h
mov dl,0dh
int 21h
begin:
mov al,n
mov num1,al ; num1=n;
mov ah,0
push ax ;对子程序hanoi的调用——是用堆栈的方式传
push 'a' ;递参数的。
push 'b'
push 'c' ; hanoi(n,'a','b','c');
call get_sys_time ;输出系统时间,形式为“秒:百分之一秒”。
call hanoi ;调用hanio子程序,开始递归。
pop ax ;出栈
pop ax
pop ax
pop ax
mov ah,2 ;回车换行
mov dl,0ah ; cout<<endl;
int 21h
mov dl,0dh
int 21h
call get_sys_time ;再输出系统时间,以计算hanoi程序用时。
exit: ;退出程序。
mov ah,4ch
int 21h
main endp ;} //main结束。
get_sys_time proc near ;输出系统时间。
mov ah,2ch ;调用功能2ch(获取系统时间)。
int 21h
mov ch,dh ;dh存放当前的秒数。
call outputch ;按十进制输出ch中的两位数(秒数)。
mov ah,2 ;中间三行输出冒号。
mov dl,':'
int 21h
mov ah,2ch ;dl存放当前百分之一秒数。
int 21h
mov ch,dl
call outputch ;输出之。
ret
get_sys_time endp
hanoi proc near ;void hanoi(int n,char a,char b,char c)
call printstats ;{
; cout <<endl<<"n="<<n<<" abc="<<num1
; <<','<<num2<<','<<num3;
mov bp,sp ;sp不能直接用,所以要先传给bp。
mov ax,[bp+2] ;读取“进度”。
mov char_c,ax
mov ax,[bp+4]
mov char_b,ax
mov ax,[bp+6]
mov char_a,ax
mov ax,[bp+8]
mov n,al
cmp n,1 ; if(n==1)
jne go_on
mov ax,char_a ; {
mov x,ax ; move子程序是用变量传递参数的,无须压栈。
mov ax,char_c
mov y,ax
call move ; move(a,c);
jmp sub_end ; }
go_on: ; else
sub n,1 ; { //else开始。
mov al,n ; 把n减去1,存入进度。
mov ah,0
push ax
mov ax,char_a
push ax
mov ax,char_c
push ax
mov ax,char_b
push ax
call hanoi ; hanoi(n-1,a,c,b);
pop ax ; 读取进度。
mov char_b,ax
pop ax
mov char_c,ax
pop ax
mov char_a,ax
pop ax
mov n,al
mov ax,char_a
mov x,ax
mov ax,char_c
mov y,ax
call move ; move(a,c);
mov al,n ; 保存进度。
mov ah,0
push ax
mov ax,char_b
push ax
mov ax,char_a
push ax
mov ax,char_c
push ax
call hanoi ; hanoi(n-1,b,a,c);
pop ax ; 读取进度。
mov char_c,ax
pop ax
mov char_a,ax
pop ax
mov char_b,ax
pop ax
mov n,al
add n,1 ; 由于先前n已被减1,故此处要恢复n原值。
sub_end: ; } //else结束。
;call printstats ;cout <<endl<<"n="<<n<<" abc="<<num1
ret ; <<','<<num2<<','<<num3;
hanoi endp ;} //hanoi结束。
move proc near ;void move(char x,char y)
cmp x,'a' ;{
je subnum1 ; if (x=='a') {--num1;}
cmp x,'b' ; if (x=='b') {--num2;}
je subnum2
cmp x,'c' ; if (x=='c') {--num3;}
je subnum3
subnum1:
sub num1,1
jmp add_nums
subnum2:
sub num2,1
jmp add_nums
subnum3:
sub num3,1
jmp add_nums
add_nums:
cmp y,'a' ; if (y=='a') {++num1;}
je addnum1
cmp y,'b' ; if (y=='b') {++num2;}
je addnum2
cmp y,'c' ; if (y=='c') {++num3;}
je addnum3
addnum1:
add num1,1
ret
addnum2:
add num2,1
ret
addnum3:
add num3,1
ret
move endp ;}
printstats proc near ;本子程序作用在上文调用处已经标明。
mov ah,2
mov dl,0ah
int 21h
mov dl,0dh
int 21h
mov dl,'n'
int 21h
mov dl,'='
int 21h
mov ch,n
call outputch
mov dl,' '
int 21h
mov dl,'a'
int 21h
mov dl,'b'
int 21h
mov dl,'c'
int 21h
mov dl,'='
int 21h
mov ch,num1
call outputch
mov dl,','
int 21h
mov ch,num2
call outputch
mov dl,','
int 21h
mov ch,num3
call outputch
ret
printstats endp
outputch proc near ;本子程序是用来以十进制形式,
push ax ;输出ch中的数。
mov ah,0
mov al,ch ;将ch赋予al(实际上是ax)待除。
mov bl,10
div bl ;ax除以10,此时商(十位)在al中,
push ax ;余数(个位)在ah中。先保存一下ax。
mov ah,2
cmp al,0 ;如果商为0(只有个位),直接输出。
je popax
mov dl,al ;否则,先输出商,然后
add dl,30h
int 21h
popax:
pop ax
mov dl,ah ;再输出余数。
add dl,30h
mov ah,2
int 21h
pop ax
ret
outputch endp
code ends
end main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -