彙編課設:實現身份證號驗證功能並輸出上面所給的信息

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

完整代碼

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