📄 闰年判断.asm
字号:
assume cs:code,ds:data
data segment;初始化各种提示语句,前面的0dh,0ah表示回车
inf db 0dh,0ah,'Please Input Year: $'
inf_ok db 0dh,0ah,'This is a leap year! $'
inf_no db 0dh,0ah,'This is not a leap year! $'
inf_err db 0dh,0ah,'Input Error! $'
inf_ag db 0dh,0ah,'Do you want to try again?(Y/N) $'
inf_end db 0dh,0ah,'Press any key to exit. $';将输入的年份字符串转为数字,存在此处
year dw 0;缓冲区,用于接受输入,第一个字节为缓冲区长度,第二个字节为实际输入长度,后面是缓冲区
buf db 8
db ?
db 8 dup (?)
data ends
stack segment
db 80 dup (0)
stack ends
code segment
start:
mov ax,data
mov ds,ax
mov ax,stack
mov ss,ax
mov sp,80;dx保存提示语句的首地址,调用21H中断09功能,显示在屏幕上
lea dx,inf
mov ax,0900H
int 21H;dx指向缓冲区首字节(表示缓冲区大小的字节),调用21H中断0AH功能,接受输入字符串
lea dx,buf
mov ax,0a00H
int 21H;cx清零
xor cx,cx
mov cl,[buf+1];cl取得实际输入字符数
cmp cl,4 ;如果实际输入字符数>4,则提示输入错误
ja input_error
lea si,[buf+2];si指向实际的缓冲区起始位置
push cx
is_num: ;判断输入的是否都是数字,如果不是,则提示输入错误
cmp byte ptr [si],'0'
jb input_error
cmp byte ptr [si],'9'
ja input_error
inc si ;si后移
loop is_num
pop cx
dec si ;上面循环结束后,si指向输入字符串的最后一个字符的后面,所以减1,使之指向最后一个字符
lea di,year ;di指向保存转换后数字的空间
mov word ptr [di],0
;该空间清0
call str2int ;调用函数,将输入字符串转换为数字
call isleap ;判断这个数字是否为闰年
jmp short try_again ;询问是否继续输入
input_error:
lea dx,inf_err ;提示输入错误
mov ax,0900H
int 21H
try_again:
lea dx,inf_ag ;询问是否继续
mov ax,0900H
int 21H
mov ax,0100H ;调用中断21H的01功能,接受一个字符输入并回显
int 21H
cmp al,'y' ;判断输入字符是否为y或Y,如果是,则跳回函数开头,重新执行
jz start
cmp al,'Y'
jz start
main_end:
lea dx,inf_end
mov ax,0900H
int 21H
mov ax,0700H
int 21H
mov ax,4c00H ;程序结束
int 21H
;函数功能:将一个数字字符串转换成对应的数字
;输入参数:cx 字符串长度
; si 指向字符串的最后一个字符
; di 指向转换结果保存的位置,大小为word型
str2int proc near
push ax ;寄存器入栈
push bx
push cx
push dx
mov ax,1 ;ax初始为1
l1:
push ax ;每次循环,ax*10,但是后面计算乘法的时候,还需要用到ax,所以先把ax的值入栈
mov bl,[si] ;把si指向的字符存入bl,并减掉字符'0'
sub bl,'0'
mov bh,0 ;bh置0,计算乘法,因为可能要乘1000,只能用16位乘16位的乘法
mul bx
add ds:[di],ax ;乘法结果加到保存计算结果的地方(也就是di指向的地址)
pop ax ;ax出栈,并乘10
mov bx,10
mul bx
dec si ;si递减
loop l1 ;这个循环开头没有写cx,因为cx是作为参数传进来的
pop dx
pop cx
pop bx
pop ax
ret
str2int endp
;函数功能:判断某个数字是否为闰年
;输入参数:di 指向被判断数字的存储地址,word型
;输出参数:无,直接屏幕显示是否闰年
isleap proc near
push ax ;寄存器入栈
push bx
push cx
push dx
mov cx,ds:[di] ;cx保留输入字符串
mov ax,cx
cmp ax,1900
jl input_error
cmp ax,2100
ja input_error
mov dx,0 ;因为除法结果可能超过8位,所以要做32位除16位的除法,所以dx要清零
mov bx,4 ;除4
div bx
cmp dx,0 ;dx是余数,判断是否为0,不是0则肯定不是闰年
jnz not_leap
mov ax,cx ;ax恢复为待计算数字,这次计算的结果只需要8位就够,所以用16位除8位就行
mov bx,100 ;除100
div bl
cmp ah,0 ;ah是余数,如果为0,那还要继续判断,如果不为0,那就肯定是闰年了
jnz is_leap
mov ax,cx ;x恢复为待计算数字,因为要除以400,超过8位,所以用32位除16位除法
mov dx,0
mov bx,400
div bx
cmp dx,0 ;余数如果为0,说明是闰年
jz is_leap
jmp short not_leap ;不是闰年
is_leap:
lea dx,inf_ok ;是闰年的话,提示是闰年
mov ax,0900H
int 21H
jmp short end_sub
not_leap:
lea dx,inf_no ;不是闰年的话,提示不是闰年
mov ax,0900H
int 21H
end_sub:
pop dx
pop cx
pop bx
pop ax
ret
isleap endp
code ends
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -