汇编课设:实现身份证号验证功能并输出上面所给的信息

1、原题再现:
输入一个学生的身份证号码,程序检验身份证号码是否合法。并显示省份、年龄、性别等信息。
下面是身份证号码的规则:
身份证号码共18位。前6位是地址码,7–14位是出生年月日,后面4位是生成的代码,第17位用来做性别判定: 偶数 – 女 ; 奇数— 男 。
第十八位数字的计算方法为:
1)、 将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
2)、将这17位数字和系数相乘的结果相加。
3)、用加出来和除以11,看余数是多少?
4)、余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
5)、通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。

2、设计思路
功能主要分为两个部分,一是判断是否合法,二是输出身份信息,包括省份,出生日期,性别,年龄。

判断合法:包括判断:①首两位省份信息是否合法,即判断是否有省份的编码是输入的首两位。
②判断出生日期是否合法。首先判断月份数是不是合理,合理的话就判断接下来日期是否合理:先判断是不是二月,不在二月的话就只要判断日期数是否在最大与最小值之间即可;是二月就需要判断是否是闰年了:先判断日期是否>29或者<0,是的话就不合法,不是的话再判断是不是29,是的话,就判断前面年份数是否是闰年,是的话就合法,否则不合法。③判断第十八位是否合法。直接将十七位乘上系数再累加,最后除以11,根据余数判断尾数是否合法。④判断长度是否合法。直接将输入字符串的id[1],即实际输入长度(不包括回车)与18比较即可。
输出身份信息:输出省份信息、出身日期、年龄、性别。

最终界面:
在这里插入图片描述
3、具体实现
运行环境:DOSBox,怎么在DOSBox上运行汇编可参考:DOSBox里运行汇编程序
部分代码:(完整版在最后)

stack segment stack
     db 200 dup(0)
stack ends

data segment
            id db 20,?,20 dup('$')
         info1 db 'Please input your id:$'     ;提示输入id
         info2 db 'Your province is:$'         ;输出省份信息
         info3 db 'The number length is incorrect!$'   ;输入身份证号码位数不对
         info4 db 'The id number is of correct length!!$'  ;长度正确
         info5 db 'Id card number valid!!$'     ;进行多重检查后最后提示检查合格
         info6 db 'your gender is:$'        ;输出性别
         info7 db 'woman!$'
         info8 db 'man!$'
         info9 db 'The id number ends correctly!$'   ;身份证号尾数正确
        info10 db 'The last digit of the id number is incorrect!$'  ;尾数不正确
        info11 db 'Province information exists!$'  ;省份信息存在
        info12 db 'The province information does not exist!$'   ;省份信息不存在
       info13  db 'The current year is a leap year! Reasonable year of birth!$'   ;闰年
        info14 db 'The current year is not a leap year! The year of birth is not reasonable!$'   ;不是闰年
        info15 db 'Reasonable date of birth!$'   ;出生日期合理
        info16 db 'The date of birth is not reasonable!$'   ;出生日期不合理
        info17 db 'Congratulations, the id number entered is legal and valid!$'   ;最终判断合法且有效
        info18 db 'Your identity information is:$'    ;身份证信息为
        info19 db 'Your date of birth is:$'    ;输出出生日期
        info20 db 'Your age is:$'      ;输出年龄
      province db 11h,'BJ',12h,'TJ',13h,'HE',14h,'SX',15h,'NM'
               db 21h,'LN',22h,'JN',23h,'HL',31h,'SH'
               db 32h,'JS',33h,'ZJ',34h,'AH',35h,'FJ',36h,'JX'
               db 37h,'SD',41h,'HA',42h,'HB',43h,'HN'
               db 44h,'GD',45h,'GX',46h,'HI',50h,'CQ',51h,'SC'
               db 52h,'GZ',53h,'YN',54h,'XZ',61h,'SN'
               db 62h,'GS',63h,'QH',64h,'NX',65h,'XJ',71h,'TW'
               db 81h,'HK',82h,'MO',91h,'FOREIGN';省份编号
          coef db 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2   ;计算第18位数字时的系数
         final db 1,0,'X',9,8,7,6,5,4,3,2     ;18位可能的取值
      leapyear db 31,29,31,30,31,30,31,31,30, 31,30,31    ;闰年每月的天数
   notleapyear db 31,28,31,30,31,30,31,31,30,31,30,31     ;平年每月的天数
      divisors dw 10000,1000,100,10,1      ;将ax中的16进制年龄转成十进制然后输出
        result db 0,0,0,0,0,'$'     ;存放年龄
data ends

code segment
assume cs:code,ds:data,ss:stack

   checkbirth MACRO        ;判断出生日期是否合法
      local no
      local judge
      local yes
      local ff
      local leap
      clc
      push ax
      push bx
      push cx
      push dx
      push si
      push di
      xor ax,ax
      xor bx,bx
      xor cx,cx
      xor dx,dx
      mov al,id[12]   ;获取四位出生有效日期,不含年份
      mov bl,id[13]
      mov cl,id[14]
      mov dl,id[15]
      sub al,30h   ;01h
      sub bl,30h   ;02h
      sub cl,30h   ;00h
      sub dl,30h   ;08h
      mov di,10
      mov si,dx
      mul di   ;dx:ax=ax*di
      add ax,bx
      mov bx,ax   ;bx存储月份数12=c
      mov ax,cx
      mul di
      add ax,si  ;ax里面存储着天数8=8
      mov si,12
      cmp bx,si
      ja no   ;月份数大于12,不合理,直接退出
      mov si,0
      cmp bx,si
      jbe no   ;月份数<=0,不合理,直接退出
      jmp judge   ;月份数都合理,转向判断日期的部分
   no:display info16  ;出身日期不合理,请重新输入
      clc
      stc
      jmp exit
  yes:display info15   ;出生日期合理
      clc
      jmp exit

judge:xor cx,cx   ;先根据月份数找到可能的两种日期,即平年和闰年,分别存在cx,dx里面
      xor dx,dx
      mov si,bx
      mov cl,leapyear[si-1]    ;两种可能的天数
      mov dl,notleapyear[si-1]
      cmp cl,dl
      jz ff   ;两个日期数相同,就不需要判断是否为闰年了,只需要判断大小月是否满足
      mov si,29   ;该月份为2月
      cmp ax,si
      ja no   ;大于29显然不合理
      mov si,0
      cmp ax,si
      jbe no  ;<=0显然也不合理,否则就要判断是否是闰年了
      mov si,29
      cmp ax,si
      jz leap   ;日期为29则判断是不是闰年
      jmp yes  ;否则合理

leap:checkleapyear
     jc yes    ;返回CF=1说明是闰年,出生日期有效
     jnc no
  ff: cmp ax,cx      ;两个可能的天数一致,只需要判断大小月,即只需要判断天数是否在有有效区间内
      ja no   ;大于可能的最大日期,直接判断不合理
      mov si,0
      cmp ax,si
      jbe no    ;<=0也不合理
      jmp yes    ;否则一定会理的

 exit:pop di
      pop si
      pop dx
      pop cx
      pop bx
      pop ax
   ENDM
    
   checkleapyear MACRO     ;判断是不是闰年
      
   ENDM
   
   checkend MACRO   ;检查第十八位是否合法
      
   ENDM


   checkgender MACRO
      local woman
      local man
      local exit
      push bx
      xor bx,bx
      mov bl,id[18]  ;17位,表示性别
      display info6
      test bl,01h    ;1进行与运算判断奇偶
      jz woman
      lea dx,info8
      mov ah,09h
      int 21h
      jmp exit
 woman:lea dx,info7
       mov ah,09h
       int 21h
  exit:pop bx
   ENDM

   checklength MACRO   ;检查长度是否合格
      local corr
      local wrong
      local exit
      clc
      push ax
      mov al,[id+1]   ;id字符串的长度存在地址首位的下一位
      cmp al,18
      jnz wrong
corr:display info4
     jmp exit
wrong:display info3
      clc
      stc   ;cf=1表示长度不正确,继续输入
exit: pop ax
   ENDM


   checkprovince MACRO   ;检查前两位省份信息是否正确
      
   ENDM


   display MACRO x    ;输出字符串并换行
      push ax
      push dx
      newline
      mov ah,09h
      lea dx,x
      int 21h
      pop dx
      pop ax
   ENDM


   dispchar MACRO x    ;输出单个字符并换行
      push dx
      push ax
      newline
      mov ah,02h
      mov dl,x
      int 21h
      pop ax
      pop dx
   ENDM


   dispchar2 MACRO x    ;输出单个字符不换行,用于输出省份信息
      push dx
      push ax
      mov ah,02h
      mov dl,x
      int 21h
      pop ax
      pop dx
   ENDM


   
   assign MACRO r1,c1,r2,c2  ;这里犯了一个致命错误,就是把cx,dx压入堆栈,导致数据初始化不成功
      mov ch,r1
      mov cl,c1
      mov dh,r2
      mov dl,c2
   ENDM



   cls MACRO r1,c1,r2,c2,x   ;清屏并将光标置于左上角
      push ax
      push bx
      push dx
      mov ah,06h
      mov al,0
      mov bh,x
      assign r1,c1,r2,c2   ;设置入口值
      int 10h
      mov ah,02h  ;置光标位置
      mov bh,0
      mov dh,0
      mov dl,0
      int 10h
      pop dx
      pop bx
      pop ax
   ENDM


   getprovince MACRO   ;根据id获取省份信息
      
   ENDM
   

   getbirth MACRO    ;获取出生日期
   
   ENDM


   getage MACRO   ;获取年龄
     
   ENDM

   newline MACRO   ;回车换行
      push ax
      push dx
      mov ah,02h
      mov dl,0ah
      int 21h
      mov ah,02h
      mov dl,0dh
      int 21h
      pop dx
      pop ax
   ENDM

main: mov ax,data          ;主程序
      mov ds,ax
      cls 0,0,99,99,0bh
      clc   ;先将cf清零,下面备用
  agn:newline
      display info1
      mov ah,0ah    ;不合理则循环输入
      lea dx,id
      int 21h
      checkprovince   ;若不合理就让cf=1
      jc agn
      checklength     ;同样长度不为18就继续要求输入
      jc agn
      checkbirth    ;出生日期不合理
      jc agn
      checkend
      jc agn
      newline
      display info17  ;提示有效
      newline
      display info18   ;开始显示信息
      mov cx,30
      newline
 line1:mov dl,2dh    ;显示分割线------
      mov ah,02h
      int 21h
      loop line1
      getprovince    ;显示身份信息
      getbirth       ;显示出身日期
      getage        ;显示年龄信息
      checkgender    ;显示性别信息
      newline
      mov cx,30
line2:mov dl,2dh     ;显示分割线------
      mov ah,02h
      int 21h
      loop line2
      mov ah,4ch
      int 21h
code ends
     end main

完整代码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章