微机原理与接口应用实验课

微机实验

分支
.486
DATA SEGMENT USE16
NUM1 DD 2A8B7654H
NUM2 DW 5ABCH
NUM3 DW ?
NUM4 DW ?
DATA ENDS

CODE SEGMENT USE16
    ASSUME DS:DATA, CS:CODE

START:
        ;装载数据段
        MOV AX,DATA
        MOV DS,AX
        ;将被除数的高16位和低16位分别装载到DX,AX
        MOV AX,WORD PTR NUM1
        MOV DX,WORD PTR NUM1+2
        ;除以立即数NUM2
        DIV NUM2

        ;将保存在AX,DX的商和余数分别保存到变量NUM3和NUM4
        MOV NUM3,AX
        MOV NUM4,DX

        ;返回DOS
        MOV AH,4CH
        INT 21H
    CODE ENDS
        END START

.486
DATA SEGMENT USE16
ARY DB 1BH,?,?
DATA ENDS

CODE SEGMENT USE16
    ASSUME DS:DATA, CS:CODE

START:
        ;装载数据段
        MOV AX,DATA
        MOV DS,AX
        ;将SI指向数组头
        LEA SI,ARY

        ;取高4位即逻辑右移4位,高位补零
        MOV AL,[SI]
        SHR AL,4
        MOV [SI+1],AL

        ;取第四位即高位与0相与
        MOV AL,[SI]
        AND AL,0FH
        MOV [SI+2],AL

        ;返回DOS
        MOV AH,4CH
        INT 21H
    CODE ENDS
        END START

.486
DATA SEGMENT USE16
A DB 03H
B DB 03H
C DB 03H
K DB ?
DATA ENDS

CODE SEGMENT USE16
    ASSUME DS:DATA, CS:CODE

START:
            ;装载数据段
            MOV AX,DATA
            MOV DS,AX

	        ;CMP指令不能两个操作数都是存储器,将B放入BL,C放入BH
	        MOV BL,B
	        MOV BH,C

            ;若A=B则跳转到 AeqB
            CMP A,BL
            JE AeqB
            ;若B=C则跳转到 K1
            CMP BL,C
            JE K1
            ;若C=A则跳转到 K1,否则跳转到K0
            CMP A,BH
            JE K1
            JMP K0

            ;若B=C则跳转到K2,否则跳转到K1
    AeqB:   CMP BL,BH
            JE K2
            JMP K1

    K0:
            MOV K,0
            JMP DONE
    K1:
            MOV K,1
            JMP DONE
    K2:
            MOV K,2
;返回DOS
DONE:
        MOV AH,4CH
        INT 21H

        CODE ENDS
            END START

.486
DATA SEGMENT USE16
A DB 10H
B DB 11H
C DB 12H
N DB ?
DATA ENDS

CODE SEGMENT USE16
    ASSUME DS:DATA, CS:CODE

START:
        ;装载数据段
        MOV AX,DATA
        MOV DS,AX
        ;由于CMP两个操作数不能都为立即数,故将B存到BL
	    MOV BL,B
        ;比较A与B的大小
	    CMP A,BL
        ;若A<=B则跳转到BbiggerA
        JNA BbiggerA
        ;不跳转则完成A-B+C,结果保存到变量N
        MOV AL,A
        SUB AL,B
        ADD AL,C
        MOV N,AL
        JMP DONE

    BbiggerA:
            ;完成A+B,结果保存到变量N
            MOV AL,A
            ADD AL,B
            MOV N,AL

        ;返回DOS
    DONE:
        MOV AH,4CH
            INT 21H
CODE ENDS
    END START

循环
.486
DATA    SEGMENT USE16
STRN    DB  '1234$'
LEN     EQU $-STRN
N      DB  ?
DATA ENDS

CODE    SEGMENT
    ASSUME DS:DATA, CS:CODE

    START:
        ;装载数据段
        MOV AX,DATA
        MOV DS,AX
        ;使用AL来计次,将SI指向字符串头,将数组长度LEN即循环次数存入CX
        MOV AL,0
        LEA SI,STRN
        MOV CX,LEN

    TRY:
        ;取出当前SI所指向的字符,与自身相与,值不变,根据PF的改变判断1个数的奇偶
        MOV BL,[SI]
        AND BL,BL
        ;若PF=1,即偶数个1,则无需改变,跳转到 NEXT
        JP  NEXT
        ;若PF=0,即奇数个1,则令最高位为1,即与80H相或
        OR BL,80H
        ;将加上偶校验位的值覆盖原值,并将计数+1
        MOV [SI],BL
        INC AL

    NEXT:
        ;SI自增1,即指向字符串的下一个字符
        INC SI
        ;循环重复之前的步骤
        LOOP    TRY

        ;最终结果保存在变量N中
        MOV N,AL

        MOV AH, 4CH
        INT 21H
CODE ENDS
    END START

.486
DATA    SEGMENT USE16
N       DB  ?
FIRST   DB  01H, 03H, 20 DUP(2), 00H, 05H, 00H, 74 DUP(4), 0AAH
LEN     EQU $-FIRST
ZERO    DB  00H
DATA ENDS

CODE SEGMENT USE16
    ASSUME CS:CODE, DS:DATA
    START:
        MOV AX,DATA
        MOV DS,AX

        LEA SI,FIRST
        MOV CX,LEN
        MOV AL,0
    DO:
        MOV BL,[SI]
        CMP BL, ZERO
        JZ  DONE
        INC AL
        INC SI
        LOOP    DO
    DONE:
        MOV N, AL

        MOV AH,4CH
        INT 21H
CODE ENDS
    END START

子程序
.486
DATA    SEGMENT USE16
BUF DB  5 DUP(3AH), 2 DUP(0F2H), 3 DUP(79H)
LEN EQU $-BUF
DATA    ENDS

CODE SEGMENT
    ASSUME DS:DATA, CS:CODE

    START:
        ;装载数据段
        MOV AX, DATA
        MOV DS, AX
        ;将SI指向字符串头,字符串长度存入CX
        LEA SI, BUF
        MOV CX, LEN
    TRY:
        ;先转换高4位并显示
        MOV AL, [SI]
        SHR AL, 4
        CALL HEXASC
        MOV AH, 02H
        INT 21H

        ;再转换低四位并显示
        MOV AL, [SI]
        AND AL, 0FH
        CALL HEXASC
        MOV AH, 02H
        INT 21H

        ;每显示一个字节的两个字符后就显示一个空格
        MOV DL, 20H
        MOV AH, 02H
        INT 21H

        ;循环重复上面步骤
        INC SI
        LOOP    TRY

    DONE:
        MOV AH, 4CH
        INT 21H


    HEXASC  PROC    NEAR
        ;加上30H后如果大于'9'的ASCII码39H,则表示要显示的字符是字母
        PUSH    AX
        ADD AL, 30H
        CMP AL, 39H
        JA  NotNum
        MOV DL, AL
        JMP RE
        ;则再加上07H得到字母的ASCII码
    NotNum:
        ADD AL, 07H
        MOV DL, AL
    RE:
        POP AX
        RET
    HEXASC  ENDP
CODE ENDS
    END START

.486
DATA    SEGMENT USE16
X   DB  'x'
BUF DB  20
N   DB  0
TB   DB  20 DUP(0)
DATA    ENDS

MAIN    SEGMENT USE16
    ASSUME  DS:DATA, CS:MAIN

START:
    ;装载数据段
    MOV AX, DATA
    MOV DS, AX

    ;输入字符串
    LEA DX, BUF
    MOV AH, 0AH
    INT 21H

    ;换行
    MOV DL, 0AH
    MOV AH, 02H
    INT 21H

    ;显示X
    MOV DL, X
    MOV AH, 02H
    INT 21H

    ;显示空格
    MOV DL, 20H
    MOV AH, 02H
    INT 21H

    ;通过堆栈传递参数
    LEA BX, TB
    PUSH BX
    LEA BX, N
    PUSH BX
    LEA BX, X
    PUSH BX

    ;调用子程序
    CALL FAR PTR CountX

    ;加上30H或37H转换为ASCII码,显示结果
    ADD DL, 30H
    CMP DL, 39H
    JA  NotNum
    JMP SOUT
    ;如果大于39H,则再加上07H得到字母的ASCII码
NotNum:
    ADD DL, 07H
SOUT:
    MOV AH, 02H
    INT 21H

    ;结束程序
    MOV AH, 4CH
    INT 21H
MAIN    ENDS

SPRO    SEGMENT USE16
    ASSUME  DS:DATA, CS:SPRO
    CountX  PROC    FAR
        ;保护现场
        PUSH    SI
        PUSH    BP
        PUSH    CX
        PUSH    AX

        ;将堆栈中的传递的参数赋值给寄存器,BP指向栈顶,CX为字符串长度N,AL保存'x'的ASCII码,AH保存当前指向的字符,DL用来计次
        MOV BP, SP
        MOV DL, 0
        ;MOV CX, [BP+14]这只能拿到N在DS中的偏移量
        MOV SI, [BP+14]
        MOV CL, [SI]

        MOV SI, [BP+12]
        MOV AL, [SI]

        MOV SI, [BP+16]
        MOV AH, [SI]

    AGAIN:
        CMP AH, AL
        JNE  LP
        INC DL
    LP:
        INC SI
        MOV AH, [SI]
        LOOP    AGAIN

        ;还原现场
        POP AX
        POP CX
        POP BP
        POP SI
        ;还原传递参数占用的堆栈
        RET 6
    CountX ENDP
SPRO    ENDS
    END START

DOS
.486
DATA	SEGMENT	USE16
STRN	DB	3
LEN		DB	0
BUF		DB	3 DUP(0)
WRN		DB	0AH, 'ERROR', 0AH, '$'
SUCC	DB	0AH, 'RIGHT', 0AH, '$'
FLAG	DB 	?
DATA	ENDS

CODE	SEGMENT	USE16
	ASSUME	DS:DATA, CS:CODE
START:
	;load
	MOV	AX, DATA
	MOV	DS, AX

INP:
	;检查到错误则将FLAG=0
	MOV FLAG, 1
	;input
	LEA	DX, STRN
	MOV	AH, 0AH
	INT	21H

	;将输入的两个字符分别存入BL,BH
	LEA		SI, BUF
	MOV		BL, [SI]
	MOV		BH, [SI+1]

	;调用子程序判断BL中是否是数字,不是则FLAG=0
	CALL	ISNUM
	;根据FLAG=0来判断输入是否正确。不正确,则跳转到 ER
	MOV 	AL, FLAG
	CMP 	AL, 0
	JE		ER

	;调用子程序判断BH中是否是字母,不是则FLAG=0
	CALL	ISLET
	;根据FLAG=0来判断输入是否正确。不正确,则跳转到 ER
	MOV 	AL, FLAG
	CMP 	AL, 0
	JE		ER

	;没有发生错误则跳到RIG
	JMP		RIG

ER:
	;输出'ERROR'并换行,跳转回输入语句实现循环输入
	LEA	DX, WRN
	MOV	AH, 09H
	INT	21H
	JMP	INP

RIG:
	;输出 'right'
	LEA	DX, SUCC
	MOV	AH, 09H
	INT	21H

DONE:
	MOV AH, 4CH
	INT 21H


;无法在子程序中跳转到主程序的标号,标号仅在子程序内部有效!
ISNUM	PROC	NEAR
	;判断BL是否属于'0'~'9'
	CMP	BL, 30H
	JB	OT1
	CMP	BL, 39H
	JA	OT1
	JMP	RE1
OT1:
	MOV FLAG, 0
RE1:
	RET
ISNUM	ENDP


ISLET	PROC	NEAR
	;判断BH是否为字母
	;A-Z
	CMP	BH, 41H
	JB	OT2
	CMP	BH, 5AH
	JA	LOWER
	JMP	RE2
	;a-z
LOWER:
	CMP	BH, 61H
	JB	OT2
	CMP	BH, 7AH
	JA	OT2
	JMP	RE2

OT2:
	MOV FLAG, 0

RE2:
	RET
ISLET	ENDP

CODE	ENDS
	END	START

.486
DATA    SEGMENT USE16
DIGIT   DB  0, 0AH,'$'
LETTER  DB  0, 0AH,'$'
OTHER   DB  0, 0AH,'$'
STRN    DB  50
LEN     DB  0
BUF     DB  50 DUP(0)
AC_TAB  DB  '0123456789ABCDEF'
OUT1    DB  0AH,'digit:','$'
OUT2    DB  'letter:','$'
OUT3    DB  'other:','$'
DATA    ENDS

CODE    SEGMENT USE16
    ASSUME  DS:DATA, CS:CODE

START:
    ;装载数据段
    MOV AX, DATA
    MOV DS, AX

    ;输入字符串
    LEA DX, STRN
    MOV AH, 0AH
    INT 21H


    LEA     SI, BUF
    MOV     CL, LEN
    MOV     CH, 0
    ;遍历字符串
LP:
    MOV     BL, [SI]
    ;对每个字符调用子程序
    CALL    COUNT
    INC     SI
    LOOP    LP

RESULT:
    ;使用XLAT查询结果数字的ASCII码,将结果覆盖原来的数字
    LEA BX, AC_TAB
    MOV AL, DIGIT
    XLAT
    MOV DIGIT, AL
    ;先显示说明语句
    LEA DX, OUT1
    MOV AH, 09H
    INT 21H
    ;再显示结果数字
    LEA DX, DIGIT
    MOV AH, 09H
    INT 21H

    ;同上
    MOV AL, LETTER
    XLAT
    MOV LETTER, AL
    LEA DX, OUT2
    MOV AH, 09H
    INT 21H
    LEA DX, LETTER
    MOV AH, 09H
    INT 21H

    MOV AL, OTHER
    XLAT
    MOV OTHER, AL
    LEA DX, OUT3
    MOV AH, 09H
    INT 21H
    LEA DX, OTHER
    MOV AH, 09H
    INT 21H

DONE:
    MOV AH, 4CH
    INT 21H

COUNT   PROC    NEAR
NUM:
    CMP BL, 30H
    JB  OTH
    CMP BL, 39H
    JA  UPPER
    INC DIGIT
    JMP RE
UPPER:
    CMP BL, 41H
    JB  OTH
    CMP BL,5AH
    JA  LOWER
    INC LETTER
    JMP RE
LOWER:
    CMP BL, 61H
    JB  OTH
    CMP BL, 7AH
    JA  OTH
    INC LETTER
    JMP RE
OTH:
    INC OTHER
RE:
    RET
COUNT   ENDP

CODE    ENDS
    END     START

8254
.486
CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG 1000H
BEG:
    JMP START
    ;在此定义数据变量
    ;
START:
    ;写控制字
    MOV DX, 30CH
    MOV AL, 00010110B ;通道0 只读写低字节 方式3 二进制方式
    OUT DX, AL

    ;写计数初值
    MOV DX, 300H
    MOV AL, 47D ;1KHZ闪烁
    ;MOV AL, 470D ;100HZ
    OUT DX, AL

WT:
    JMP WT
CODE    ENDS
    END BEG
.486
CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG 1000H
BEG:
    JMP START

START:
    ;写控制字
    MOV DX, 30CH
    MOV AL, 01010110B ;通道1 只读写低字节 方式3 二进制方式
    OUT DX, AL
    ;写通道1的计数初值
    MOV DX, 304H
    MOV AX, 1860D ;20ms * 93KHZ
    OUT DX, AL
    MOV AL, AH
    OUT DX, AL 

    ;写控制字
    MOV DX, 30CH
    MOV AL, 00010110B ;通道0 只读写低字节 方式3 二进制方式
    OUT DX, AL
    ;写通道0的计数初值
    MOV DX, 300H
    MOV AL, 50D ;50次
    OUT DX, AL

WT:
    JMP WT
CODE    ENDS
    END BEG
.486
CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG 1000H
BEG:
    JMP START

START:
    MOV DX, 30CH
    MOV AL, 10110010B
    OUT DX, AL
    
    MOV DX, 308H
    MOV AX,60000D
    OUT DX, AL
    MOV AL, AH
    OUT DX, AL

WT:
    JMP WT
CODE    ENDS
    END BEG
8255
.486
PORTA   EQU  300H
PORTB   EQU  304H
PORTC   EQU  308H
CTRL_8255   EQU  30CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG 1000H
START:
    MOV DX, CTRL_8255
    MOV AL, 10000000B ;C口高低位输出
    OUT DX, AL

    MOV AL, 10101010B
LP:
    MOV DX, PORTC
    OUT DX, AL
    ROL AL, 1 ;循环左移实现亮灭交替
    CALL    DLY_L
    JMP LP
WT: JMP WT

    DLY_L PROC
        PUSH    ECX
        MOV ECX, 2FFFFH
    DLYS_AGN:
        NOP
        NOP
        LOOP    DLYS_AGN
        POP ECX
        RET
    DLY_L ENDP

CODE    ENDS
    END START

.486
PORTA   EQU  300H
PORTB   EQU  304H
PORTC   EQU  308H
CTRL_8255   EQU  30CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG 1000H
START:
    MOV DX, CTRL_8255
    MOV AL, 10000010B ;C口方式0输出  B口方式0输入
    OUT DX, AL
LP:
    MOV DX, PORTB
    IN  AL, DX ;读取开关状态
    MOV BL, AL
    MOV BH, 0 ;BH记录BL中1的个数

    TEST    BL, 00001000B
    JNZ WT ;K4为1时,程序结束

CNT:
    AND BL, BL
    JZ  PNT ;全为0则表示全部移位完成,跳到输出
    SHL BL,1
    JC  YS ;移出来的是1则计数+1,否则直接进行下一次位移
    JMP CNT
YS:
    INC BH
    JMP CNT
PNT:
    MOV AL, BH
    NOT AL
    MOV DX, PORTC
    OUT DX, AL
    JMP LP

WT: JMP WT
CODE    ENDS
    END START

.486
PORTA   EQU  300H
PORTB   EQU  304H
PORTC   EQU  308H
CTRL   EQU  30CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG 1000H
BEG:
	JMP START
    FLAG DB ?
START:
    ;写控制字
    MOV DX, CTRL
    MOV AL, 10000010B ;C口输出  B口方式0输入
    OUT DX, AL

CASE:
    ;开关状态存在BL中,根据读取到的开关状态跳转到不同的分支
    MOV DX, PORTB
    IN  AL, DX
    MOV BL, AL
    CMP BL, 00000001B
    JE MD_ONE
    CMP BL, 00000011B
    JE MD_TWO
    CMP BL, 00000111B
    JE MD_THREE
    CMP BL, 00001111B
    JE MD_FOUR
    CMP BL, 00011111B
    JE MD_FIVE
    CMP BL, 00111111B
    JE MD_SIX
    CMP BL, 01111111B
    JE MD_SEVEN
    CMP BL, 11111111B
    JE DN
    
    JMP CASE

MD_ONE:
    ;灯亮情况和开关情况电平相反
    MOV AL, BL
    NOT AL
AGN_ONE:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 1
    CALL    CHANGED ;如果灯亮循环过程中开关状态变化,则重新判断对应的分支

    CMP FLAG, 1
    JE  CASE
    JMP AGN_ONE

MD_TWO:
    MOV AL, BL
    NOT AL
AGN_TWO:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 2
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE
    JMP AGN_TWO

MD_THREE:
    MOV AL, BL
    NOT AL
AGN_THREE:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 3
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE
    JMP AGN_THREE

MD_FOUR:
    MOV AL, BL
    NOT AL
AGN_FOUR:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 4
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE
    JMP AGN_FOUR

MD_FIVE:
    MOV AL, BL
    NOT AL

AGN_FIVE:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 5
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE
    JMP AGN_FIVE

MD_SIX:
    MOV AL, BL
    NOT AL
AGN_SIX:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 6
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE
    JMP AGN_SIX

MD_SEVEN:
    MOV AL, BL
    NOT AL
AGN_SEVEN:
    MOV DX, PORTC
    CALL	DLY_L
    CALL	DLY_L
    OUT DX, AL
    ROL AL, 7
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE
    JMP AGN_SEVEN
    
DN:
    MOV DX, PORTC
    MOV AL, 0FFH
    OUT DX, AL
WT:
    JMP WT

CHANGED PROC
    PUSH AX
    MOV FLAG, 0
    MOV DX, PORTB
    IN  AL, DX
    CMP BL, AL
    JE  DONE
    MOV FLAG, 1
DONE:
    POP AX
    RET
CHANGED ENDP

DLY_L   PROC
    PUSH    ECX
    MOV     CX, 0FFFFH
DLYS_AGN:
    NOP
    NOP
    LOOP    DLYS_AGN
    POP     ECX
    RET
DLY_L   ENDP

CODE    ENDS
    END BEG


LED
.486
PORTA EQU 320H
PORTB EQU 324H
PORTC EQU 328H
CTRL  EQU 32CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG     1000H
BEG:
    JMP START
    ;
START:
    MOV DX, CTRL
    MOV AL, 10000000B; A接段选,B接位选
    OUT DX, AL

    ;送段选
    MOV AL, 7FH
    MOV DX, PORTA
    OUT DX ,AL

SET:
    ;送位选
    MOV AH, 00100000B
LP:
    MOV AL, AH
    MOV DX, PORTB
    OUT DX, AL
    ;长延时
    CALL    DLY_L
    ;位选右移
    SHR AH, 1
    ;若1被移出则从头开始
    JC  SET
    JMP LP

WT: JMP WT

DLY_L   PROC
    PUSH    CX
    MOV     CX, 0FFH
DLYS_AGN:
    NOP
    NOP
    LOOP    DLYS_AGN
    POP     CX
    RET
DLY_L   ENDP

CODE    ENDS
    END BEG

.486
PORTA EQU 320H
PORTB EQU 324H
PORTC EQU 328H
CTRL  EQU 32CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG     1000H
BEG:
    JMP START
    MESS    DB  06H, 5BH, 4FH, 0E6H, 6DH, 7DH;字形码
START:
    LEA SI, MESS
    ;位选预置数
    MOV AH, 00100000B
    ;控制字
    MOV AL, 10000000B; A接段选,B接位选
    MOV DX, CTRL
    OUT DX, AL
LP:
    ;先送段选
    MOV AL, [SI]
    MOV DX, PORTA
    OUT DX, AL
    ;再送位选
    MOV AL, AH
    MOV DX, PORTB
    OUT DX ,AL
    ;延时
    CALL DLY_L
    ;位选右移
    SHR AH, 1
    JC  START
    INC SI
    JMP LP
WT:
    JMP WT

DLY_L   PROC
    PUSH    CX
    MOV     CX, 0FFH
DLYS_AGN:
    NOP
    NOP
    LOOP    DLYS_AGN
    POP     CX
    RET
DLY_L   ENDP
CODE    ENDS
    END BEG

.486
PORTA EQU 320H
PORTB EQU 324H
PORTC EQU 328H
CTRL  EQU 32CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG     1000H
BEG:
    JMP START
    MESS    DB  3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH;字形码
    DISP    DB  2,0,1,9,3,8,1,8
START:
    ;控制字
    MOV AL, 10000000B; A接段选,B接位选
    MOV DX, CTRL
    OUT DX, AL
DIS:
    LEA SI, DISP
    LEA BX, MESS
    ;位选预置数
    MOV AH, 10000000B
LP:
    ;送段选
    MOV AL, [SI]
    XLAT
    MOV DX, PORTA
    OUT DX, AL
    ;送位选
    MOV AL, AH
    MOV DX, PORTB
    OUT DX, AL

    SHR AH, 1
    JC DIS
    INC SI
    JMP LP

WT: JMP WT

DLY_L   PROC
    PUSH    CX
    MOV     CX, 0FFH
DLYS_AGN:
    NOP
    NOP
    LOOP    DLYS_AGN
    POP     CX
    RET
DLY_L   ENDP
CODE    ENDS
    END BEG

.486
PORTA EQU 320H
PORTB EQU 324H
PORTC EQU 328H
CTRL  EQU 32CH

CODE    SEGMENT USE16
    ASSUME  CS:CODE
    ORG     1000H
BEG:
    JMP START
    MESS    DB  3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH;字形码
    DISP    DB  2,0,1,9,3,8,1,8
    FLAG    DB  ?
START:
    ;控制字
    MOV AL, 10001001B; A接段选,B接位选,C读开关
    MOV DX, CTRL
    OUT DX, AL

CASE:
    ;读开关
    MOV DX, PORTC
    IN  AL, DX
    MOV BL, AL
    MOV CH, AL;CH存开关状态
    TEST BL, 10000000B
    JNZ  C3
    CMP BL, 00000001B
    JE  C1
    CMP BL, 00000010B
    JE  C2
    JMP C4

C1:
    ;送段选 '8'
    MOV AL, 7FH
    MOV DX, PORTA
    OUT DX, AL
    ;送位选
    MOV AH, 10000000B
LP1:
    MOV AL, AH
    MOV DX, PORTB
    OUT DX, AL
    CALL    DLY_L
    ;循环右移1位
    SHR AH, 1
    JC  C1   
    ;判断开关状态是否改变,改变则重新判断分支,没改变则继续循环
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE

    JMP LP1

C2:
    LEA SI, DISP
    LEA BX, MESS
    MOV AH, 10000000B
LP2:
    ;取字形码
    MOV AL, [SI]
    XLAT
    ;送段选
    MOV DX, PORTA
    OUT DX, AL
    ;送位选
    MOV AL, AH
    MOV DX, PORTB
    OUT DX, AL

    SHR AH, 1
    JC  C2
    ;判断开关状态是否改变,改变则重新判断分支,没改变则继续循环
    CALL    CHANGED
    CMP FLAG, 1
    JE  CASE

    INC SI
    JMP LP2

C3:
    ;灯全灭,结束
    MOV AL, 00H
    MOV DX, PORTB
    OUT DX, AL
    JMP WT

C4:
    ;送段选
    MOV AL, MESS
    MOV DX, PORTA
    OUT DX, AL
    ;送位选
    MOV AL, 0FFH
    MOV DX, PORTB
    OUT DX, AL
    JMP CASE


WT:
    JMP WT

    DLY_L   PROC
        PUSH    ECX
        MOV     ECX, 2FFFFH
    DLYS_AGN:
        NOP
        NOP
        LOOPD    DLYS_AGN
        POP     ECX
        RET
    DLY_L   ENDP

    CHANGED PROC ;按键没变则FLAG=0
        PUSH CX
        MOV FLAG, 0
        MOV DX, PORTC
        IN  AL, DX
        CMP CH, AL
        JE  DONE
        MOV FLAG, 1
    DONE:
        POP CX
        RET
    CHANGED ENDP
CODE    ENDS
    END BEG

键盘
.486
PORTA   EQU  300H
PORTB   EQU  304H
PORTC   EQU  308H
CTRL_8255   EQU  30CH
CHANEL0 EQU    320H
CHANEL1 EQU    324H
CHANEL2 EQU    328H
CTRL_8254   EQU 32CH
KA  EQU     0BBH
KB  EQU     0B7H
CODE    SEGMENT USE16
    ASSUME CS:CODE
    ORG 1000H
START:
    ;初始化8255
    MOV DX, CTRL_8255
    MOV AL, 10000010B ;A口输出控制8254,B口输入读键盘行,C口输出送键盘列信号
    OUT DX, AL
    ;初始化8254
    MOV DX, CTRL_8254
    MOV AL, 00110110B ;通道0,高低字节,方式三,二进制
    OUT DX, AL
    MOV AX, 47000; 1s*47000Hz
    MOV DX, CHANEL0
    OUT DX, AL
    MOV AL, AL
    OUT DX, AL
    ;
    KSCAN:
        MOV BL, 0BH ;A,B的列特征值
        MOV AL, BL
        MOV DX, PORTC;送列读行
        OUT DX, AL
        MOV DX, PORTB
        IN  AL, DX
        AND AL, 0FH
        CMP AL, 0FH
        JNZ FNDKEY ;有键按下则跳转
        JMP KSCAN  ;无键按下则重新读取
    FNDKEY:
        SHL BL, 4
        OR  BL, AL;列信号和行信号组成键特征值
        CALL    DLY_L
    KEYUP:  ;判断按键是否释放
        MOV AL, 0
        MOV DX, PORTC
        OUT DX, AL
        MOV DX, PORTB
        IN  AL, DX
        AND AL, 0FH
        CMP AL, 0FH
        JNZ KEYUP   ;未释放则继续等待
        CMP BL, KA;如果按下的是'A'
        JE  CA
        CMP BL, KB;'B'
        JE  CB
        JMP KSCAN

    CA:
        ;输出高电平到8254的GATE
        MOV AL, 0FFH
        MOV DX, PORTA
        OUT DX, AL
        JMP KSCAN

    CB:
        ;输出低电平到8254的GATE
        MOV AL, 00H
        MOV DX, PORTA
        OUT DX, AL
        JMP WT
    WT:
        JMP WT

    DLY_L PROC
        PUSH    ECX
        MOV ECX, 2FFFFH
    DLYS_AGN:
        NOP
        NOP
        LOOP    DLYS_AGN
        POP ECX
        RET
    DLY_L ENDP

CODE    ENDS
    END START

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值