匯編語言之計算器設計


題目描述:  

  計算器設計。在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

 結果示例:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM