【分享】关于int 13H
无意间在Google中找到了一个网址,发现里面是一段汇编源代码,但看了半天,奈何功力太浅竟然无法全部弄明白,同时秉着共同分享的心情将代码贴在这儿,望哪位前辈高人能够将其中的种种分析一下,拜托!ENTRY 0EC59h ; IBM entry point for floppy
INT_13: STI ; Floppy disk services
PUSH BP
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH BX
MOV DI,AX ; Request type in DI, for index
XOR AX,AX
MOV DS,AX ; get interrupt vector 13h
LES SI,DWord ptr DS:78h ; Get disk parameter table
MOV AX,40h
MOV DS,AX
MOV BX,5
MOV AX,ES:[BX+SI] ; Get (Gap Length, DTL) in AX
PUSH AX ; ...save it
DEC BX
DEC BX
MOV AX,ES:[BX+SI] ; Get (Bytes/sector,EOT) in AX
PUSH AX ; ...save it
XCHG CL,DH
XCHG DL,CL
PUSH DX ; Push (Head,Drive) swapped
PUSH CX
PUSH DI
MOV BP,SP ; Mark bottom of stack frame
ifdef SLOW_FLOPPY
CALL FD_SPD ; ...execute request lo speed
else
CALL FD_XQT ; ...execute at current speed
endif
MOV AH,ES:[SI+2] ; Get new motor count
MOV DS:40h,AH ; ...and save it
MOV AH,DS:41h ; Get completion status
CMP AH,1 ; ...check for write protect
CMC ; ...was write protect error
POP BX
POP CX
POP DX
XCHG DL,CL
XCHG CL,DH
POP BX ; Clean
POP BX ; ...up
POP BX ; ...stack
POP ES
POP DS
POP DI
POP SI
POP BP
RETF 2
FD_XQT: MOV AL,[BP+1] ; Get floppy service number
OR AL,AL
JZ FD_RST ; ...reset, AH=0
DEC AL
JZ FD_XQ3 ; ...read status, AH=1
CMP Byte ptr [BP+2],3 ; For track number above 3?
JA FD_XQ1 ; ...yes
CMP AL,5 ; Service within range?
JBE FD_XQ2 ; ...yes
FD_XQ1: MOV Byte ptr DS:41h,1 ; Say write protect error
RET
FD_XQ2: JMP FD_001 ; Execute legal service
FD_XQ3: MOV AL,DS:41h ; Return NEC status byte
RET
FD_RST: MOV DX,3F2h ; Reset the floppy disk system
CLI
AND Byte ptr DS:3Fh,0Fh ; Clear "write in progress"
MOV AL,DS:3Fh ; ...find out busy drives
MOV CL,4
SHL AL,CL
TEST AL,20h
JNZ FD_RS1 ; Drive #1 active
TEST AL,40h
JNZ FD_RS2 ; Drive #2 active
TEST AL,80h
JZ FD_RS0 ; Drive #3 idle
FD_RS3: INC AL
FD_RS2: INC AL
FD_RS1: INC AL
FD_RS0: MOV Byte ptr DS:3Eh,0 ; All drives need recalibrate
MOV Byte ptr DS:41h,0 ; ...no completion status
OR AL,8 ; Interrupt ON in command word
OUT DX,AL ; ...send word to controller
OR AL,4 ; "Reset" in command word
OUT DX,AL ; ...send word to controller
STI
CALL NC_BSY ; Wait for completion
CALL NC_STS ; ...read result block
MOV AL,DS:42h
CMP AL,0C0h ; Did the reset work
JZ FD_RS4 ; ...yes
MOV Byte ptr DS:41h,20h ; Else set controller error
JMP SHORT FD_RS5 ; ...return
FD_RS4: MOV AL,3 ; Specify command to NEC
CALL NEC765 ; ...send it
MOV AL,ES:[SI] ; First byte in param block
CALL NEC765 ; ...send it
MOV AL,ES:[SI+1] ; Secnd byte in param block
CALL NEC765 ; ...send it
FD_RS5: RET
NECFUN DB 003h,000h,0E6h,0C5h,0E6h,04Dh ; NEC function table lookup
NECDMA DB 000h,000h,046h,04Ah,042h,04Ah ; DMA modes for 8237
NECWRT DB 000h,000h,000h,080h,000h,080h ; Write flag table lookup
NECDRV DB 1,2,4,8 ; Drive number table lookup
NECERR DB 80h,20h,10h,4,2,1 ; Error code table lookup
NECSTS DB 04h,10h,08h,04h,03h,02h,20h ; Disk status table lookup
FD_001: CLI ; Normal (non-reset) commands
MOV Byte ptr DS:41h,0 ; ...reset status
MOV AL,[BP+1] ; Get command word
XOR AH,AH
MOV DI,AX ; Save copy, zero-extended
OUT 0Ch,AL ; ...diddle LSB/MSB flip-flop
MOV AL,CS:[DI+NECDMA] ; Fetch DMA mode
OUT 0Bh,AL ; ...send it to IC8237
MOV AX,[BP+0Ch] ; Get segment address
MOV CL,4 ; ...convert
ROL AX,CL ; ...to bytes
MOV CH,AL ; Copy the wrap around
AND CH,0Fh ; ...mask out not wrapped, CH
AND AL,0F0h ; ...mask out wrapped, AL
ADD AX,[BP+0Ah] ; Add offset to AX
ADC CH,0 ; ...do carry if set
MOV DX,AX ; Now save lo 16 bits of addr.
OUT 4,AL ; ...send lowest 8 bits " "
MOV AL,AH
OUT 4,AL ; ...send next 8 bits " "
MOV AL,CH
OUT 81h,AL ; Send hi bits to DMA page reg
MOV AH,[BP+0]
XOR AL,AL
SHR AX,1 ; Sector cnt * 128
MOV CL,[BP+6] ; Track count
SHL AX,CL ; * sector count
DEC AX ; - 1
OUT 5,AL ; Send 1/2 of the word count
XCHG AL,AH
OUT 5,AL ; Send 2/2 of the word count
XCHG AL,AH
ADD AX,DX ; Compute final address
JNB FD_002 ; ...ok
STI
MOV Byte ptr DS:41h,9h ; Else wrapped around page reg
JMP FD_011
FD_002: MOV AL,2 ; Disable floppy disk dma
OUT 0Ah,AL
MOV Byte ptr DS:40h,0FFh ; Set large motor timeout
MOV BL,[BP+2] ; ...get drive number
XOR BH,BH
MOV AL,CS:[BX+NECDRV] ; Table lookup bit position
MOV CH,AL ; ...save mask
MOV CL,4
SHL AL,CL ; Shift mask into place
OR AL,BL ; ...or in drive select
OR AL,0Ch ; ...or in DMA and NO RESET
MOV DX,3F2h
OUT DX,AL ; Send to floppy control port
STI
MOV AL,CS:[DI+NECWRT] ; Table lookup for write flag
OR DS:3Fh,AL ; ...set write flag if active
OR AL,AL
JNS FD_003 ; ...skip if non-write
MOV AH,ES:[SI+0Ah] ; Motor start from param blk
OR AH,AH
JZ FD_003 ; ...none specified
TEST CH,DS:3Fh ; Was this drive motor running?
JNZ FD_003 ; ...skip if so
CALL FD_WT1 ; Else delay for motor start
FD_003: OR DS:3Fh,CH ; Show this motor is running
TEST CH,DS:3Eh ; Drive recalibration needed?
JNZ FD_004 ; ...no, skip
OR DS:3Eh,CH ; Else show recalibrated
MOV AL,7 ; Send RECAL command
CALL NEC765 ; ...to NEC 765 chip
MOV AL,BL
CALL NEC765 ; ...drive number
CALL NC_BSY ; Wait for completion of RECAL
CALL NEC_04 ; ...dummy call to RET
FD_004: MOV AL,0Fh ; Request a seek
CALL NEC765 ; ...from the NEC 765
MOV AL,BL
CALL NEC765 ; Drive number
MOV AL,[BP+3]
CALL NEC765 ; Cylinder number
CALL NC_BSY ; ...wait for completion
CALL NC_STS ; ...read results
MOV AL,ES:[SI+9] ; Get head settle time
OR AL,AL ; ...none specified?
JZ FD_005 ; ...if none, skip
FD_STL: MOV CX,226h ; Delay time for head settle
FD_STZ: LOOP FD_STZ ; ...timed wait
DEC AL ; ...delay in millisec
JNZ FD_STL ; ...wait some more
FD_005: MOV AL,CS:[DI+NECFUN] ; Translate user service, then
CALL NEC765 ; ...and send as NEC func
MOV AL,[BP+4] ;
AND AL,1
SHL AL,1
SHL AL,1
OR AL,BL
CALL NEC765
CMP Byte ptr [BP+1],5 ; Is this a format request?
JNZ FD_006 ; ...skip if not
MOV AL,[BP+6] ; Else use user bytes/sector
CALL NEC765
MOV AL,[BP+7] ; ... user EOT
CALL NEC765
MOV AL,ES:[SI+7] ; Disk table format gap length
CALL NEC765
MOV AL,ES:[SI+8] ; Disk table format fill byte
CALL NEC765
JMP SHORT FD_008
FD_006: MOV CX,7 ; Else lookup bytes * 512/sec
MOV DI,3 ; ...from disk table
FD_007: MOV AL,[BP+DI] ; AL has bytes/sector * 512
CALL NEC765
INC DI ; ...get next item for table
LOOP FD_007 ; ...also (EOT,GAP,DTL...)
FD_008: CALL NC_BSY ; Wait on floppy i/o completion
CALL NC_ST1 ; ...get NEC status
MOV AL,DS:42h ; ...into AL
AND AL,0C0h ; Isolate errors
JZ FD_012 ; ...no errors
CMP AL,40h ; Test direction bit
JZ FD_ERR
MOV Byte ptr DS:41h,20h ; Set if bad controller
JMP SHORT FD_012 ; ...return error
FD_ERR: MOV AL,DS:43h ; Read return code from block
MOV CX,6 ; ...number of error types
XOR BX,BX ; Start at error type 0
FD_009: TEST AL,CS:[BX+NECERR] ; Has error type BX occured?
JNZ FD_010 ; ...yes
INC BX ; Else try next error type
LOOP FD_009 ; ...until done
FD_010: MOV AL,CS:[BX+NECSTS] ; Translate error code again
MOV DS:41h,AL ; ...store it as disk status
FD_012: MOV AL,DS:45h ; Get bytes read
CMP AL,[BP+3] ; ...compare with requested
MOV AL,DS:47h ; Read sectors requested
JZ FD_013 ; ...return if all read
MOV AL,[BP+7] ; Else read sectors requested
INC AL ; ...add one for luck
FD_013: SUB AL,[BP+5] ; Subtract stectors read
RET
FD_011: MOV AL,0 ; Show no sectors read
RET
NC_BSY: STI ; Wait for operatin to finish
XOR CX,CX ; ...zero lo orderdelay
MOV AL,2 ; Load hi order delay
NC_BS1: TEST Byte ptr DS:3Eh,80h ; Has interrupt set the flag?
CLC ; ...hack to slow CPU
JNZ NC_BS2 ; ...yes
LOOP NC_BS1 ; Else back for more
DEC AL
JNZ NC_BS1
MOV Byte ptr DS:41h,80h ; Time-out, say it completed
POP AX
XOR AL,AL ; ...return time out code
STC ; ...error status
RET
NC_BS2: AND Byte ptr DS:3Eh,7Fh ; Mask off completion status
RET ; ...return carry clear
NC_RDY: PUSH CX ; Wait for NEC ready for comand
XOR CX,CX
MOV DX,3F4h ; ...NEC status port
NC_RD1: IN AL,DX ; Read status of NEC 765 chip
OR AL,AL
JS NC_RD2 ; ...able to accept command
LOOP NC_RD1
MOV Byte ptr DS:41h,80h ; Else show timeout error
JMP SHORT NC_RD3
NC_RD2: TEST AL,40h ; Test the direction bit
JNZ NC_RD4
MOV Byte ptr DS:41h,20h ; ...clear iff controller err
NC_RD3: POP CX
STC
RET
NC_RD4: INC DX ; Load NEC data port
IN AL,DX ; ...read it
PUSH AX
MOV CX,0Ah ; Short delay
NC_RD5: LOOP NC_RD5
DEC DX ; Load NEC status port
IN AL,DX ; ...read status
TEST AL,10h ; ...set Z flag if done
CLC ; ...return success
POP AX
POP CX
RET
FD_WT1: PUSH CX ; Millisecond delay in AH
FD_WT2: XOR CX,CX
FD_WT3: LOOP FD_WT3
DEC AH
JNZ FD_WT2
POP CX
RET
ifdef SLOW_FLOPPY ; Run floppy at SLOWEST speed
FD_SPD: IN AL,61h ; Toggle speed on Floppy Disk
PUSH AX ; ...save old clock rate
AND AL,0F3h ; ...load slowest clock rate
OUT 61h,AL ; ...slow down to 4.77 mHz
CALL FD_XQT ; Execute the i/o request
POP AX ; ...restore old clock rate
OUT 61h,AL ; ...from saved clock byte
RET
endif
ENTRY 0EF57h ; Disk interrupt entry
INT_E: STI ; Floppy disk attention
PUSH DS
PUSH AX
MOV AX,40h
MOV DS,AX
OR Byte ptr DS:3Eh,80h ; Raise "attention" flag
MOV AL,20h ; Send end_of_interrupt code
OUT 20h,AL ; ...to 8259 interrupt chip
POP AX
POP DS
IRET
NC_STS: MOV AL,8 ; Send a "Request status"
CALL NEC765 ; ...to the NEC 765 chip
NC_ST1: PUSH BX ; Alternate entry point
PUSH CX
MOV CX,7
XOR BX,BX
NC_ST2: CALL NC_RDY ; Wait for NEC 765 ready
JB NC_ST3 ; ...NEC 765 error
MOV [BX+42h],AL ; Save status in BIOS block
JZ NC_ST4 ; ...NEC 765 ready
INC BX ; Count more
LOOP NC_ST2
MOV Byte ptr DS:41h,20h ; NEC 765 controller error
NC_ST3: STC ; Set error condition
POP CX
POP BX
POP AX
XOR AL,AL
RET
NC_ST4: POP CX ; Successful return
POP BX
RET
NEC765: PUSH CX ; Send control to NEC 765 chip
PUSH DX
PUSH AX
XOR CX,CX
MOV DX,3F4h ; Load NEC 765 status port
NEC_01: IN AL,DX ; Read NEC 765 status
OR AL,AL
JS NEC_02 ; ...done
LOOP NEC_01
MOV Byte ptr DS:41h,80h ; Set time out status
JMP SHORT NEC_05
NEC_02: TEST AL,40h ; Check data direction
JZ NEC_03
MOV Byte ptr DS:41h,20h ; ...NEC 765 is gimped
JMP SHORT NEC_05
NEC_03: INC DX ; Load NEC 765 data port
POP AX
OUT DX,AL ; ...write user's parameter
CLC
POP DX
POP CX
NEC_04: RET
NEC_05: POP AX ; Common error return
POP DX
POP CX
POP AX
XOR AL,AL
STC
RET
ENTRY 0EFC7h ; IBM entry for disk param
INT_1E: db 11001111B ; Disk parameter table
db 2
db 25h
db 2
db 8
db 2Ah
db 0FFh
db 50h
db 0F6h
db 19h
db 4