data segment ;定义数据段 infon db 0dh,0ah,'Please input a year: $' ;声明空间存储输入提示信息,其中0d回车,0a换行 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 db ? db 8 dup(?) ;声明空间作为缓冲区,总共10个字节,第一个表示准备接受的字 ;符数,即8;第二个表示实际接受的字符数,初始为空(?);后面8 ;个字节作为缓冲接收字符,后面两行只是做初始化工作 data ends stack segment stack db 200 dup(0) stack ends ;定义一个栈,200字节 code segment assume ds:data,ss:stack,cs:code start:mov ax,data mov ds,ax ;指定堆栈 lea dx,infon ;在屏幕上显示提示信息 mov ah,9 int 21h ;将infon开始的字符串输出到屏幕 lea dx,buf ;从键盘输入年份字符串 mov ah,10 int 21h mov cl, [buf+1] ;获取实际输入长度 mov ch,0 ;保证cx的值为[buf+1]对应字节的值 lea di,buf+2 ;获取字符串首地址 call datacate ;调用子程序,将输入字符串传化为年份数字 call ifyears ;调用子程序,判断是否闰年 jc a1 ;如果进位标记C为1则跳转到a1 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,保证下面的循环使si指向最后一个字符(buf中回车符前面的一个) lea si,buf+2 ;将buf中第一个字符(即buf的第三个字节数据)的地址赋给si tt1: inc si ;循环,使得si指向最后一个字符(即buf中回车符前面的一个) loop tt1 pop cx ;回复cx mov dh,30h ;辅助数据,用来将数字字符对应的ASCII码转换为其代表的数字本身 mov bl,10 ;辅助数据,用来在每进一位时使得ax乘以10 mov ax,1 ;ax用来装对应位的权值 l1: push ax ;备份ax push bx ;备份bx push dx ;备份dx,下面dx将接收乘法运算结果的高位(实际上在本例中它不起任何作用,因为乘法结果不会超过ax表示的范围,之所以需要是因为有时乘数(某些权值)要用两个字节来表示) sub byte ptr [si],dh ;将单个字符转换为对应的数字 mov bl, byte ptr [si] ;获取该位的数字 mov bh,0 ;因为:1.我们要用两个字节装对应位数字;2.该数字不会超过一个字节表示的范围 mul bx ;将改位数字乘以相应的权值,结果存储在ax中,我们预定年份最大值不超过两个字节表示的范围 add [w],ax ;加到结果上(易知当所有位都加完时,即是我们想要的年份数字) pop dx ;恢复dx pop bx ;恢复bx pop ax ;恢复ax mul bl ;权值乘以10 dec si ;si指向更高一位数字 loop l1 ret ;子程序返回 datacate endp ifyears proc near ;指明该子程序段在主程序段内,该子程序用于检测是否是闰年,接收年份数据,改变C标记位表示不同结果 push bx ;备份bx push cx ;备份cx,下面cx用于存储原始年份数据 push dx ;备份dx,下面dx用于存储除法余数 mov ax,[w] ;获取年份数据 mov cx,ax ;将年份数据备份到cx,因为后面做除法时ax值将会改变 mov dx,0 ;因为被除数要为32字节,高位在dx,本程序中为0 mov bx,100 ;这三行判断是否能被100整除 div bx cmp dx,0 jnz lab1 ;若不能被100整除,跳转到lab1 mov ax,cx ;否则判断能否被400整除 mov bx,400 div bx cmp dx,0 jz lab2 ;若能表示是闰年,跳转到lab2 clc ;否则不是闰年,将C标记位清零,并跳转到lab3 jmp lab3 lab1: mov ax,cx ;不能被100整除时跳转到此处,进一步判断能否被4整除 mov dx,0 mov bx,4 div bx cmp dx,0 jz lab2 ;若不能被100整除但能能被4整除是闰年,跳转到lab2 clc ;若不能被100整除也不能被4整除不是闰年,将c标志位置0,并跳转到lab3 jmp lab3 lab2: stc ;若是闰年跳转到此处将c标志位置1 lab3: pop dx ;相应寄存器恢复 pop cx pop bx ret ;子程序返回 ifyears endp code ends end start
本文对应的实例源码