Sky's blog

微机实验代码

Word count: 1,952 / Reading time: 10 min
2017/06/18 Share

实验一

微机实验(基于8086的阶乘)(仅限于8以内)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
                      ;--------------------------------------------
DATA SEGMENT
INPUT_TIPS DB 10, 13, "Please input a number(0~8): $" ;为什么只能0~8 因为到9以后,阶乘的值的16进制已经超过4位。。。这里的程序逻辑不中了~
OUTPUT_TIPS DB 10, 13, "The number's factorial is: $"
Error_0_TIPS DB 10, 13, "The number is < 0,error! Please input the number(0~8): $"
Error_8_TIPS DB 10, 13, "The number is > 8,error! Please input the number(0~8): $"
DATA ENDS
;--------------------------------------------
STACK SEGMENT
;INPUT STACK SEGMENT CODE HERE
db 256 dup(0)
STACK ENDS
;--------------------------------------------
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
START:
MOV AX, DATA
MOV DS, AX
;----------------------------------
MOV DX, OFFSET INPUT_TIPS
MOV AH, 9 ;显示字符串.
INT 21H ;int 21中断调用DOS
MOV AH, 1 ;输入到 AL
INT 21H
CMP AL, '0'
JB ERROR_0 ;小于0 就退出
CMP AL, '8'
JA ERROR_8 ;大于8就退出
SUB AL, '0' ;sub结果放到 AL中
MOV AH, 0 ;令AH等于0,则AX等于0
CMP AX, 0 ;是 0 吗?
JNZ CMP_1 ;不是0就看看是不是1
MOV AX, 1 ;是 0 就去显示 1
JMP DISP
CMP_1:
CMP AX, 1 ;是 1 吗?
JZ DISP ;是 1 就去显示 1
MOV CX, AX ;非 0 非 1,就是其它数字,那么
CALL FACTOR ;调用递归函数去计算阶乘
;----------------------------------
DISP: ;显示函数
PUSH AX
MOV DX, OFFSET OUTPUT_TIPS
MOV AH, 9 ;显示字符串.
INT 21H
POP AX
MOV BX, 10
MOV CX, 0
L1: ;16进制转10进制
MOV DX, 0
DIV BX ;被除数A 默认存放在AX中(16位以内) 或 AX和DX中(32位,DX存放高16位,AX存放低16位)
;结果: 如果除数B是8位, 那么除法的结果AL保存商,AH保存余数,
; 如果除数B是16位,那么除法的结果 AX保存商,DX保存余数。
PUSH DX ;余数入栈
INC CX ;CX加一
AND AX, AX
JNZ L1
L2: ;一位一位出栈输出显示
POP DX
ADD DL, 48 ;数字转ASCII码
MOV AH, 2 ;显示到控制台
INT 21H
LOOP L2
;----------------------------------
EXIT: ;退出函数
MOV AH, 4CH
INT 21H
;==================================
ERROR_0:
MOV DX, OFFSET Error_0_TIPS
MOV AH, 9 ;显示字符串.
INT 21H
JMP EXIT

ERROR_8:
MOV DX, OFFSET Error_8_TIPS
MOV AH, 9 ;显示字符串.
INT 21H
JMP EXIT
;==================================
FACTOR PROC NEAR ;阶乘.
DEC CX ;CX=2~8
CMP CX, 1 ;=1 ?
JE FACTOR_E ;为1就退出
PUSH CX ;非1压栈保存
CALL FACTOR ;递归调用,把CX一次次的减一
POP CX ;弹出一个个递减的数值
MUL CX ;乘到AX
FACTOR_E:
RET ;AX=(2~8)!
FACTOR ENDP ;简洁明了,无与伦比
;==================================
CODE ENDS
END START

实验二

微机实验(利用8253和8255的跑马灯)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
code segment
assume cs:code
start:mov dx,28bh
mov al,10010000b
out dx,al
mov al,01h
mov bl,al

MOV AL,00110101B
MOV DX,283H
OUT DX,AL
MOV DX,280H
MOV AL,00H
OUT DX,AL
MOV DX,280H
MOV AL,50H
OUT DX,AL

MOV AL,01110101B
MOV DX,283H
OUT DX,AL
MOV AL,00H
MOV DX,281H
OUT DX,AL
MOV AL,08H
MOV DX,281H
OUT DX,AL

run: mov dx,288h
in al,dx
test al,00000001b
jnz run

mov al,bl
mov dx,289h
out dx,al
rol al,1
mov bl,al
yu: mov dx,288h
in al,dx
test al,00000001b
jz yu

jmp run


code ends
end start

实验三

微机实验(带回显的键盘)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
;======================= 端口地址
PORT_A EQU 280H ;A口地址
PORT_B EQU 281H ;B口地址
PORT_C EQU 282H
PORT_CTL EQU 283H ;控制口地址
;=======================

;======================= 键盘扫描码表
DATA SEGMENT
TABLE_A DB 77H,7BH,7DH,7EH,0B7H,0BBH,0BDH,0BEH
;=========0===1===2===3===4=====5====6===7=========
DB 0D7H,0DBH,0DDH,0DEH,0E7H,0EBH,0EDH,0EEH
;=========8====9====10===11===12===13===14===15====
TABLE_C DB 3FH,06H,5BH,4FH,66H,6DH,7DH,0FH
DB 7FH,67H,77H,7CH,39H,5EH,79H,71H
DATA ENDS

;======================== 堆栈段
STACK SEGMENT STACK
DW 50 DUP(0)
TOP_STACK LABEL WORD
STACK ENDS
;========================

;======================== 代码段
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
START:
MOV AX,STACK
MOV SS,AX ;给堆栈段赋地址
LEA SP,TOP_STACK ;sp指向堆栈栈顶
MOV AX,DATA
MOV DS,AX ;给数据段赋地址

;======================== 初始化,方式0,A口输出,B,C口输入
MOV DX,PORT_CTL ;指向控制口
MOV AL,10001011B ;方式0,A口输出,C口高位输入,B口方式0,B口输入,C口低四位输入
OUT DX,AL ;写入控制字

;======================== 向所有行送0
MOV DX,PORT_A ;指向A口
MOV AL,00H
OUT DX,AL ;向A口各位输出0

;======================== 读列,查看是否所有键均松开
MOV DX,PORT_B ;指向B口
WAIT_OPEN:
IN AL,DX ;键盘状态读入B口
AND AL,0FH ;保留低四位(只查看低4位,列值)
CMP AL,0FH ;低四位是否均为1?(各键均松开)
JNE WAIT_OPEN ;低四位不均为1,则继续循环这个函数,直到低四位均为1

;======================== 各键均已松开,再查看列是否有0,即是否有键按下
WAIT_PRES:
IN AL,DX
AND AL,0FH
CMP AL,0FH
JE WAIT_PRES ;低四位均为1时(没有键按下),循环这个函数,直到有键按下

;======================== 有键按下,延时20ms,防止抖动
MOV CX,16EAH
DELAY:
LOOP DELAY ;循环16EAH次(按照指令时间,这么多次,大概是20ms)

;======================== 再查列,看键是否被压着(如果还被压着,则不是抖动问题,而是真的按下)
IN AL,DX
AND AL,0FH
CMP AL,0FH
JE WAIT_PRES ;如果没有键按下,则说明之前是抖动,就跳回到等待到按键函数

;======================== 若键依旧被压着,就确定是哪一个键被压下
MOV AL,0FEH ;AL=1111 1110 B
MOV CL,AL ;CL=1111 1110 B
NEXT_ROW:
MOV DX,PORT_A
OUT DX,AL ;先让第一行全部置0(低电平)
MOV DX,PORT_B
IN AL,DX ;读B口状态
AND AL,0FH ;取低4位(列值)
CMP AL,0FH ;查看低4位(列值)看是否有键按下(是否均为1)
JNE ENCODE ;否,说明有键按下,则转去编码函数
ROL CL,01 ;左移一次,让下一行都变为0
MOV AL,CL
JMP NEXT_ROW ;再次循环函数,查看第二行

;========================= 找到一列为低电平,对压键的行列值编码
ENCODE:
MOV BX,000FH ;建立地址指针,先指向F键(15)对应的地址
IN AL,DX ;读B口状态(行列号)
NEXT_TRY:
CMP AL,TABLE_A[BX] ;读入的行列值与表中查的相等吗?
JE DONE ;相等,转出到完成函数
DEC BX ;不相等,则转到下一个地址(往小的慢慢转)
JNS NEXT_TRY ;BX还大于0时,继续跳回到NEXT_TRY函数
MOV AH,01 ;一直查到地址为负数都没查到,置出错码01→AH
JMP EXIT ;直接跳到退出程序
DONE:
MOV AL,BL ;BL中存有键的16进制代码(按下的键是几)
MOV BX,OFFSET TABLE_C
XLAT
MOV DX,PORT_C
OUT DX,AL
MOV CX,0FFH
JMP DELAY2
DELAY2:LOOP DELAY2
JMP START
EXIT:
HLT
CODE ENDS
END

实验四

微机实验(基于0832的旋转电机)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CODE SEGMENT
ASSUME CS:CODE
START:
MOV AL,0FFH
AGAIN:
INC AL
MOV DX,280H
OUT DX,AL
MOV BX,80H
DELAY:
MOV CX,16EAH
DELAY1:
LOOP DELAY1
DEC BX
JNZ DELAY
JMP AGAIN
CODE ENDS
END

微机实验(基于0809和8255的闪烁灯)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,28BH
MOV AL,10010001B
OUT DX,AL
NEXT: MOV DX,280H
OUT DX,AL
MOV DX,28AH
POLL:
IN AL,DX
TEST AL,01H
JZ POLL
MOV DX,280H
IN AL,DX
MOV DX,289H
OUT DX,AL
JMP NEXT
CODE ENDS
END START
CATALOG
  1. 1. 实验一
    1. 1.1. 微机实验(基于8086的阶乘)(仅限于8以内)
  2. 2. 实验二
    1. 2.1. 微机实验(利用8253和8255的跑马灯)
  3. 3. 实验三
    1. 3.1. 微机实验(带回显的键盘)
  4. 4. 实验四
    1. 4.1. 微机实验(基于0832的旋转电机)
    2. 4.2. 微机实验(基于0809和8255的闪烁灯)