• 汇编语言之计算器设计


    题目描述:  

      计算器设计。在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

     结果示例:

  • 相关阅读:
    Android入门第六篇之ListView (一)
    mysql触发器的作用及语法
    查询记录时rs.previous()的使用
    Microsoft Visual C++ Runtime Library Runtime Error的解决的方法
    Ubuntu中编译链接Opencv应用的简便方式
    24点经典算法
    CMS系统简介(从简介到使用)
    编程学习资源
    Django是什么
    Thinkphp中的自动验证
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12655543.html
Copyright © 2020-2023  润新知