判断闰年
data segment ;定义数据段infon db 0dh,0ah,'Please input a year: $'
Y db 0dh,0ah,'This is a leap year! $'
N db 0dh,0ah,'This is not a leap year! $'
w dw 0 ;用于保存输入的年份的数值,因为输入的年份是字符串,因此需要转换为数值
;定义输入缓冲区
buf db 8 ;第一个字节指出能容纳的最大字符个数,由用户给出,这里
;定义了8个字节的缓存区
db ? ;第二个字节存放实际输入的字符个数,由系统最后填入
db 8 dup(?) ;从第三个字节开始存放键盘接受的字符ASCII码值,直到enter结束键
data ends
stack segment stack
db 200 dup(0)
stack ends
code segment
assume ds:data,ss:stack,cs:code
start:mov ax,data
mov ds,ax
lea dx,infon ;在屏幕上显示提示信息。就是目标地址传送指令: 将一个近地址指针写入到
;指定的寄存器。格式:LEA reg16,mem16 其中reg16必须是一个16位通用寄存
;器,mem16必须是一个存储器,执行这个指令后,就将mem16所指的16位偏移地
;传送到reg16中
mov ah,9 ;显示字符串
int 21h
lea dx,buf ;从键盘输入年份字符串
mov ah,0Ah ;0AH功能调用从键盘接受字符串到内存的输入缓存区
int 21h
mov cl, buf+1 ;把输入的字符的个数保存在cl中(第二个字节存放实际输入的字符个数)
lea di,buf+2 ;把从键盘输入字符的首地址存放到di中
call datacate ;调用datacate子程序
call ifyears ;调用ifyears子程序
jc a1 ;jump if carry如果进位则跳转
lea dx,n ;输出不是闰年
mov ah,9
int 21h
jmp exit ;无条件跳转 跳转到退出返回操作系统
a1: lea dx,y ;输出是闰年
mov ah,9
int 21h
exit: mov ah,4ch ;返回操作系统
int 21h
datacate proc near ;用于把表示年份的字符串转换为数值
push cx; ;进栈操作,保存cx,即字符个数
dec cx ;让cx寄存器自减1
lea si,buf+2 ;把字符串的首地址保存在源地址寄存器SI中
;让si指向字符串的最低位
tt1: inc si ;si寄存器中内容增1(inc是增量指令,dec是减量指令)
loop tt1 ;loop是循环语句
pop cx ;出栈操作,与55行进栈操作相呼应
mov dh,30h
mov bl,10
mov ax,1
l1: push ax ;入栈操作,
sub byte ptr [si],dh ;由于字符是ASCII码表示的,因此减去30H后即可转换为十六进制数
mul byte ptr [si] ;计算ax乘以字符数字
add w,ax ;把计算结果累加,并保存在w中
pop ax ;出栈操作,去除上一次操作后的倍数
mul bl ;乘以bl,计算当前的倍数
dec si ;修改源地址寄存器si的值,使得si指向下一个字符(即高位)
loop l1 ;循环直到所有字符处理完毕(本程序中定义buf为8个字节,
;所以最多八个字符)
ret ;子程序返回指令
datacate endp
ifyears proc near ;此子程序用来判断年份是否为闰年
push bx ;将寄存器实行入栈操作是为了保存寄存器状态
push cx
push dx
mov ax,w ;把转换后的年份的数值存入AX
mov cx,ax ;把AX中存储的年份的数值存入CX,作用是复制一个年份数值,
;留作计算年份是否为100的整数倍用
;计算年份是否为4的整数倍
mov dx,0 ;把0存放到寄存器dx中(预先将dx清零,为后来除法指令第3种存储方法
;坐下铺垫)
mov bx,4 ;把4存放到寄存器bx中(除数)
div bx ;除法指令
;1、被除数16位,除数8位:被除数必须放在AX中,相除之后
;商放在AL中,余数放在AH中
;2、被除数8位,除数8位:被除数必须放在AL中,AH清零,相除之后
;商放在AL中,余数放在AH中
;3、被除数32位,除数16位:被除数必须放在DX,AX中,DX为高高字节
;商放在AX中,余数放在DX中
;4、被除数16位,除数16位:被除数必须放在AX中,DX清零,相除之后
;上放在AX中,余数放在DX中
;本例中 被除数为ax,整型数据占两个字节16位,除数(即源操作数)
;为整型数据4,也占两个字节16位,所以按照第3中方式存储
;余数放在dx中。
cmp dx,0 ;将dx中的余数与0进行比较,看似否整除
jnz lab1 ;JNZ用来判断比较的结果,如果有不等的数据则跳转。(zf=1则转移)
;判断年份是否为100的整数倍
mov ax,cx ;将前面复制到cx寄存器中的年份的数值传给ax
mov bx,100 ;将100赋给bx寄存器,做div的源操作数(除数)
mov dx,0
div bx ;本例中 被除数为ax,整型数据占两个字节16位,除数(即源操作数)
;为整型数据100,也占两个字节16位,所以按照第3中方式存储
cmp dx,0 ;将dx中的余数与0进行比较,看似否整除
jnz lab2 ;JNZ用来判断比较的结果,如果有不等的数据则跳转。(zf=1则转移)
;判断年份是否位400的整数倍
mov ax,cx
mov bx,400
mov dx,0
div bx
cmp dx,0
jz lab2
lab1: clc ;清除进位标志,即非闰年(进位标志用于标志是否为闰年)
jmp lab3 ;jmp无条件转移
lab2: stc ;设置进位标志,即闰年
lab3: pop dx ;出栈操作,寄存器状态。要注意的是出战顺序与入栈顺序是相反的
pop cx
pop bx
ret ;子程序返回指令
ifyears endp
code ends
end start
本程序在判断闰年是有一个问题,当大于1000时比如1100按理说不是闰年但是,程序判断出来的确实闰年,小于一千时,判断结果都是对的,比如900判断出来的就不是闰年,这是为什么呀?