題目描述:
計算器設計。在PC機上實現從鍵盤讀入數據,並完成加、減、乘、除的計算。要求:1)屏幕上顯示一個主菜單,提示用戶輸入相應的數字鍵,分別執行加、減、乘、除4種計算功能和結束程序的功能。若按其他鍵,則顯示提示輸入出錯並要求重新輸入,並繼續顯示主菜單。分別按數字鍵“1”、“2”、“3”,則執行相應子模塊1、2、3,進行兩個字節與兩個字節的加法、減法和乘法運算,並在屏幕上顯示運算結果。按數字鍵“4”,執行模塊4,進行兩字節除一個字節的除法運算。按數字鍵“5”,程序退出,返回DOS;2)要使用到子程序。
代碼:
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 menus db' MENU$' 12 input db' Please select a function!$' 13 number db' 1-add, 2-sub, 3-mult, 4-div, 5-exit$' 14 a db'You are adding. Please enter two numbers separated by a space$' 15 s db'You are subtracting. Please enter two numbers separated by a space$' 16 m db'You are in the process of multiplication. Please enter two numbers separated by a space$' 17 d db'You are in the process of division.Please enter two numbers separated by a space$' 18 e db'Exiting program$' 19 20 err db 'Illegal input! Please Try Again$' 21 again db'Invalid input, try again.$' 22 overout db'The number overflowed, try again$' 23 err1 db'The result is overflowed, try again$' 24 command db ? 25 flag db ? 26 temp dw 0 27 buf db 20,?,20 dup(0) ;定義鍵盤接收字符緩沖區,最多接收19個字符 28 ff db ? ;輸出的判斷前導0的標志 29 30 op1 dw ? ;定義兩個操作數(16位) 31 op2 dw ? 32 33 hex_buf db 4 dup(30h),'H' 34 crlf db '$' ;這是一個字符串的結尾符號,緊跟在緩沖區后可形成字符串,丟失后會產生 35 DATAS ENDS 36 37 STACKS SEGMENT 38 ;此處輸入堆棧段代碼 39 STACKS ENDS 40 41 CODES SEGMENT 42 ASSUME CS:CODES,DS:DATAS,SS:STACKS 43 START: 44 MOV AX,DATAS 45 MOV DS,AX 46 ;此處輸入代碼段代碼 47 48 ;注意每次做完了計算都要回到主菜單 49 menu: ;菜單部分 50 lea dx,menus 51 mov ah,9 52 int 21h 53 enterline 54 55 lea dx,input 56 mov ah,9 57 int 21h 58 enterline 59 60 lea dx,number 61 mov ah,9 62 int 21h 63 enterline 64 65 mov ah,1 ;字符存在AL里面 66 int 21h 67 68 judge: ;判斷執行哪個功能 69 cmp al,'1' 70 je a1 71 72 cmp al,'2' 73 je a2 74 75 cmp al,'3' 76 je a3 77 78 cmp al,'4' 79 je a4 80 81 cmp al,'5' 82 je stop 83 84 ;上面匹配都不成功,則把輸入當成無效的輸入,要求重新輸入 85 enterline 86 lea dx,again 87 mov ah,9 88 int 21h 89 enterline 90 jmp menu 91 92 a1: ;加法模塊 ;設計完加法子程序后把下面這部分也封裝進去 93 enterline ;這部分是輸出提示性語句 94 lea dx,a 95 mov ah,9 96 int 21h 97 enterline 98 99 call inputi ;調用輸入的子程序 100 cmp flag,1 101 je a1 ;由於錯誤輸入跳回a1重新進行加法操作 102 cmp flag,2 103 je a1 ;由於溢出跳回a1重新輸入 104 105 call addi ;調用加法子程序 106 cmp flag,2 107 je over 108 call outi 109 jmp menu ;執行完后跳回主菜單 110 111 over: 112 mov ax,op1 113 call to16str;將十進制轉化為十六進制 114 mov dx,offset hex_buf 115 mov ah,9 116 int 21h 117 118 mov ax,op2 119 call to16str;將十進制轉化為十六進制 120 mov dx,offset hex_buf 121 mov ah,9 122 int 21h 123 enterline 124 jmp menu ;執行完后跳回主菜單 125 a2: ;減法模塊 126 enterline 127 lea dx,s 128 mov ah,9 129 int 21h 130 enterline 131 132 call inputi ;調用輸入的子程序 133 cmp flag,1 134 je a2 ;由於錯誤輸入跳回a1重新進行加法操作 135 cmp flag,2 136 je a2 ;由於溢出跳回a1重新輸入 137 138 call subi 139 call outi 140 jmp menu ;執行完后跳回主菜單 141 142 a3: ;乘法模塊 143 enterline 144 lea dx,m 145 mov ah,9 146 int 21h 147 enterline 148 149 call inputi ;調用輸入的子程序 150 cmp flag,1 151 je a3 ;由於錯誤輸入跳回a1重新進行加法操作 152 cmp flag,2 153 je a3 ;由於溢出跳回a1重新輸入 154 155 call multi 156 157 mov ax,op1 158 call to16str;將十進制轉化為十六進制 159 mov dx,offset hex_buf 160 mov ah,9 161 int 21h 162 163 mov ax,op2 164 call to16str;將十進制轉化為十六進制 165 mov dx,offset hex_buf 166 mov ah,9 167 int 21h 168 enterline 169 170 jmp menu ;執行完后跳回主菜單 171 172 a4: ;除法模塊 173 enterline 174 lea dx,d 175 mov ah,9 176 int 21h 177 enterline 178 179 call inputi ;調用輸入的子程序 180 cmp flag,1 181 je a4 ;由於錯誤輸入跳回a1重新進行加法操作 182 cmp flag,2 183 je a4 ;由於溢出跳回a1重新輸入 184 185 call divi 186 cmp flag,1 187 je a4 ;由於除數可能輸0導致重新輸入 188 call outi 189 jmp menu ;執行完后跳回主菜單 190 191 stop: ;程序的結束 192 enterline 193 lea dx,e 194 mov ah,9 195 int 21h 196 197 MOV AH,4CH 198 INT 21H 199 200 201 inputi proc ;輸入子程序如下 202 mov flag,0 ;初始化flag 203 204 lea dx,buf ;從鍵盤接收輸入數值放入buf緩沖區(輸入操作) 205 mov ah,10 206 int 21h 207 enterline ;回車換行 208 209 210 mov cl,buf+1 ;獲取實際鍵入字符數,置於CX寄存器中 211 xor ch,ch ;ch清0 212 213 xor di,di ;累加器清0 214 xor dx,dx ;dX寄存器清0 215 mov bx,1 ;由於從個位數開始算起,因而將所乘權值設為1 216 217 lea si,buf+2 ;將si指向接收到的第1個字符位置 218 add si,cx ;因為從個位算起,所以將si指向最后1個接收到的個位數 219 dec si ;往回減1使其指向字串最后一個元素 220 221 ;cov是檢測並生成第一個數字的步驟 222 cov:mov al,[si] ;取出個位數給al 223 cmp al,' ' 224 jz next1 ;遇見空格則跳轉 225 226 cmp al,'0' ;邊界檢查:如果輸入不是0-9的數字,就報錯 227 jb wrong 228 cmp al,'9' 229 ja wrong 230 231 sub al,30h ;將al中的ascii碼轉為數字 232 xor ah,ah 233 mul bx ;乘以所處數位的權值 234 cmp dx,0 ;判斷結果是否超出16位數范圍,如超出則報錯 235 jne yichu 236 237 add di,ax ;將形成的數值疊加放在累加器di中 238 jc yichu ;CF是進位標志 239 240 mov ax,bx ;將BX中的數位權值擴大10倍,此處需要借助ax來實現 241 mov bx,10 242 mul bx 243 mov bx,ax 244 245 dec si ;si指針減1,指向前一數位 246 loop cov ;按CX中的字符個數計數循環 247 248 ;跳到次處表明第一個數字已經生成,接着去檢測第二個數字 249 next1: 250 mov op1,di ;將結果儲存在op1中4 251 xor ax,ax 252 xor di,di ;累加器清0 253 xor bx,bx 254 mov bx,1 ;由於從個位數開始算起,因而將所乘權值設為1 255 dec si ;向前移動一格位置 256 dec cx ;遇到空格cx相應的減少1 257 258 259 ;cov2是檢測並生成第2個數字 260 cov2: 261 mov al,[si] ;取出個位數給al 262 263 cmp al,'0' ;邊界檢查:如果輸入不是0-9的數字,就報錯 264 jb wrong 265 cmp al,'9' 266 ja wrong 267 268 sub al,30h ;將al中的ascii碼轉為數字 269 xor ah,ah 270 mul bx ;乘以所處數位的權值 271 cmp dx,0 ;判斷結果是否超出16位數范圍,如超出則報錯 272 jne yichu 273 274 add di,ax ;將形成的數值放在累加器di中 275 jc yichu ;CF是進位標志 276 277 mov ax,bx ;將BX中的數位權值擴大10倍,此處需要借助ax來實現 278 mov bx,10 279 mul bx 280 mov bx,ax 281 282 dec si ;si指針減1,指向前一數位 283 loop cov2 ;按CX中的字符個數計數循環 284 285 next2: 286 mov op2,di ;將結果儲存在op2中 287 jmp return ;結束后跳到return部分 288 289 wrong: 290 lea dx,err 291 mov ah,9 292 int 21h 293 mov flag,1 294 jmp return 295 296 yichu: 297 mov flag,2 298 lea dx,overout 299 mov ah,9 300 int 21h 301 302 return: 303 ret 304 inputi endp 305 306 addi proc ;加法子程序(16位數相加) 307 xor bx,bx 308 xor cx,cx 309 mov bx,op2 310 mov cx,op1 311 add bx,cx 312 cmp bx,op1 313 jb ex 314 cmp bx,op2 315 jb ex 316 jmp addret 317 ex: ;表示結果高於16位的加法操作 318 mov flag,2 319 mov op2,bx 320 mov op1,1 ;表示進位 321 322 addret: 323 ret 324 addi endp 325 326 subi proc ;減法子程序(16位數相減) 327 xor bx,bx 328 xor cx,cx 329 mov bx,op2 330 mov cx,op1 331 cmp bx,cx ;比較大小 332 jb fuhao 333 sub bx,cx ;結果儲存在bx中 334 jmp subret 335 fuhao: 336 mov dx,'-' 337 mov ah,2 338 int 21h 339 sub cx,bx 340 mov bx,cx 341 subret: 342 ret 343 subi endp 344 345 multi proc ;乘法子程序(16位數相乘) 346 xor ax,ax 347 xor cx,cx 348 mov ax,op2 349 mov cx,op1 350 mul cx ;結果存在dx:ax里面 351 mov op1,dx 352 mov op2,ax ;暫存在op1和op2 353 ret 354 multi endp 355 356 divi proc ;除法子程序(16位數除以8位數) 357 xor bx,bx ;注意 該程序的除數不能超過255 並且商也不能超過255 他們的承載能力只有8位 358 xor cx,cx 359 xor ax,ax 360 mov cx,op1 ;實際上存在cl中 361 cmp cx,255 ;讓cx的值處於0~255之間(因為寄存器是8位的) 362 ja divwrong 363 cmp cl,0 364 je divwrong 365 mov al,255 ;讓255和op1相乘,與op2比較,若小於op2則會發生divide error因此判斷非法 366 mul cl 367 cmp ax,op2 368 jb overflow 369 370 mov ax,op2 371 div cl ;字除以1字節型除法,商存在al中 372 mov ah,0 ;清除ah中的內容 373 mov bx,ax 374 jmp divret 375 divwrong: 376 lea dx,err 377 mov ah,9 378 int 21h 379 mov flag,1 380 overflow: 381 lea dx,err1 382 mov ah,9 383 int 21h 384 mov flag,1 385 divret: 386 ret 387 divi endp 388 389 outi proc 390 mov ax,bx ;待輸出的數先存在bx里面,在給ax 391 mov bx,10000 ;初始數位權值為10000 392 mov ff,0 ;每次都賦初值0 393 394 cov1:xor dx,dx ;將dx:ax中的數值除以權值 395 div bx 396 mov cx,dx ;余數備份到CX寄存器中 397 398 cmp ff,0 ;檢測是否曾遇到非0商值 399 jne nor1 ;如遇到過,則不管商是否為0都輸出顯示 400 cmp ax,0 ;如未遇到過,則檢測商是否為0 401 je cont ;為0則不輸出顯示 402 nor1: 403 mov dl,al ;將商轉換為ascii碼輸出顯示 404 add dl,30h 405 mov ah,2 406 int 21h 407 408 mov ff,1 ;曾遇到非0商,則將標志置1 409 cont: 410 cmp bx,10 ;檢測權值是否已經修改到十位了 411 je outer ;如果相等,則完成最后的個位數輸出顯示 412 413 xor dx,dx ;將數位權值除以10 414 mov ax,bx 415 mov bx,10 416 div bx 417 mov bx,ax 418 419 mov ax,cx ;將備份的余數送入AX 420 jmp cov1 ;繼續循環 421 outer: 422 mov dl,cl ;最后的個位數變為ascii碼輸出顯示 423 add dl,30h 424 mov ah,2 425 int 21h 426 enterline 427 ret 428 outi endp 429 430 to16str proc;功能:將十進制轉化為十六進制 431 mov bx,ax;將帶轉換的十進制數賦值給bx 432 mov si,offset hex_buf ;將字符串的首地址賦值給si 433 434 mov ch,4 ;將10進制轉為4位16進制數,每次操作1位,ch為當前還需要轉換的位數 435 loop_trans: 436 mov cl,4 437 rol bx,cl;此處cl的值為4,代表將BX中的值循環左移4位,bx中做該4位移動到最低4位 438 439 mov al,bl;從高到低提取四位二進制數送入al,和0fh進行與操作得bl中低4位 440 and al,0fh 441 442 add al,30h;al=0~9,加30h轉化為ascii碼 443 cmp al,3ah 444 jl next_trans 445 add al,7 ;al>9,加37h轉化為ascii碼,轉換為字母A~F 446 447 next_trans: 448 mov [si],al ;將轉換好的ascii碼賦值給字符串的si位置處 449 inc si ;si向后移動一位 450 dec ch ;代表還需轉換的位數減1 451 jnz loop_trans;注意,這兒只能用dec運算對標志位的設置來判斷循環與否 452 ;因為cl被用來存放位移數了 453 ret 454 to16str endp 455 CODES ENDS 456 END START
結果示例: