|
题目描述:
打印回文数。如果一个数从左边和从右边读都是相同的数,就称它为回文数,例如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
来源:https://www.cnblogs.com/xwh-blogs/p/12576877.html |