⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dmaw.asm

📁 大学微型计算机接口技术实验源代码,直接就可以运行,包含了C++和asm代码,比较前面.
💻 ASM
字号:
                                                           
;*************************************
;*		Source Code
;*		"DMA Read" 
;*		采用DMA方式读主存数据到软盘
;*		DMAC: 0号8237A
;*		FDC: uPD765
;*************************************                                               

	;8237的模式字:55
	;46H: 单一方式,地址加1,非自动预置,DMA写主存,通道2
	;4aH: 单一方式,地址加1,非自动预置,DMA读主存,通道2
;=====================================================

DMA	EQU	0
;=====================================================
DISP_CH	MACRO	CHAR
	PUSH	BX
	MOV	AL,CHAR		;字符
	MOV	AH,0EH		;显示字符
	MOV	BL,0		;背景色
	INT	10H
	POP	BX
        ENDM
;=====================================================        
SSTACK	SEGMENT	PARA	STACK 	'STACK'
	DB	100	DUP(?)
SSTACK	ENDS
;=====================================================
S0040	SEGMENT	AT	40H		;以下11字节为软盘数据区
	ORG	3EH
DISKDATA	LABEL	BYTE	
SSS		DB	?		;询道状态
MS		DB	?		;马达状态
MC		DB	?		;马达计数
DSS		DB	?		;软区状态
NS		DB	7 DUP(?)	;nec状态
S0040	ENDS
;=====================================================
DDATA           SEGMENT
DPARA		LABEL	BYTE		;软盘参数表,系统BIOS中使用的参数值
                DB      11011111B
		DB	00000010B
		DB	25H
                DB      02H
                DB      3FH
                DB      1BH
		DB	0FFH
                DB      054H
		DB	0F6H
                DB      0FH
                DB      08H
BUF             DB      512 DUP(72)      ;磁盘缓冲区
OLDPARAS	DW	0		;保存系统软盘参数入口地址
OLDPARAO	DW	0
OLDINTS		DW	0		;保存系统软盘中断处理程序入口
OLDINTO		DW	0
EMES		DB	'ERROR!$'
DDATA           ENDS
;=====================================================
CODE	SEGMENT	PARA	PUBLIC	'CODE'
        ASSUME  CS:CODE,ES:DDATA,DS:S0040,SS:SSTACK
START	PROC	FAR
        MOV     AX,DDATA
        MOV     DS,AX
	CLI				;关中断	
	XOR	AX,AX			;设置中断向量
	MOV	ES,AX
        MOV     DI,38H			;4*0EH,0EH号中断为软盘中断
	MOV	AX,ES:[DI]
	MOV	OLDINTO,AX
	MOV	AX,OFFSET DISKINT
	CLD	
	STOSW
	MOV	AX,ES:[DI]
	MOV	OLDINTS,AX
	MOV	AX,SEG	DISKINT
	STOSW

        MOV     DI,78H          	;4*1EH,1EH为软盘参数块
        MOV	AX,ES:[DI]
        MOV	OLDPARAO,AX
	MOV	AX,OFFSET DPARA
	STOSW
	MOV	AX,ES:[DI]
	MOV	OLDPARAS,AX
	MOV	AX,SEG	DPARA
	STOSW

	MOV	AX,S0040
	MOV	DS,AX
        MOV     AX,DDATA		;ES指向系统数据区
	MOV	ES,AX
	MOV	SI,OFFSET DPARA		;SI指向软盘参数区入口
	AND	SSS,07FH		;清中断标志
	STI

	MOV	DH,1			;设置DMA参数
	MOV	BX,OFFSET BUF
	MOV	AX,SEG BUF
	MOV	ES,AX
        MOV     AL,4aH                  ;4aH为8237的模式字
	CALL	DMA_SETUP

	JNC	ST1
	MOV	DSS,09H
	MOV	AX,09H			;返回DOS系统
	CALL	SHWORD
	MOV	AX,4C00H
	INT	21H

ST1:    MOV     AX,DDATA
	MOV	ES,AX
	CLI
	MOV	MC,0FFH			;马达延长计数值设置为最大
        TEST    MS,01H                  ;驱动器1马达是否已经转动
	JNZ	ST2			;已转动转J14
	
	AND	MS,0F0H			;以下为启动处理
        OR      MS,01H
	MOV	AL,00011100B		;选择驱动器1,开马达,允许中断,FDC
	MOV	DX,3F2H
	OUT	DX,AL			;送数字输出寄存器
	
	MOV	SSS,0
	MOV	DSS,0
	
ST2:	STI				;开中断,完成询道操作
        TEST    SSS,01H			;检查1号驱动器是否需要归零道
        JNZ     ST3
        
ST21:	MOV	AH,07H			;执行归零操作
	CALL	NEC_OUTPUT		
	MOV	BX,11H
	JC	ST22
	MOV	AH,0H
	CALL	NEC_OUTPUT
	MOV	BX,12H
	JC	ST21
        mov     cx,0F10h
st211:  CALL    CHK_STAT
        mov     bx,13h
	JNC	ST3
        loop    st211
ST22:	MOV	AX,bx
	CALL	SHWORD
	JMP	ENDR

ST3:	MOV	AH,0FH
	CALL	NEC_OUTPUT
        MOV     BX,21H
        JC      ST31
	MOV	AH,0
	CALL	NEC_OUTPUT
        MOV     BX,22H
        JC      ST31
        MOV     AH,12
	CALL	NEC_OUTPUT
        MOV     BX,23H
        MOV     CX,0F10H
ST311:  CALL    CHK_STAT
        mov     bx,24h
        JNC	J29
        LOOP    ST311
ST31:   MOV     AX,BX
	CALL	SHWORD
	JMP	ENDR
J29:	MOV	AH,ES:[SI+9]
J29A:	OR	AH,AH
	JZ	J31
        MOV     CX,550
J30:	LOOP	J30
	DEC	AH
	JMP	J29A
J31:    mov     ah,0c5h
	CALL	NEC_OUTPUT
	MOV	AH,0
	CALL	NEC_OUTPUT
        MOV     AH,12
	CALL	NEC_OUTPUT
	MOV	AH,0
	CALL	NEC_OUTPUT
	MOV	AH,1
	CALL	NEC_OUTPUT
	MOV	AH,ES:[SI+3]
	CALL	NEC_OUTPUT
	MOV	AH,ES:[SI+4]
	CALL	NEC_OUTPUT
	MOV	AH,ES:[SI+5]
	CALL	NEC_OUTPUT
	MOV	AH,ES:[SI+6]
	CALL	NEC_OUTPUT
        MOV     CX,0F10H
J311:   CALL    WAIT_INT
        JNC	J32
        LOOP    J311        
        CALL    RESULTS
        MOV	AX,07H
	CALL	SHWORD
        JMP	ENDR
J32:	CALL	RESULTS
        JNC     S11
        MOV     AX,08H
        CALL    SHWORD
        JMP     ENDR
S11:    call    delay
        mov     ax,ddata
        mov     es,ax
        mov     di,offset buf
        mov     cx,20h
s111:   mov     ax,es:[di]
        call    shword
        loop    s111
        JMP     REND
ENDR:	MOV	AH,ES:[SI+2]
	MOV	MC,AH
	MOV	AX,OFFSET DDATA
	MOV	DS,AX
	MOV	DX,OFFSET EMES
	MOV	AH,09H
	INT	21H
REND:   CLI                             ;关中断 
        MOV     AX,DDATA
        MOV     DS,AX
        XOR     AX,AX                   ;设置中断向量
        MOV     ES,AX
        MOV     DI,38H                  ;4*0EH,0EH号中断为软盘中断
        MOV     AX,ES:[DI]
        MOV     AX,OLDINTO
        CLD 
        STOSW
        MOV     AX,ES:[DI]
        MOV     AX,OLDINTS
        STOSW
        MOV     DI,78H                  ;4*1EH,1EH为软盘参数块
        MOV     AX,ES:[DI]
        MOV     AX,OLDPARAO
        STOSW
        MOV     AX,ES:[DI]
        MOV     AX,OLDPARAS
        STOSW
        STI 

wait_press_key:
		mov	ah, 0bh	;检测是否有键按下?检查键盘状态,al=00则无输入
		int	21h
		cmp	al, 0h
		je		wait_press_key	;若无键按下,则程序往下执行

        MOV     AX,4C00H
        INT     21H
START	ENDP

NEC_OUTPUT	PROC	NEAR	;AH为参数
	PUSH	DS
        PUSH    DX
        PUSH    CX
        MOV	DX,S0040
        MOV	DS,DX
        MOV	DX,3F4H		;将软盘FDC的主状态寄存器地址送DX
	XOR	CX,CX		;置循环等待时间,清标志
N1:	IN	AL,DX		;读主状态寄存器,判是否可以写数据寄存器
        MOV	BL,AL
        AND	AL,0C0H
        CMP     AL,80H
        JZ      N3
        LOOP    N1
N2:     OR      DSS,80H		;置超时错误码
        POP     CX
        POP     DX
        POP	DS
        STC
        RET
N3:     MOV     AL,AH		;输出命令
        MOV     DX,3F5H
	OUT	DX,AL
        POP     CX
        POP     DX
        POP	DS
	RET
NEC_OUTPUT	ENDP

DISKINT	PROC FAR
	STI
	PUSH	DS
	PUSH	AX
	MOV	AX,S0040
	MOV	DS,AX
	OR	SSS,80H
	MOV	AL,20H
	OUT	20H,AL
	POP	AX
	POP	DS
	IRET
DISKINT	ENDP

WAIT_INT	PROC	NEAR
	STI
        PUSH	DS
        PUSH    BX
        PUSH    CX
        MOV	BX,S0040
        MOV	DS,BX
 	XOR	CX,CX
        MOV     CX,0FFFFH
W1:     TEST    SSS,80H
        JNZ      W2
        LOOP    W1
	OR	DSS,80H
        STC
W2:     PUSHF
        AND     SSS,07FH
        POPF
        POP     CX
        POP     BX
        POP	DS
	RET	
	ENDP
	
DMA_SETUP PROC NEAR		;DMA初始化程序,AH为参数,决定DMA的方式字
        PUSH    CX		;ES指向缓冲区所在段
	CLI
        OUT     0CH,AL		;清除字节指针触发器
        OUT     0BH,AL		;写模式寄存器
	MOV	AX,ES		;缓冲区段地址
	MOV	CL,4
	ROL	AX,CL
	MOV	CH,AL		;取得页面地址
	AND	AL,0F0H		
	ADD	AX,BX		;计算页内偏移
        JNC     D1		;没有跨页
	INC	CH		;保存页内偏移
D1:     PUSH    AX		;设置通道2内存地址初值
        OUT     04H,AL		;写低字节
	MOV	AL,AH
        OUT     04H,AL		;写高字节
	MOV	AL,CH
	AND	AL,0FH
	OUT	81H,AL		;写通道2的页面地址寄存器
	MOV	AH,DH		;送扇区数到AH中
	SUB	AL,AL
	SHR	AX,1		;<=> 扇区数*128
	PUSH	AX
        PUSH    DS
        MOV     AX,DDATA
        MOV     DS,AX
        MOV     AX,OFFSET DPARA
        MOV     SI,AX
        MOV     BX,3
        MOV     AH,[BX+SI]	;取每扇区的字节数
        POP     DS
        JNC     D2
        CALL    NEC_OUTPUT
D2:     MOV     CL,AH		;写传送字节数
        POP     AX		
	SHL	AX,CL
	DEC	AX
	PUSH	AX		;送通道2字节计数值
        OUT     05,AL		;写低字节		
        MOV     AL,AH
        OUT     05,AL		;写高字节
        STI			;开中断
        POP     CX
        POP     AX
	ADD	AX,CX
        MOV     AL,2
        OUT     0AH,AL		;清通道2 的屏蔽字
        POP     CX
	RET
DMA_SETUP	ENDP

RESULTS	PROC	NEAR
        CLD     
	PUSH	DS
        PUSH    CX
        PUSH    DX
        PUSH    BX
        MOV	BX,S0040
        MOV	DS,BX
        MOV     DI,OFFSET NS
        MOV	BL,7
R1:     XOR     CX,CX
	MOV	DX,3F4H
R2:     IN      AL,DX
	TEST	AL,80H
        JNZ     R4
        LOOP    R2
	OR	DSS,80H
R3:     STC
        POP     BX
        POP     DX
        POP     CX
	POP	DS
	RET
R4:     IN      AL,DX
	TEST	AL,40H
        JNZ     R6
R5:     OR      DSS,20H
        JMP     R3
R6:     MOV     DX,3F5H
	IN	AL,DX
	MOV	[DI],AL
	INC	DI
        XOR	CX,CX
R7:     LOOP    R7
	MOV	DX,3F4H
	IN	AL,DX
	TEST	AL,10H
        JZ      R8
	DEC	BL
        JNZ     R1
        JMP     R5
R8:     POP     BX
        POP     DX
        POP     CX
	POP	DS
        RET
RESULTS	ENDP

CHK_STAT	PROC	NEAR
        PUSH    CX
	CALL	WAIT_INT
	mov	bx,55H
        JC      C1
        MOV     AH,08H
	CALL	NEC_OUTPUT
	CALL	RESULTS
	mov 	bx,66H
        JC      C1
	MOV	AL,NS
	AND	AL,60H
	CMP	AL,60H
        mov	bx,77H
        JZ      C2
	CLC	
	mov 	bx,88H
C1:     POP     CX
        RET
C2:     OR      DSS,40H
	STC
        POP     CX
	RET
CHK_STAT	ENDP

SHWORD	PROC	NEAR
	PUSH	BX
	MOV	BL,AH
	CALL	SHOW
	MOV	BL,AL
	CALL	SHOW
	POP	BX
	RET	
	ENDP
		
SHOW	PROC	NEAR
	PUSH	AX
	PUSH	DX
	MOV	AL,BL
	AND	AL,0F0H			;取高4位
	SHR	AL,4
	CMP	AL,0AH			;是否是A以上的数
        JB      SC2       
	ADD	AL,07H		
SC2:    ADD     AL,30H   
	MOV	DL,AL			;显示字符
	MOV	AH,02H
	INT	21H
	MOV	AL,BL
	AND	AL,0FH			;取低4位
	CMP	AL,0AH
        JB      SC3
	ADD 	AL,07H
SC3:    ADD     AL,30H
	MOV	DL,AL			;显示字符
	MOV	AH,02H
	INT	21H
	POP	DX
	POP	AX
	RET
	ENDP

DELAY	PROC	NEAR
	PUSH	BX
	PUSH	CX
	MOV	CX,0FFFFH
DD2:	PUSH	CX
	MOV	CX,0FFFH
DD1:	LOOP	DD1
	POP	CX
	LOOP	DD2
	POP	CX
	POP	BX
	RET
DELAY	ENDP

CODE	ENDS
        END START

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -