以前在学java的时候就写过判断闰年的程序,仅仅几行代码就能搞定,判断闰年的方法也很简单,满足下列条件之一者就是闰年:
1. 能被4整除但不能被100整除
2. 能被400整除
用java很容易就能实现的功能,用汇编就不见得很容易了,但判断规则这么简单,想必用汇编也不会很难了。
我的思路如下:
1. 用一个子程序来输入年份,并判断是否有效(有效年份为1900-2100),将输入的年份字符串转换成10进制后保存在AX中作为返回结果。
2. 用一个子程序用来判断是否是闰年,并显示结果信息。
3. 用一个程序来调用两个子程序。
写完代码后,编译时没出现编译错误,心头一阵暗喜。但一运行就有问题了。有些年份明明是闰年,但结果显示不是闰年。经过耐心调试,发现在输入结束后进行了换行,换行调用了中断程序,所以AH已经改变!改过后仍然不正确,出现除法溢出错误,调了我好长时间,一度想放弃调试,结果又发现是寄存器使用不当!调试代码的时间是写代码的几倍!深深体会了那一句话:代码是调出来的。
总结这次的错误:
1. 寄存器使用不小心,同一寄存器要使用在不同方面,改变寄存器时没有保存原来的值。没有意识到调用中断时改变了AH的值、进行循环时改变了CX的值。
2. 堆栈使用不熟练,虽然知道push与pop要配对,在代码中也进行了配对,但在push与pop之间有跳转指令,一旦发生跳转,程序就会发生莫名奇妙的错误。
如果写代码的时候能细心一点,就能少花好多时间了。汇编语言寄存器数量有限,如何合理地利用有限的资源,在使用时不发生冲突,是学习汇编编程所必须的技能,加油!
----------------------------下面是源代码---------------------------------
- ;-----------------------------------------------
- ;输入一个具体的年份(1900-2100),判断是否是闰年
- ;-----------------------------------------------
- ;***********************************************
- data segment
- inbuff db 5,?,5 dup(?)
- prompt db 'Please input the year(1900-2100):','$'
- errmsg db 'Input illegal!','$'
- yes db ' is leap year','$'
- no db ' is not leap year','$'
- mess db 'Continue?(y/n):','$'
- newline db 13,10,'$'
- data ends
- ;***********************************************
- code segment
- ;-----------------------------------------------
- main proc far
- assume cs:code,ds:data
- start:
- push ds
- sub ax,ax
- push ax
- mov ax,data
- mov ds,ax
- lop0:
- call input
- call judge
- lea dx,mess
- mov ah,09h
- int 21h
- mov ah,01h
- int 21h
- cmp al,'n'
- je exit
- continue:
- lea dx,newline
- mov ah,09h
- int 21h
- jmp lop0
- exit:
- ret
- main endp
- ;-----------------------------------------------
- ;输入一个具体的年份,并转换成10进制
- ;返回:
- ;* (ax)=输入的年份
- input proc near
- push bx
- push cx
- push dx
- s1:
- lea dx,prompt
- mov ah,09h
- int 21h
- lea dx,inbuff
- mov ah,0ah
- int 21h
- mov dl,byte ptr inbuff[1]
- cmp dl,4
- jne error
- mov cx,4
- lea bx,inbuff
- add bx,2
- mov ax,0
- mov dx,0
- lop1:
- mov dl,10
- mul dl
- mov dl,byte ptr [bx]
- sub dl,30h
- cmp dl,0
- jb error
- cmp dl,9
- ja error
- add ax,dx
- inc bx
- loop lop1
- ;检查输入有效性
- cmp ax,1900
- jb error
- cmp ax,2100
- ja error
- jmp s2
- error:
- lea dx,newline
- mov ah,09h
- int 21h
- lea dx,errmsg
- mov ah,09h
- int 21h
- lea dx,newline
- mov ah,09h
- int 21h
- jmp s1
- s2:
- mov cx,ax
- lea dx,newline
- mov ah,09h
- int 21h
- mov ax,cx
- pop dx
- pop cx
- pop bx
- ret
- input endp
- ;-----------------------------------------------
- ;判断一个年份是否闰年
- ;输入:
- ;* (ax)=年份
- judge proc near
- push bx
- push cx
- push dx
- push ax ;保存ax
- ;输出要判断的年份
- mov cx,4
- lea bx,inbuff
- add bx,2
- lop2:
- mov dl,byte ptr [bx]
- mov ah,02h
- int 21h
- inc bx
- loop lop2
- pop ax
- mov dx,0
- mov cx,ax ;保存ax到cx中
- ;判断是否能被4整除
- mov bx,4
- div bx
- cmp dx,0
- jne notleap
- ;判断是否能被100整除
- mov ax,cx
- mov bx,100
- div bx
- cmp dx,0
- jne isleap
- ;判断是否能被400整除
- mov ax,cx
- mov bx,400
- div bx
- cmp dx,0
- jne notleap
- isleap:
- lea dx,yes
- mov ah,09h
- int 21h
- jmp s3
- notleap:
- lea dx,no
- mov ah,09h
- int 21h
- s3:
- ;换行
- lea dx,newline
- mov ah,09h
- int 21h
- pop dx
- pop cx
- pop bx
- ret
- judge endp
- ;-----------------------------------------------
- code ends
- ;***********************************************
- end start