仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
image.png

可以循环计数

image.png

关机状态

image.png

8086汇编语言源程序如下:

        DATA  SEGMENT
  •            X  DB        ?,?,?,?     ;存放数据的每一位
  •           X1  DW        ?           ;存放第一个数据值
  •           X2  DW        ?           ;存放第二个数据值
  •            Y  DW        ?           ;存放运算结果
  •            S  DB        ?           ;存放运算符号值
  •            E  DB        ?           ;按下等号键标记
  •           CC  DB        ?           ;存放运算数据位数
  •            H  DB        0           ;存放按键行号
  •            L  DB        0           ;存放按键列号
  •      DISCODE  DB        3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H         ;段码表
  •         DATA  ENDS
  •         CODE  SEGMENT
  •               ASSUME    CS:CODE,DS:DATA
  •       START:  MOV       AX,DATA
  •               MOV       DS,AX
  •               MOV       AL,90H      ;设置为A口输入,B口输出,C口输出
  •               OUT       46H,AL
  •               MOV       DI,OFFSET X+3           ;DI指向X的高位
  •         KKK:  CALL      KEY         ;扫描按键
  •               JMP       KKK
  • ;以下为按键扫描子程序,程序返回后,在变量H和L中存放当前按键的行列号
  •          KEY  PROC
  •       CHECK:  CALL      DISP        ;等待按键按下的同时进行显示
  •               MOV       AL,0F0H     ;所有行输出低电平
  •               OUT       44H,AL
  •               IN        AL,40H
  •               CMP       AL,0FFH     ;读列值
  •               JZ        CHECK       ;若都为高电平则无键按下,等待
  •               MOV       CX,50
  •               LOOP      $           ;延时消抖
  •               IN        AL,DX       ;重读列值
  •               CMP       AL,0FFH
  •               JZ        CHECK       ;无键按下一直等待
  •               MOV       H,0         ;有键按下,先把行列号变量清0
  •               MOV       L,0
  •               MOV       BL,01H
  •               MOV       BH,0FEH     ;扫描法读键值:从第一行开始测试,即PC0输出低电平
  •        NEXT:  MOV       AL,BH
  •               OUT       44H,AL
  •       NEXTH:  IN        AL,40H      ;读列值,判断是第几列有键按下
  •               TEST      AL,BL       ;从第一列开始判断
  •               JZ        WAIT0
  •               ROL       BL,1
  •               CMP       BL,10H      ;当前行状态下没有任何列有键按下,则转为对下一行的测试
  •               JZ        NEXTL
  •               INC       H           ;每判断一列,列号加1
  •               JMP       NEXTH       ;再对下一列进行判断
  •       NEXTL:  MOV       H,0
  •               MOV       BL,01H
  •               ROL       BH,1        ;对下一行测试,让下一个PC口输出低电平
  •               CMP       BH,0EFH
  •               JZ        EXIT
  •               INC       L
  •               JMP       NEXT
  •       WAIT0:  IN        AL,40H      ;若有键按下,则等该按键松开后再计算键值
  •               CMP       AL,0FFH
  •               JNZ       WAIT0
  •               MOV       CX,50
  •               LOOP      $           ;延时消抖
  •               IN        AL,40H
  •               CMP       AL,0FFH
  •               JNZ       WAIT0
  •               CALL      KEYVALUE    ;调计算键值子程序
  •        EXIT:  RET
  •          KEY  ENDP
  •    ;以下为计算键值子程序,通过行列号计算键值(键值=列号*4+行号)
  •    ;键值存放在DL寄存器中
  •     KEYVALUE  PROC
  •               MOV       DL,L
  •               MOV       DH,H
  •               SHL       DL,1
  •               SHL       DL,1        ;列号乘4
  •               ADD       DL,DH
  •               CMP       DL,9        ;按下的是数字键
  •               JNG       NUM_CALL
  •               CMP       DL,14
  •               JL        CONT_CALL   ;按下的是运算键
  •               CMP       DL,14
  •               JZ        OUTP_CALL   ;按下的是等于键
  •               CMP       DL,15
  •               JZ        CLR_CALL    ;按下的是清除键
  •    NUM_CALL:  CALL      NUMBER      ;调数字键处理子程序
  •               JMP       EXIT1
  •   CONT_CALL:  MOV       S,DL        ;存放运算键的键值
  •               MOV       E,0
  •               CALL      COUNT       ;调运算键处理子程序,计算第一个加数
  •               JMP       EXIT1
  •   OUTP_CALL:  CALL      OUTP        ;调等号键处理子程序
  •               JMP       EXIT1
  •    CLR_CALL:  CALL      CLEAR       ;调清除键处理子程序
  •       EXIT1:  RET
  •     KEYVALUE  ENDP
  • ;以下为清除键处理子程序,按下清除键后,X变量全部清0
  •        CLEAR  PROC
  •               MOV       X[3],0
  •               MOV       X[2],0
  •               MOV       X[1],0
  •               MOV       X[0],0
  •               CALL      BITP
  •               RET
  •        CLEAR  ENDP
  • ;以下为等号键处理子程序,该子程序负责将第二个运算数据的数值计算出来存入X2变量
  • ;并根据运算符号,调用相应的运算子程序
  •         OUTP  PROC
  •               PUSH      AX
  •               PUSH      DX
  •               PUSH      BX
  •               INC       E
  •               CALL      COUNT       ;调运算键处理子程序,计算第二个运算数据
  •               CMP       S,10
  •               JZ        ADD_CALL    ;运算符为加号,则调用加法子程序
  •               CMP       S,11
  •               JZ        SUB_CALL    ;运算符为减号,则调用减法子程序
  •               CMP       S,12
  •               JZ        MUL_CALL    ;运算符为乘号,则调用乘法子程序
  •               CMP       S,13
  •               CALL      DIVP        ;运算符为除号,则调用除法子程序
  •               JMP       STORE1
  •    ADD_CALL:  CALL      ADDP
  •               JMP       STORE1
  •    SUB_CALL:  CALL      SUBP
  •               JMP       STORE1
  •    MUL_CALL:  CALL      MULP
  •      STORE1:  MOV       AX,Y        ;以下程序将各运算子程序返回的运算结果,按位分解,送入X变量
  •               MOV       DX,0
  •               MOV       BX,1000
  •               DIV       BX
  •               MOV       X[0], AL
  •               MOV       AX,DX
  •               MOV       BL,100
  •               DIV       BL
  •               MOV       X[1],AL
  •               MOV       AL,AH
  •               MOV       AH,0
  •               MOV       BL,10
  •               DIV       BL
  •               MOV       X[2],AL
  •               MOV       X[3],AH
  •               POP       BX
  •               POP       DX
  •               POP       AX
  •               RET
  •         OUTP  ENDP
  • ;以下为运算键处理子程序,该程序将第一个运算数据的数值计算出来并存入X1变量
  • ;或者将第二个运算数据的数值计算出来并存入X2变量
  • ;将运算符的值存入S变量
  •        COUNT  PROC
  •               PUSH      AX
  •               PUSH      BX
  •               PUSH      DX
  •               MOV       DX,0
  •               CALL      BITP        ;测试X中的数据是多少位
  •               CMP       CC,4        ;输入的数据是4位数 ?
  •               JZ        C4
  •               CMP       CC,3        ;输入的数据是3位数 ?
  •               JZ        C3
  •               CMP       CC,2        ;输入的数据是2位数 ?
  •               JZ        C2
  •               JMP       C1          ;输入的数据是1位数 ?
  •          C4:  MOV       AX,0
  •               MOV       AL,X[0]
  •               MOV       BX,1000
  •               MUL       BX
  •               MOV       DX,AX
  •          C3:  MOV       AL,X[1]
  •               MOV       BL,100
  •               MUL       BL
  •               ADD       DX,AX
  •          C2:  MOV       AL,X[2]
  •               MOV       BL,10
  •               MUL       BL
  •               ADD       DX,AX
  •          C1:  MOV       AL,X[3]
  •               MOV       AH,0
  •               ADD       DX,AX
  •               CMP       E,1
  •               JNZ       X1_S
  •               MOV       X2,DX       ;按下的是等号,则将第二个运算数据的值存入X2变量
  •               JMP       EXIT3
  •        X1_S:  MOV       X1,DX       ;按下的是运算符号,则将第一个运算数据的值存X1变量
  •               MOV       X[3],0      ;清空X变量
  •               MOV       X[2],0
  •               MOV       X[1],0
  •               MOV       X[0],0
  •       EXIT3:  POP       DX
  •               POP       BX
  •               POP       AX
  •               RET
  •        COUNT  ENDP
  • ;以下为数字键处理子程序
  • ;该程序,将输入的数据按位存放在X变量中,并由CC记录数据的位数
  •       NUMBER  PROC
  •               CMP       E,1
  •               JNZ       CONTINUE
  •               MOV       E,0
  •               CALL      CLEAR
  •    CONTINUE:  CMP       CC,0        ;目前数据为0位,即没有数据,则转到SSS
  •               JZ        SSS
  • ;若已有数据,以下程序将X左移8位。
  • ;例如:先输入“1”,当再输入2时,
  • ;先要将“1”从个位移到十位,然后再将“2”存放到个位
  •               PUSH      AX
  •               PUSH      DX
  •               MOV       AL,X[3]
  •               MOV       AH,X[2]
  •               MOV       DL,X[1]
  •               MOV       DH,X[0]
  •               MOV       CX,8
  •          LL:  SHL       AX, 1
  •               RCL       DX,1
  •               LOOP      LL
  •               MOV       X[3],AL
  •               MOV       X[2],AH
  •               MOV       X[1],DL
  •               MOV       X[0],DH
  •               POP       DX
  •               POP       AX
  •         SSS:  MOV       [DI],DL     ;将当前键入的数据存放到X的最低位
  •               INC       CC          ;数据位数加1
  •               CMP       CC,4        ;判断数据位数
  •               JNG       EXIT2
  •               MOV       CC,0        ;如果数据超过4位,重新从最低位开始存放
  •               MOV       X[2],0
  •               MOV       X[1],0
  •               MOV       X[0],0
  •       EXIT2:  CALL      DISP        ;调显示子程序,显示输入的数据
  •               RET
  •       NUMBER  ENDP
  • ;加法子程序
  •         ADDP  PROC
  •               PUSH      AX
  •               MOV       AX,X1
  •               ADD       AX,X2
  •               MOV       Y,AX
  •               POP       AX
  •               RET
  •         ADDP  ENDP
  • ;减法子程序
  •         SUBP  PROC
  •               PUSH      AX
  •               MOV       AX,X1
  •               SUB       AX,X2
  •               MOV       Y,AX
  •               POP       AX
  •               RET
  •         SUBP  ENDP
  • ;乘法子程序
  •         MULP  PROC
  •               PUSH      AX
  •               PUSH      DX
  •               MOV       AX,X1
  •               MOV       DX,X2
  •               MUL       DX
  •               MOV       Y,AX
  •               POP       DX
  •               POP       AX
  •               RET
  •         MULP  ENDP
  • ;除法子程序
  •         DIVP  PROC
  •               PUSH      AX
  •               PUSH      BX
  •               PUSH      DX
  •               MOV       DX,0
  •               MOV       AX,X1
  •               MOV       BX,X2
  •               DIV       BX
  •               MOV       Y,AX
  •               POP       DX
  •               POP       BX
  •               POP       AX
  •               RET
  •         DIVP  ENDP
  • ;显示子程序 ,将X中的数值按位显示出来
  •         DISP  PROC
  •               PUSH      BX
  •               PUSH      AX
  •               MOV       BH,0
  •               LEA       SI,DISCODE
  •               CALL      BITP        ;测试X位数
  •               CMP       CC,4
  •               JZ        QIAN
  •               CMP       CC,3
  •               JZ        BAI
  •               CMP       CC,2
  •               JZ        SHI
  •               CMP       CC,1
  •               JMP       G
  •               JMP       NONE
  •        QIAN:  MOV       AH,11100000B            ;从第4位开始显示
  •               MOV       AL,AH
  •               OUT       44H,AL
  •               MOV       BL,X[0]
  •               MOV       AL,[SI+BX]
  •               OUT       42H,AL
  •               CALL      DELY
  •               MOV       AL,0
  •               OUT       42H,AL
  •         BAI:  MOV       AH,11010000B            ;从第3位开始显示
  •               MOV       AL,AH
  •               OUT       44H,AL
  •               MOV       BL,X[1]
  •               MOV       AL,[SI+BX]
  •               OUT       42H,AL
  •               CALL      DELY
  •               MOV       AL,0
  •               OUT       42H,AL
  •         SHI:  MOV       AH,10110000B            ;从第2位开始显示
  •               MOV       AL,AH
  •               OUT       44H,AL
  •               MOV       BL,X[2]
  •               MOV       AL,[SI+BX]
  •               OUT       42H,AL
  •               CALL      DELY
  •               MOV       AL,0
  •               OUT       42H,AL
  •           G:  MOV       AH,01110000B            ;从第1位开始显示
  •               MOV       AL,AH
  •               OUT       44H,AL
  •               MOV       BL,X[3]
  •               MOV       AL,[SI+BX]
  •               OUT       42H,AL
  •               CALL      DELY
  •               JMP       EXIT4
  • ……………………
  • …………限于本文篇幅 余下代码请下载附件…………
  • 复制代码