汇编语言之判断回文数

题目描述:

  打印回文数。如果一个数从左边和从右边读都是相同的数,就称它为回文数,例如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

 

 

 

   

posted @ 2020-03-26 19:51  neverstopcoding  阅读(1710)  评论(0编辑  收藏  举报