📄 led.asm
字号:
;386以上微机适用
;纯dos下才能使用
;tasm4.1或以上编译
;*********************;
;* LED *;
;*********************;
io_plx_device_id equ 05406h ;TPC卡设备ID
io_plx_vendor_id equ 010b5h ;TPC卡厂商ID
IO_PLX_SUB_ID EQU 0905410B5H ;TPC卡子设备及厂商ID
TIM_CTL EQU 203H-200H ;8253端口地址
TIMER0 EQU 200H-200H
TIMER1 EQU 201H-200H
MODE03 EQU 36H ;8253端口数据
MODE12 EQU 74H
INTA00 EQU 20H
INTA01 EQU 21H
PORTSEG EQU 211H-200H ;数码管端口地址
PORTBIT EQU 210H-200H
data segment
csreg dw ?
ipreg dw ? ;旧中断向量保存空间
io_9054base_address db 4 DUP(0) ;TPC卡PCI接口芯片I/O基地址暂存空间
io_base_address db 4 DUP(0) ;TPC卡I/O基地址暂存空间
interrupt_line db 2 DUP(0) ;TPC卡中断号暂存空间
pcicardnotfind db 0dh,0ah,'TPC pci card not find or address/interrupt error !!!',0dh,0ah,'$'
io9054baseaddress db 0dh,0ah,'TPC pci card 9054 Chip I/O Base Address : ','$'
iobaseaddress db 0dh,0ah,'TPC pci card I/O Base Address : ','$'
intnumber db 0dh,0ah,'TPC pci card Interrupt Line : ','$'
enter_return db 0dh,0ah,'$'
MESS DB '8253A TIMER0 IN MODE3! COUNT=0200H',0AH,0DH
DB '8253A TIMER1 IN MODE2! COUNT=0aH',0AH,0DH,'$'
irq_vect db 08h,09h,0ah,0bh,0ch,0dh,0eh,0fh,70h,71h,72h,73h,74h,75h,76h,77h
;新的中断向量,中断0-7的向量为:08h-0fh,中断8-15的向量为:70h-77h
irq_mask_0_7_table db 011111110b,011111101b,011111011b,011110111b
db 011101111b,011011111b,010111111b,001111111b
db 011111011b,011111011b,011111011b,011111011b
db 011111011b,011111011b,011111011b,011111011b
;新的中断掩码,中断0-7时从低至高相应位为零,中断8-15时第2位为零
irq_mask_8_15_table db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh
db 011111110b,011111101b,011111011b,011110111b
db 011101111b,011011111b,010111111b,001111111b
;新的中断掩码,中断0-7时全一,中断8-15时从低至高相应位为零
MIN1 DB 0
MIN2 DB 0
GAP1 DB 10
GAP2 DB 10
SEC1 DB 0
SEC2 DB 0
INTMASK DB ?
COUNT DB 0
LED DB 3FH,06,5BH,4FH,66H,6DH,7DH,07,7FH,6FH,40H
MES DB 'DISPLAY THE LEDS,PRESS ANY KEY TO EXIT!'
DB 0AH,0DH,'$'
data ends
stacks segment
db 100 dup (?)
STA DW 512 DUP (?)
TOP EQU LENGTH STA
stacks ends
code segment
assume cs:code,ds:data,ss:stacks,es:data
start:
;Enable Local Interrupt Input
.386
cli
mov ax,data
mov ds,ax
mov es,ax
mov ax,stacks
mov ss,ax
call findtpc ;查找TPC卡资源并显示
MOV DX,word ptr io_base_address ;初始化8253
add dx,TIM_CTL
MOV AL,MODE03
OUT DX,AL
MOV DX,word ptr io_base_address
add dx,TIMER0
MOV AL,00h
OUT DX,AL
MOV AL,02H
OUT DX,AL
MOV DX,word ptr io_base_address
add dx,TIM_CTL
MOV AL,MODE12
OUT DX,AL
MOV DX,word ptr io_base_address
add dx,TIMER1
MOV AL,0aH
OUT DX,AL
MOV AL,00
OUT DX,AL
MOV DX,OFFSET MESS
MOV AH,09
INT 21H
MOV DX,OFFSET MES ;显示提示
MOV AH,09
INT 21H
mov dx,word ptr io_9054base_address
add dx,68h ;设置 tpc 卡中9054芯片io口,使能中断
in ax,dx
or ax,0900h
out dx,ax
mov bx,word ptr interrupt_line ;保存原中断向量
mov al,byte ptr [irq_vect+bx]
mov ah,35h
int 21h
mov ax,es
mov csreg,ax
mov ipreg,bx
mov bx,word ptr interrupt_line ;设置新中断向量
mov al,byte ptr [irq_vect+bx]
mov cx,cs
mov ds,cx
mov dx,offset int_proc
mov ah,25h
int 21h
mov ax,data
mov ds,ax
mov es,ax
in al, 21h ;设置中断掩码
mov bx,word ptr interrupt_line
mov ah,byte ptr [irq_mask_0_7_table+bx]
and al,ah
out 21h, al
in al, 0a1h
mov bx,word ptr interrupt_line
mov ah,byte ptr [irq_mask_8_15_table+bx]
and al,ah
out 0a1h, al
sti ;开中断
loop1:
mov ah,1
int 16h
jnz exit ;按任意键退出
jmp loop1
exit: cli
mov bx,word ptr interrupt_line ;恢复中断掩码
mov ah,byte ptr [irq_mask_0_7_table+bx]
not ah
in al, 21h
or al, ah
out 21h, al
mov bx,word ptr interrupt_line
mov ah,byte ptr [irq_mask_8_15_table+bx]
not ah
in al, 0a1h
or al, ah
out 0a1h, al
mov bx,word ptr interrupt_line ;恢复原中断向量
mov al,byte ptr [irq_vect+bx]
mov dx,ipreg
mov cx,csreg
mov ds,cx
mov ah,25h
int 21h
mov ax,data ;设置 tpc 卡中9054芯片io口,关闭中断
mov ds,ax
mov dx,word ptr io_9054base_address
add dx,68h
in ax,dx
and ax,0f7ffh
out dx,ax
mov ax,4c00h
int 21h ;退出
int_proc proc far
cli
push ax
PUSH CX
push dx
PUSH DI
push ds
MOV AX,DATA
MOV DS,AX
MOV DI,OFFSET MIN1
MOV CL,01
DIS1: MOV AL,[DI]
MOV BX,OFFSET LED
XLAT
MOV DX,word ptr io_base_address
add dx,PORTSEG
OUT DX,AL
MOV AL,CL
MOV DX,word ptr io_base_address
add dx,PORTBIT
OUT DX,AL
PUSH CX
MOV CX,8000H ;显示时间延迟
DELAY: LOOP DELAY
POP CX
CMP CL,20H
JZ CHG
INC DI
SHL CL,1
MOV AL,00
OUT DX,AL
JMP DIS1
CHG: INC COUNT
CMP COUNT,50
JL QUIT
MOV COUNT,0
INC SEC2
CMP SEC2,10
JL QUIT
MOV SEC2,0
INC SEC1
CMP SEC1,6
JL QUIT
MOV SEC1,0
INC MIN2
CMP MIN2,10
JL QUIT
MOV MIN2,0
INC MIN1
CMP MIN1,6
JL QUIT
MOV MIN1,0
QUIT:
MOV DX,word ptr io_base_address
add dx,PORTBIT
MOV AL,00
OUT DX,AL
mov al,20h ;Send EOI
out 0a0h,al
out 20h,al
mov cx,0ffffh
loopx:
nop
loop loopx ;延时
pop ds
POP DI
pop dx
POP CX
pop ax
sti
iret
int_proc endp
findtpc proc near ;查找TPC卡资源并显示
pushad
pushfd
MOV AX,0B101H
INT 1AH
JC findtpc_notfind ;检查PCI BIOS是否存在
MOV AX,0B102H
MOV CX,io_plx_device_id
MOV DX,io_plx_vendor_id
MOV SI,0
INT 1AH
JC findtpc_notfind ;检查TPC卡是否安装,设备号、厂商号
MOV AX,0B10AH
MOV DI,02CH
INT 1AH
JC findtpc_notfind
CMP ECX,IO_PLX_SUB_ID
JNZ findtpc_notfind ;检查TPC卡是否安装,子设备号、厂商号
MOV AX,0B10AH
MOV DI,14H
INT 1AH
JC findtpc_notfind ;读TPC卡9054芯片I/O基址信息
mov dword ptr io_9054base_address,ecx
and ecx,1
jz findtpc_notfind ;检查是否为i/o基址信息
mov ecx,dword ptr io_9054base_address
and ecx,0fffffffeh
mov dword ptr io_9054base_address,ecx ;去除i/o指示位并保存
MOV AX,0B10AH
MOV DI,18H
INT 1AH
JC findtpc_notfind ;读TPC卡I/O基址信息
mov dword ptr io_base_address,ecx
and ecx,1
jz findtpc_notfind ;检查是否为i/o基址信息
mov ecx,dword ptr io_base_address
and ecx,0fffffffeh
mov dword ptr io_base_address,ecx ;去除i/o指示位并保存
MOV AX,0B10AH
MOV DI,3CH
INT 1AH
JC findtpc_notfind ;读TPC卡中断信息
and cx,0ffh
mov word ptr interrupt_line,cx ;去除interrupt其它指示位并保存
mov dx,offset io9054baseaddress ;显示i/o提示信息
mov ah,09h
int 21h
mov ax,word ptr io_9054base_address
call dispword ;显示i/o基地址
mov dx,offset iobaseaddress ;显示i/o提示信息
mov ah,09h
int 21h
mov ax,word ptr io_base_address
call dispword ;显示i/o基地址
mov dx,offset intnumber ;显示interrupt提示信息
mov ah,09h
int 21h
mov ax,word ptr interrupt_line
call dispword ;显示中断号
mov dx,offset enter_return ;加回车符,换行符
mov ah,09h
int 21h
popfd
popad
ret
findtpc_notfind:
mov dx,offset pcicardnotfind ;显示未找到tpc卡提示信息
mov ah,09h
int 21h
mov ax,4c00h
int 21h ;退出
findtpc endp
dispword proc near ;显示子程序
push dx
push cx
push bx
mov cx,4
mov bx,16
dispword_loop1:
push ax
push cx
sub bx,4
mov cx,bx
shr ax,cl
and al,0fh ;首先取低四位
mov dl,al
cmp dl,9 ;判断是否<=9
jle dispword_num ;若是则为'0'-'9',ASCII码加30H
add dl,7 ;否则为'A'-'F',ASCII码加37H
dispword_num:
add dl,30h
mov ah,02h ;显示
int 21h
pop cx
pop ax
loop dispword_loop1
pop bx
pop cx
pop dx
ret ;子程序返回
dispword endp
code ends
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -