題目描述:
打印回文數。如果一個數從左邊和從右邊讀都是相同的數,就稱它為回文數,例如383。求出500 以內的回文數並輸出顯示。要求:提示數據范圍為0-500;Enter鍵,換行顯示結果。
基本功能:
每輸入一個數,都判斷是不是回文數(同時伴隨着溢出和錯誤輸入判斷);若出現溢出或者是錯誤輸入時,程序提示重新輸入。
拓展功能:
每輸入一個1到500的數,若該數是回文數,則輸出打印其中0到該數內的所有回文數;若不是回文數,則輸出提示不是回文數,並且結束程序。
基本功能代碼:
enterline macro ;定義回車換行的宏指令 mov dl,13 mov ah,2 int 21h mov dl,10 mov ah,2 int 21h endm DATAS SEGMENT input db 'Please input a number between 0 and 500:$' output1 db 'Convertion Success!$' err db 'Illegal input! Please Try Again$' out1 db 'Sorry, the number you entered is more than 500, please try again$' buf db 10,?,10 dup(0) ;定義鍵盤接收字符緩沖區,最多接收9個字符 len dw ? ;記錄輸入的數的長度 nop1 db 'The number you entered is not palindrome, bye$' sum dw ? space db ' ' ;空格 flag db 0 test1 db '333$' ;此處輸入數據段代碼 DATAS ENDS STACKS SEGMENT ;此處輸入堆棧段代碼 STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS START: MOV AX,DATAS MOV DS,AX ;此處輸入代碼段代碼 begin: lea dx,input ;給出輸入提示 mov ah,9 int 21h enterline ;回車換行 lea dx,buf ;從鍵盤接收輸入數值放入buf緩沖區(輸入操作) mov ah,10 int 21h enterline ;回車換行 push bx ;入棧保護 push cx push dx push si call ascii_num pop si ;退棧 pop dx pop cx pop bx ;接下來是回文數的檢測 考慮直接對字符進行回文數的檢測 jmp judge ;判斷輸入的數長度,結果存在cx中,si存入檢測的數 judgeovr: cmp flag,0 ;標志是否為輸出的那個數 je firstjudge firstjudge: mov flag,1 mov si,0 cmp cx,1 je loop_num cmp cx,2 je len2 cmp cx,3 je len3 len2: lea dx,test1 mov ah,9 int 21h enterline xor ax,ax xor dx,dx mov ax,sum mov bx,10 div bx cmp ax,dx je loop_num jmp not1 ;判斷出該數不是回文數 len3: xor ax,ax xor dx,dx xor di,di mov ax,sum mov bx,100 div bx mov di,ax mov ax,dx xor dx,dx mov bx,10 div bx cmp di,dx je loop_num jmp not1 ;判斷出該數不是回文數 loop_num: lea dx,output1 mov ah,9 int 21h jmp stop num_ascii: mov ax,si;(有效數值為0~65535) 待轉換數放置於AX寄存器中 mov bx,100 ;初始數位權值為100 cov1:xor dx,dx ;將dx:ax中的數值除以權值 div bx mov cx,dx ;余數備份到CX寄存器中 cmp flag,0 ;檢測是否曾遇到非0商值 jne nor1 ;如遇到過,則不管商是否為0都輸出顯示 cmp ax,0 ;如未遇到過,則檢測商是否為0 je cont ;為0則不輸出顯示 nor1: mov dl,al ;將商轉換為ascii碼輸出顯示 add dl,30h mov ah,2 int 21h mov flag,1 ;曾遇到非0商,則將標志置1 cont: cmp bx,10 ;檢測權值是否已經修改到十位了 je outer ;如果相等,則完成最后的個位數輸出顯示 xor dx,dx ;將數位權值除以10 mov ax,bx mov bx,10 div bx mov bx,ax mov ax,cx ;將備份的余數送入AX jmp cov1 ;繼續循環 outer: mov dl,cl ;最后的個位數變為ascii碼輸出顯示 add dl,30h mov ah,2 int 21h mov dl,space mov ah,2 int 21h jmp loop_num not1: ;不是回文數 lea dx,nop1 mov ah,9 int 21h enterline jmp stop ;如出錯則返回起始點重新輸入 error: ;給出錯誤提示(輸入不規范) lea dx,err mov ah,9 int 21h enterline jmp begin ;如出錯則返回起始點重新輸入 yichu: ;超過500范圍的提示 lea dx,out1 mov ah,9 int 21h enterline jmp begin ;如出錯則返回起始點重新輸入 judge: xor ax,ax xor dx,dx xor bx,bx xor cx,cx mov si,sum mov cx,1 ;最初長度賦值為1 mov ax,si ;將檢測的數賦值給ax mov bx,10 ;除數賦值10 div bx cmp ax,0 ;相等就跳走 je judgeovr mov cx,2 xor dx,dx mov ax,si ;將檢測的數賦值給ax mov bx,100 ;除數賦值10 div bx cmp ax,0 je judgeovr mov cx,3 jmp judgeovr stop: MOV AH,4CH INT 21H ascii_num PROC ;將字符串轉成數字的子程序 mov cl,buf+1 ;獲取實際鍵入字符數,置於CX寄存器中 xor ch,ch ;ch清0 mov len,cx ;這里把長度保存下來方便后面使用 xor di,di ;累加器清0 xor dx,dx ;dX寄存器清0 mov bx,1 ;由於從個位數開始算起,因而將所乘權值設為1 lea si,buf+2 ;將si指向接收到的第1個字符位置 add si,cx ;因為從個位算起,所以將si指向最后1個接收到的個位數 dec si ;往回減1使其指向字串最后一個元素 cov:mov al,[si] ;取出個位數給al cmp al,'0' ;邊界檢查:如果輸入不是0-9的數字,就報錯 jb error cmp al,'9' ja error sub al,30h ;將al中的ascii碼轉為數字 xor ah,ah mul bx ;乘以所處數位的權值 cmp dx,0 ;判斷結果是否超出16位數范圍,如超出則報錯 jne error add di,ax ;將形成的數值放在累加器di中 jc error ;如數值超過16位數范圍報錯 cmp di,500 ja yichu mov sum,di mov ax,bx ;將BX中的數位權值乘以10 mov bx,10 mul bx mov bx,ax dec si ;si指針減1,指向前一數位 loop cov ;按CX中的字符個數計數循環 mov ax,di ;將最終轉換結果從di中放置到ax中 EXIT: RET ascii_num ENDP CODES ENDS END START
拓展功能代碼:
1 enterline macro ;定義回車換行的宏指令 2 mov dl,13 3 mov ah,2 4 int 21h 5 mov dl,10 6 mov ah,2 7 int 21h 8 endm 9 10 DATAS SEGMENT 11 input db 'Please input a number between 0 and 500:$' 12 err db 'Illegal input! Please Try Again$' 13 out1 db 'Sorry, the number you entered is more than 500, please try again$' 14 buf db 10,?,10 dup(0) ;定義鍵盤接收字符緩沖區,最多接收9個字符 15 16 nop1 db 'The number you entered is not palindrome, bye$' 17 sum dw ? 18 space db ' ' ;空格 19 flag db 0 ;用於不輸出前導0的標志 20 ff db 0 ;用於標記是否為第一次回文數判斷 21 zero db 0 ;標志0是否輸出過 22 23 ;此處輸入數據段代碼 24 DATAS ENDS 25 26 STACKS SEGMENT 27 ;此處輸入堆棧段代碼 28 STACKS ENDS 29 30 CODES SEGMENT 31 ASSUME CS:CODES,DS:DATAS,SS:STACKS 32 START: 33 MOV AX,DATAS 34 MOV DS,AX 35 ;此處輸入代碼段代碼 36 37 begin: 38 lea dx,input ;給出輸入提示 39 mov ah,9 40 int 21h 41 enterline ;回車換行 42 43 lea dx,buf ;從鍵盤接收輸入數值放入buf緩沖區(輸入操作) 44 mov ah,10 45 int 21h 46 enterline ;回車換行 47 48 push bx ;入棧保護 49 push cx 50 push dx 51 push si 52 call ascii_num ;調用子程序輸入數據 53 pop si ;退棧 54 pop dx 55 pop cx 56 pop bx 57 58 mov si,sum ;將輸入的數的值先復制給si 59 call judge ;判斷輸入的數長度,結果存在cx中,si是待檢測的數 60 61 62 judgeovr: ;第二次及以后的回文數判斷 63 cmp ff,0 ;標志是否為輸出的那個數 64 je firstjudge 65 66 cmp cx,1 ;數只有一位時直接輸出 67 je num_ascii 68 cmp cx,2 ;數有兩位時跳轉到兩位數的回文判斷 69 je len22 70 cmp cx,3 ;數有三位時跳轉到三位數的回文判斷 71 je len33 72 73 len22: ;兩位數的回文判斷,判斷個位十位是否相同 74 xor ax,ax 75 xor dx,dx 76 mov ax,si 77 mov bx,10 78 div bx 79 cmp ax,dx 80 je num_ascii 81 82 jmp loop_num ;判斷出該數不是回文數,跳回loop_num去取下一個數 83 84 len33: ;三位數的回文判斷,判斷百位個位是否相同 85 xor ax,ax 86 xor dx,dx 87 xor di,di 88 mov ax,si 89 mov bx,100 90 div bx 91 mov di,ax 92 mov ax,dx 93 xor dx,dx 94 mov bx,10 95 div bx 96 cmp di,dx 97 je num_ascii 98 99 jmp loop_num ;判斷出該數不是回文數,跳回loop_num去取下一個數 100 101 102 firstjudge: ;對輸入的數進行第一次的回文判斷 103 mov ff,1 104 mov si,0 ;si從0開始,方便后面inc 105 106 cmp cx,1 ;數只有一位時直接跳轉去循環,代表輸入的數是回文數 107 je loop_num 108 cmp cx,2 ;數有兩位時跳轉到兩位數的回文判斷 109 je len2 110 cmp cx,3 ;數有三位時跳轉到三位數的回文判斷 111 je len3 112 113 len2: ;兩位數的回文判斷,判斷個位十位是否相同 114 xor ax,ax 115 xor dx,dx 116 mov ax,sum ;將輸入的值賦給ax去判斷 117 mov bx,10 118 div bx 119 cmp ax,dx 120 je loop_num ;判斷該數是回文數,跳轉循環 121 122 jmp not1 ;判斷出該數不是回文數,跳轉notq 123 124 len3: ;三位數的回文判斷,判斷百位各位是否相同 125 xor ax,ax 126 xor dx,dx 127 xor di,di 128 mov ax,sum ;將輸入的值賦給ax去判斷 129 mov bx,100 130 div bx 131 mov di,ax 132 mov ax,dx 133 xor dx,dx 134 mov bx,10 135 div bx 136 cmp di,dx 137 je loop_num ;判斷該數是回文數,跳轉循環 138 139 jmp not1 ;判斷出該數不是回文數,跳轉not1 140 141 142 loop_num: ;循環:代表輸入的數已經是回文數,接下來循環從0—輸入的數的回文數打印 143 144 inc si ;每次都去判斷,si的變化范圍是0—輸入的數,每次加1 145 cmp si,sum ;當大於輸入的數時跳轉停止 146 ja stop 147 148 call judge ;每次si加1后,都要去判斷si的長度,其中cx中存長度 149 ;judge判斷完長度后,會自動跳轉判斷回文數和打印數 150 151 jmp loop_num ;不斷循環 152 153 zz: ;該段程序是解決輸出0的問題 154 mov zero,1 ;0輸出過 155 156 mov dl,'0' 157 mov ah,2 158 int 21h 159 160 mov dl,space ;輸出空格 161 mov ah,2 162 int 21h 163 164 jmp num_ascii ;輸完0后再開始從1開始輸出 165 166 num_ascii: ;將num轉為ascii 167 cmp zero,0 ;判斷0是否輸出過,沒輸出就去輸出0 168 je zz 169 170 mov ax,si ;將每次循環計數的si賦值ax去輸出 171 mov bx,10 ;初始數位權值為10 172 cmp cx,3 ;若為3位數,則賦權為100 173 je cx_3 174 175 cov1:xor dx,dx ;將dx:ax中的數值除以權值 176 div bx 177 mov cx,dx ;余數備份到CX寄存器中 178 179 cmp flag,0 ;檢測是否曾遇到非0商值 180 jne nor1 ;如遇到過,則不管商是否為0都輸出顯示 181 cmp ax,0 ;如未遇到過,則檢測商是否為0 182 je cont ;為0則不輸出顯示 183 184 nor1: 185 mov dl,al ;將商轉換為ascii碼輸出顯示 186 add dl,30h 187 mov ah,2 188 int 21h 189 190 mov flag,1 ;曾遇到非0商,則將標志置1 191 192 cont: 193 cmp bx,10 ;檢測權值是否已經修改到十位了 194 je outer ;如果相等,則完成最后的個位數輸出顯示 195 196 xor dx,dx ;將數位權值除以10 197 mov ax,bx 198 mov bx,10 199 div bx 200 mov bx,ax 201 202 mov ax,cx ;將備份的余數送入AX 203 jmp cov1 ;繼續循環 204 205 outer: 206 mov dl,cl ;最后的個位數變為ascii碼輸出顯示 207 add dl,30h 208 mov ah,2 209 int 21h 210 211 mov dl,space ;輸出空格 212 mov ah,2 213 int 21h 214 215 jmp loop_num ;每次輸出完一個數后,跳回循環去取下一個數 216 217 218 219 cx_3: 220 mov bx,100 ;賦權值為100 221 jmp cov1 222 223 not1: ;不是回文數 224 lea dx,nop1 225 mov ah,9 226 int 21h 227 enterline 228 229 jmp stop ;如輸入不是回文數則返回起始點重新輸入 230 231 error: ;給出錯誤提示(輸入不規范) 232 lea dx,err 233 mov ah,9 234 int 21h 235 enterline 236 237 jmp begin ;如出錯則返回起始點重新輸入 238 239 yichu: ;超過500范圍的提示 240 lea dx,out1 241 mov ah,9 242 int 21h 243 enterline 244 245 jmp begin ;如出錯則返回起始點重新輸入 246 247 stop: 248 MOV AH,4CH 249 INT 21H 250 251 judge PROC ;判斷位數的子程序 252 xor ax,ax 253 xor dx,dx 254 xor bx,bx 255 xor cx,cx 256 mov cx,1 ;最初長度賦值為1 257 258 mov ax,si ;將檢測的數賦值給ax 259 mov bx,10 ;除數賦值10 260 div bx 261 cmp ax,0 ;商等於0就跳轉,去判斷回文數 262 je judgeovr 263 mov cx,2 264 265 xor dx,dx 266 mov ax,si ;將檢測的數賦值給ax 267 mov bx,100 ;除數賦值10 268 div bx 269 cmp ax,0 ;商等於0就跳轉,去判斷回文數 270 je judgeovr 271 272 mov cx,3 ;表明當前為數應該為三 273 jmp judgeovr ;去判斷回文數 274 275 EXIT: 276 RET 277 judge ENDP 278 279 ascii_num PROC ;將字符串轉成數字的子程序 280 281 mov cl,buf+1 ;獲取實際鍵入字符數,置於CX寄存器中 282 xor ch,ch ;ch清0 283 284 xor di,di ;累加器清0 285 xor dx,dx ;dX寄存器清0 286 mov bx,1 ;由於從個位數開始算起,因而將所乘權值設為1 287 288 lea si,buf+2 ;將si指向接收到的第1個字符位置 289 add si,cx ;因為從個位算起,所以將si指向最后1個接收到的個位數 290 dec si ;往回減1使其指向字串最后一個元素 291 292 cov:mov al,[si] ;取出個位數給al 293 cmp al,'0' ;邊界檢查:如果輸入不是0-9的數字,就報錯 294 jb error 295 cmp al,'9' 296 ja error 297 298 sub al,30h ;將al中的ascii碼轉為數字 299 xor ah,ah 300 mul bx ;乘以所處數位的權值 301 cmp dx,0 ;判斷結果是否超出16位數范圍,如超出則報錯 302 jne error 303 304 add di,ax ;將形成的數值放在累加器di中 305 jc error ;如數值超過16位數范圍報錯 306 307 cmp di,500 ;超過500的判斷 308 ja yichu 309 310 mov ax,bx ;將BX中的數位權值乘以10 311 mov bx,10 312 mul bx 313 mov bx,ax 314 315 dec si ;si指針減1,指向前一數位 316 loop cov ;按CX中的字符個數計數循環 317 318 mov sum,di ;將最終轉換結果從di中放置到sum中 319 EXIT: 320 RET 321 ascii_num ENDP 322 323 CODES ENDS 324 END START