题目描述:
加法练习程序。要求:从键盘输入百位数以内的加法算式,并提示输入答案,若正确给出正确提示,若错误给出错误提示,并提示输入答案;按R 键继续输入下一题,按Q 键返回DOS。
扩展功能:
支持多位加数相加
代码:
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 ;此处输入数据段代码 12 info db'Please enter an addition expression, such as A + B$' 13 err db 'Illegal input! Please Try Again$' 14 again db'Invalid input, try again.$' 15 overout db'The number overflowed, try again$' 16 overout1 db'The result overflowed, try again$' 17 inn db'Please enter your answer$' 18 win db'Congratulations, the answer is right$' 19 note db'Note: press the r key to continue to input the next question, and press the q key to exit the program$' 20 lose1 db'Sorry, your answer is wrong. You have 2 more chances$' 21 lose2 db'Sorry, your answer is wrong. You have 1 more chances$' 22 lose3 db'Sorry, your answer is wrong. The right answer is $' 23 24 result dw 0 ;用于存放最终结果 25 errtime db ? ;答案错误次数 26 flag db ? 27 28 buf db 30,?,30 dup(0) ;定义键盘接收字符缓冲区,最多接收19个字符 29 ff db ? ;输出的判断前导0的标志 30 input db ? ;储存输入的按键 31 32 op1 dw ? ;定义两个操作数 33 op2 dw ? 34 DATAS ENDS 35 36 STACKS SEGMENT 37 ;此处输入堆栈段代码 38 STACKS ENDS 39 40 CODES SEGMENT 41 ASSUME CS:CODES,DS:DATAS,SS:STACKS 42 START: 43 MOV AX,DATAS 44 MOV DS,AX 45 ;此处输入代码段代码 46 47 main: ;加法模块 ;设计完加法子程序后把下面这部分也封装进去 48 lea dx,info ;提示信息 49 mov ah,9 50 int 21h 51 enterline 52 53 mov errtime,3 ;允许犯错的次数 54 55 call inputi ;调用输入的子程序,输入公式 56 57 cmp flag,1 58 je main ;由于错误输入跳回a1重新进行加法操作 59 cmp flag,2 60 je main ;由于溢出跳回a1重新输入 61 62 63 shuru: 64 lea dx,inn ;提示输入信息 65 mov ah,9 66 int 21h 67 enterline 68 69 call input2 ;调用输入的子程序,输入答案 70 cmp flag,1 71 je shuru ;由于错误输入跳回shuru 72 cmp flag,2 73 je shuru ;由于错误输入跳回shuru 74 75 mov bx,result ;判断输入的答案是否正确 76 cmp bx,op1 77 je correct 78 79 dec errtime ;尝试次数减1 80 cmp errtime,2 ;剩余两次机会 81 je error1 82 cmp errtime,1 ;剩余1次机会 83 je error2 84 cmp errtime,0 ;不剩机会 85 je error3 86 87 error1: 88 lea dx,lose1 ;提示信息 89 mov ah,9 90 int 21h 91 enterline 92 jmp shuru ;执行完后跳回主菜单 93 error2: 94 lea dx,lose2 ;提示信息 95 mov ah,9 96 int 21h 97 enterline 98 jmp shuru ;执行完后跳回主菜单 99 error3: 100 lea dx,lose3 ;提示信息 101 mov ah,9 102 int 21h 103 mov bx,result ;result是正确的和 104 call outi ;输出正确结果,结束此题 105 enterline 106 107 judge1: ;结果错误时的按键提示 108 lea dx,note ;提示信息 109 mov ah,9 110 int 21h 111 enterline 112 113 call judge ;判断输入的键是什么键 114 enterline 115 cmp input,'r' 116 je main 117 cmp input,'q' 118 je stop 119 120 jmp judge1 121 correct: ;表示结果正确 122 lea dx,win ;提示信息 123 mov ah,9 124 int 21h 125 enterline 126 127 judge2: ;结果正确时的按键提示 128 lea dx,note ;提示信息 129 mov ah,9 130 int 21h 131 enterline 132 133 call judge ;判断输入的键是什么键 134 enterline 135 cmp input,'r' 136 je main 137 cmp input,'q' 138 je stop 139 jmp judge2 140 141 stop: 142 MOV AH,4CH 143 INT 21H 144 145 inputi proc ;输入子程序如下;专门用于存表达式的子程序 146 mov flag,0 ;初始化flag,用于标志错误或溢出 147 mov result,0 ;存放累加结果 148 149 lea dx,buf ;从键盘接收输入数值放入buf缓冲区(输入操作) 150 mov ah,10 151 int 21h 152 enterline ;回车换行 153 154 155 mov cl,buf+1 ;获取实际键入字符数,置于CX寄存器中 156 xor ch,ch ;ch清0 157 158 xor di,di ;累加器清0 159 xor dx,dx ;dX寄存器清0 160 mov bx,1 ;由于从个位数开始算起,因而将所乘权值设为1 161 162 lea si,buf+2 ;将si指向接收到的第1个字符位置 163 add si,cx ;因为从个位算起,所以将si指向最后1个接收到的个位数 164 dec si ;往回减1使其指向字串最后一个元素 165 166 ;cov是检测并生成第一个数字的步骤 167 cov:mov al,[si] ;取出个位数给al 168 cmp al,'+' 169 jz addi ;遇见空格则跳转 170 171 cmp al,'0' ;边界检查:如果输入不是0-9的数字,就报错 172 jb wrong 173 cmp al,'9' 174 ja wrong 175 176 sub al,30h ;将al中的ascii码转为数字 177 xor ah,ah 178 mul bx ;乘以所处数位的权值 179 cmp dx,0 ;判断结果是否超出16位数范围,如超出则报错 180 jne yichu 181 182 add di,ax ;将形成的数值叠加放在累加器di中 183 cmp di,99 184 ja yichu ;超过100报错 185 186 mov ax,bx ;将BX中的数位权值扩大10倍,此处需要借助ax来实现 187 mov bx,10 188 mul bx 189 mov bx,ax 190 191 dec si ;si指针减1,指向前一数位 192 loop cov ;按CX中的字符个数计数循环 193 194 lastadd: ;从后往前数的最后一个加数,执行lastadd时loop已经结束 195 mov bx,result 196 add bx,di ;存在bx寄存器中带回 197 mov result,bx ;备份结果在result中 198 jmp return 199 addi: 200 mov bx,result ;把当前累加值赋给bx 201 add bx,di ;di表示当前某一个加数 202 203 cmp bx,result ;判断是否溢出超过65535 204 jb yichu 205 mov result,bx ;将结果存回result 206 207 xor ax,ax 208 xor bx,bx 209 xor di,di ;累加器清0 210 mov bx,1 ;由于下一个加数又从个位数开始算起,因而将所乘权值设为1 211 212 dec si ;向前移动一格位置 213 dec cx ;遇到加号cx相应的减少1 214 jmp cov ;结束后跳到cov部分 215 216 wrong: ;输入错误 217 lea dx,err 218 mov ah,9 219 int 21h 220 mov flag,1 221 enterline 222 jmp return 223 224 yichu: ;加数超过100 225 mov flag,2 226 lea dx,overout 227 mov ah,9 228 int 21h 229 enterline 230 231 return: 232 ret 233 inputi endp 234 235 236 input2 proc ;专用于输入纯数字答案的子程序 237 mov flag,0 238 lea dx,buf ;从键盘接收输入数值放入buf缓冲区 239 mov ah,10 240 int 21h 241 enterline ;回车换行 242 243 mov cl,buf+1 ;获取实际键入字符数,置于CX寄存器中 244 xor ch,ch 245 xor di,di ;累加器清0 246 xor dx,dx ;DX寄存器清0 247 mov bx,1 ;由于从个位数开始算起,因而将所乘权值设为1 248 lea si,buf+2 ;将si指向接收到的第1个字符位置 249 add si,cx ;因为从个位算起,所以将si指向最后1个接收到的个位数 250 dec si 251 252 cov:mov al,[si] ;取出个位数给al 253 cmp al,'0' ;边界检查:如果输入不是0-9的数字,就报错 254 jb wrong2 255 cmp al,'9' 256 ja wrong2 257 258 sub al,30h ;将al中的ascii码转为数字 259 xor ah,ah 260 mul bx ;乘以所处数位的权值 261 cmp dx,0 ;判断结果是否超出16位数范围,如超出则报错 262 jne over2 263 264 add di,ax ;将形成的数值放在累加器di中 265 jc over2 ;如数值超过16位数范围报错 266 267 mov ax,bx ;将BX中的数位权值乘以10 268 mov bx,10 269 mul bx 270 mov bx,ax 271 dec si ;si指针减1,指向前一数位 272 loop cov ;按CX中的字符个数计数循环 273 274 mov op1,di ;将结果储存在op1中 275 jmp return2 276 277 wrong2: ;给出错误提示 278 lea dx,err 279 mov ah,9 280 int 21h 281 enterline 282 mov flag,1 283 284 jmp return2 285 286 over2: 287 lea dx,overout 288 mov ah,9 289 int 21h 290 enterline 291 mov flag,2 292 293 return2: 294 ret 295 input2 endp 296 297 outi proc ;输出子程序 298 mov ax,bx ;待输出的数先存在bx里面,在给ax 299 mov bx,10000 ;初始数位权值为10000 300 mov ff,0 ;每次都赋初值0 301 302 cov1:xor dx,dx ;将dx:ax中的数值除以权值 303 div bx 304 mov cx,dx ;余数备份到CX寄存器中 305 306 cmp ff,0 ;检测是否曾遇到非0商值 307 jne nor1 ;如遇到过,则不管商是否为0都输出显示 308 cmp ax,0 ;如未遇到过,则检测商是否为0 309 je cont ;为0则不输出显示 310 nor1: 311 mov dl,al ;将商转换为ascii码输出显示 312 add dl,30h 313 mov ah,2 314 int 21h 315 316 mov ff,1 ;曾遇到非0商,则将标志置1 317 cont: 318 cmp bx,10 ;检测权值是否已经修改到十位了 319 je outer ;如果相等,则完成最后的个位数输出显示 320 321 xor dx,dx ;将数位权值除以10 322 mov ax,bx 323 mov bx,10 324 div bx 325 mov bx,ax 326 327 mov ax,cx ;将备份的余数送入AX 328 jmp cov1 ;继续循环 329 outer: 330 mov dl,cl ;最后的个位数变为ascii码输出显示 331 add dl,30h 332 mov ah,2 333 int 21h 334 enterline 335 ret 336 outi endp 337 338 judge proc 339 mov ah,1 340 int 21h 341 mov input,al ;将储存的字符给input 342 ret 343 judge endp 344 345 346 CODES ENDS 347 END START