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

📄 atoms.asm

📁 这是一些例程
💻 ASM
📖 第 1 页 / 共 3 页
字号:
;----------------------------------------------------------------------------;
; ATOMS.ASM:    A simple installable character device driver
;----------------------------------------------------------------------------;
; based on skeleton in The MS-DOS Encyclopedia, (c) 1988 Microsoft Press
;----------------------------------------------------------------------------;

	include dos.inc         ; macros to @ShowStr, etc...
	
	.model  tiny, c
	.386
	
;----------------------------------------------------------------------------;
;                           Typedefs & Prototypes 
;----------------------------------------------------------------------------;

NPBYTE  TYPEDEF NEAR PTR BYTE           ; near pointer to a byte
FPTR    TYPEDEF FAR PTR                 ; far pointer
NPTR    TYPEDEF NEAR PTR                ; near pointer
SEGPTR  TYPEDEF WORD                    ; segment selector
DEVLINK TYPEDEF SDWORD                  ; link to other devices
ATRIBUT TYPEDEF WORD                    ; device attribute word

st_len  PROTO NEAR, :NPBYTE, :SEGPTR    ; gets the length of string into ax
int2hex PROTO NEAR, :WORD, :NPBYTE      ; converts integers to hexadecimal
scan    PROTO NEAR, :NPBYTE, :SEGPTR    ; scans the command line

;----------------------------------------------------------------------------;
;                          Flags & Numeric Equates                
;----------------------------------------------------------------------------;

MaxCmd  EQU     24t             ; max command code for DOS 3.2+
cr      EQU     0Dh             ; carriage return
lf      EQU     0Ah             ; linefeed
eom     EQU     '$'             ; end-of-message signal
space   EQU     20h             ; ascii space
tab     EQU     09h             ; ascii tab

; definition of a Request Header structure so that we can access its elements. 
; this structure is not exhaustive at all: block device use some addresses for
; different purposes, and have data beyond the cmd_seg word.

REQ_HEADER      STRUCT 1t
	lengt   BYTE    ?               ; request header length
	unit    BYTE    ?               ; unit number (for Block Devs. only)
	code    BYTE    ?               ; command code
	stat    WORD    ?               ; status word
	reserv  QWORD   ?               ; reserved for DOS us
	media   BYTE    ?               ; Media ID    (for Block Devs. only)
	xfer    NPTR    ?               ; offset of data buffer
	xseg    SEGPTR  ?               ; segment of data buffer
	UNION
		xcount  WORD    ?       ; count of bytes in request, or
		cmd_off NPTR    ?       ; offset of CONFIG.SYS line
	ENDS
	cmd_seg SEGPTR  ?               ; segment of CONFIG.SYS line
REQ_HEADER      ENDS

; values for the different 'magic numbers' used with Device Drivers

fNEXTLINK   EQU -1              ; word to tell DOS to substitute by address of
				; next device
fCHARDEVICE EQU 8000h           ; bit to define device as a character device
fOPENCLOSE  EQU 0040h           ; bit to indicate that device supports open/close
fDONE       EQU 0100h           ; Status Done bit meaning device is done
fERROR      EQU 8000h           ; Status Error bit meaning error on operation
fWRITE_E    EQU 000Ah           ; Write Fault Error bit
fUNKNOWN_E  EQU 0003h           ; Unknown Command Error bit

; values for the search flags used by Write Routine

fDELETE EQU     2
fINSERT EQU     4
fSEARCH EQU     8

; value for buffer (atom memory) limits

BUFMINIMUM EQU  00400h  ; the minimum will be 1024 bytes
BUFMAXIMUM EQU  07FFFh  ; the maximum will be 32K. It can be less than that,
			; but not greater, because of the signed index for 
			; scasb operations.

;----------------------------------------------------------------------------;
;                             Code Segment                                   
;----------------------------------------------------------------------------;
	.code
	
	org     0               ; drivers should start at address 0000h
	                        ; this will cause a linker warning - ignore it.

Header:                         ; device driver header
	DEVLINK  fNEXTLINK       ; link to next device driver
	ATRIBUT fCHARDEVICE+fOPENCLOSE  ; device attribute word: 
					; char.device+open/close
	NPTR    Strat           ; 'Strat' entry point
	NPTR    Intr            ; 'Intr' entry point
	BYTE    'ATMS     '     ; logical device name (needs to be 8 chars)

;----------------------------------------------------------------------------;
; data variables
;----------------------------------------------------------------------------;

null     BYTE    0              ; dummy to do a quick erase of pAtomValue
pAtomVal NPBYTE  null           ; pointer to value of result of atom search
MemEnd   NPBYTE  AtomList       ; end of used memory:      initially AtomList
MaxMem   NPBYTE  AtomList       ; end of available memory: initially AtomList
lpHeader FPTR    0              ; far pointer to request header
		
;----------------------------------------------------------------------------;
; Dispatch table for the interrupt routine command codes                     
;----------------------------------------------------------------------------;

Dispatch:                       
	NPTR    Init            ;  0 = init driver 
	NPTR    Error           ;  1 = Media Check         (block devices only) 
	NPTR    Error           ;  2 = build BPB           (block devices only)
	NPTR    Error           ;  3 = I/O control read         (not supported)
	NPTR    Read            ;  4 = read (input) from device  (int 21h, 3Fh)
	NPTR    Error           ;  5 = nondestructive read      (not supported)  
	NPTR    Success         ;  6 = ret input status        (int 21h, 4406h) 
	NPTR    Error           ;  7 = flush device input buffer (not supportd)         
	NPTR    Write           ;  8 = write (output) to device  (int 21h, 40h)
	NPTR    Write           ;  9 = write with verify (== write)  (21h, 40h)
	NPTR    OutStat         ; 10 = ret output status       (int 21h, 4407h)
	NPTR    Error           ; 11 = flush output buffer      (not supported) 
	NPTR    Error           ; 12 = I/O control write        (not supported)
	NPTR    Success         ; 13 = device open               (int 21h, 3Dh)
	NPTR    Success         ; 14 = device close              (int 21h, 3Eh)
	NPTR    Error           ; 15 = removable media     (block devices only)
	NPTR    Error           ; 16 = Output until Busy   (mostly for spooler)
	NPTR    Error           ; 17 = not used
	NPTR    Error           ; 18 = not used
	NPTR    Error           ; 19 = generic IOCTL            (not supported)
	NPTR    Error           ; 20 = not used
	NPTR    Error           ; 21 = not used
	NPTR    Error           ; 22 = not used
	NPTR    Error           ; 23 = get logical device  (block devices only)
	NPTR    Error           ; 24 = set logical device  (block devices only)

;----------------------------------------------------------------------------;
; Strategy Routine
;----------------------------------------------------------------------------;
; device driver Strategy routine, called by MS-DOS kernel with
; ES:BX = address of request header
;----------------------------------------------------------------------------;

Strat   PROC FAR
	mov     word ptr cs:[lpHeader], bx      ; save the address of the 
	mov     word ptr cs:[lpHeader+2], es    ; request into 'lpHeader', and                  
	ret                                     ; back to MS-DOS kernel
Strat   ENDP

;----------------------------------------------------------------------------;
; Intr
;----------------------------------------------------------------------------;
; Device driver interrupt routine, called by MS-DOS kernel after call to     
; Strategy routine                                                           
; This routine basically calls the appropiate driver routine to handle the
; requested function. 
; Routines called by Intr expect:
;       ES:DI   will have the address of the request header
;       DS      will be set to cs
; These routines should only affect ax, saving es,di,ds at least
;
; Input: NONE   Output: NONE   -- data is transferred through request header
;
;----------------------------------------------------------------------------;

Intr    PROC FAR
	pusha                   ; save registers
	pushf                   ; save flags
	cld                     ; direction flag: go from low to high address
				
	mov     si, cs          ; make local data addressable
	mov     ds, si          ; by setting ds = cs
			
	les     di, [lpHeader]  ; ES:DI = address of req.header

	ASSUME  di:PTR REQ_HEADER ; to be able to use the REQ_HEADER offsets

	xor     ebx, ebx        ; erase ebx
	mov     bl,es:[di].code ; get EBX = command code (from req.header)
	
	.IF (bx > MaxCmd)                 ; check to make sure we have a valid
		call    Error             ; command code
	.ELSE                             ; else, call command-code routine,  
		call    NPTR PTR Dispatch[2*ebx] ; indexed from Dispatch table
	.ENDIF                            ; (Ebx used to allow scaling factors)

	or      ax, fDONE       ; merge Done bit into status and
	mov     es:[di].stat,ax ; store status into request header
	
	ASSUME  di:NOTHING      ; di will be something else now

	popf                    ; restore registers
	popa                    ; restore flags
	ret                     ; return to MS-DOS kernel
Intr    ENDP

; Command-code routines are called by the Interrupt routine via the dispatch
; table. Each routine should return AX = 0000H if function was completed
; successfully or AX = 8000h + error code if function failed.

;----------------------------------------------------------------------------;
; function 4 = read (input) from device                                      
;----------------------------------------------------------------------------;
; what the function basically does is transfer from the string that pAtomVal 
; points, to the buffer pointed to in the request header. the values have 
; to be loaded into ES:DI and DS:SI for the movsb instruction, and other
; checks are made to account for differences in sizes                                ; 
;----------------------------------------------------------------------------;

Read    PROC NEAR USES ds es di         

	lds     si, [lpHeader]          ; put request header address in DS:SI

	ASSUME  si:PTR REQ_HEADER       ; to use the REQ_HEADER offsets

	mov     cx, [si].xcount         ; load cx with the size of buffer
	mov     es, [si].xseg           ; load es with segment of buffer
	mov     di, [si].xfer           ; load di with offset of buffer

	ASSUME  si:NOTHING              ; si will be something else now
	
	mov     si, cs                  ; load ds with cs again
	mov     ds, si
	mov     si, pAtomVal            ; load si with the string's address

	INVOKE  st_len, si, ds          ; load length of pAtomVal into ax

	.IF     (cx > ax)               ; if cx > ax, then the buffer has space
		mov     bx, ax          ; to hold all the string. bx (used to
		mov     cx, ax          ; return number of chars transferred)
		rep     movsb           ; will hold the string length. We move
					; into cx the length of the string, 
					; and copy the result string into the 
					; buffer, with the 'rep movsb' instruct
	.ELSE
		mov     bx, cx          ; otherwise, bx will be the size of the
		dec     cx              ; the buffer. decrement cx so that we
		rep     movsb           ; leave the last char of the buffer
		xor     ax,ax           ; free to store a 0 to mark the end of
		stosb                   ; the string.

⌨️ 快捷键说明

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