; *****************************************************
;FLOPPY DISK SUB ROUTINE CODE
;
; *****************************************************************************
BITS 16 ; Set code generation to 32 bit mode
ORG 0×0100 ; Set code start address to 0100h
SECTION .text ; Main code section -
; test code for subroutines goes here
MAIN:
;sector sector parameters that we need to test
;head=0,track=0,sector=0
mov dh,0 ;head
mov ch,5 ;track
mov cl,2 ;sector
mov bx, Sector1 ;buffer address
;;;;;;;;;;;;#TEST-1#;;;;;;;;;;;;;;;;;;;;
;Now test initSector
mov al,’A’ ;41H- value to initialize
;no need to set the other arguments as we have already set them earlier
call InitSector
;if you want to see the results just uncomment the below call to DisplaySector
;see the sector contens again to check if the init is working OK?
;call DisplaySector
;;;;;;;;;;;;#END of TEST-1#;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;#TEST-2#;;;;;;;;;;;;;;;;;;;;
;Test setByteAt and GetByteAt routines
;set byte at index 496 of the same sector to ‘X’
mov DI, 496
mov DL, ‘X’
call SetByteAt
;set byte at index 508 of the same sector to ‘Y’
mov DI, 508
mov DL,’Y’
call SetByteAt
;set byte at index 510 of the same sector to ‘Z’
mov DI, 510
mov DL, ‘Z’
call SetByteAt
;we can see the partial test results at this point
;see the sector again to check if the bytes have been set properly
;call DisplaySector
;now we will get the byte that we just set at location 510 and
;use the return value to set another location 509 to see if get/set
;combination is working OK
mov AL,0 ;reset AL before we get the return value. Just to make sure return value we get is the right one
mov SI, 510 ;byte location for GetByteAt routine
call GetByteAt
;now set the byte 511 to the value returned in AL
mov DL,AL ;pass return value in AL as argument to setByteAt
mov DI,511
call SetByteAt
;see the results, Last line of the sector should have two ‘Z’ at end
;and ‘X’ and ‘Y’ on the other locations we set
;rest of the sector would be all ‘A’s as we initSector to ‘A’
call DisplaySector
;;;;;;;;;;;;#End of TEST-2#;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;#TEST-3#;;;;;;;;;;;;;;;;;;;;
;now we will test getSubSector and setSubsector routines
; we will get the last 16 bytes of the current sector that we just
;initialized in test1 and 2 and then use this subsector to set
;the preceding 16 bytes subsector of the same sector
mov SI, 496 ;we need to start with index 496 i.e start of last line
mov AX, 16 ; we need to get 16 bytes subsector
mov BP, SubSector1 ;buffer for subsector
call GetSubSector ;no need to set other arguments as they are already set earlier
;now we have subsector of 16 bytes into buffer Subsector1
;lets set the subsector now
mov DI, 480
call SetSubSector
;see the results. Last two lines of the sector should be identical
call DisplaySector
;;;;;;;;;;;;#End of TEST-3#;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;#TEST-4#;;;;;;;;;;;;;;;;;;;;
;now test the copysector and compare sector routines
;lets copy the sector we have tested in test3 on to another sector
mov dh,0 ;head
mov ch,5 ;track
mov bh,2 ;sector
mov si, Sector1 ;buffer address for source sector
mov dl,1 ;destination head
mov cl,6 ;dest track
mov bl,3 ;dest sector
mov di, Sector2 ;buffer for dest sector
call SectorCopy
;if I uncomment the following line before the sectorcompare is called,
;it should return sectors are NOT equal.
;Otherwise it should print sectors are equal
;mov bl, 4 ;uncomment it and sector compare result should be Not equal
;now if we compare these two sectors, function should return FF (equal)
call SectorCompare
cmp al, 0FFH
je SectorEqual
;sectors are not equal
mov SI, MsgNotEqual
call PutString
jmp exitProgram
SectorEqual:
;sectors are equal
mov SI, MsgEqual
call PutString
exitProgram:
;;;;;;;;;;;;#End of TEST-4#;;;;;;;;;;;;;;;;;;;;
mov AX, 04C00H ; Exit the program
int 21H
; SUBROUTINES ******************************************
; *****************************************************************
; Subroutine name: ReadSector
; Function: Reads a specified sector into a buffer
; Entry conditions: Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector (200H in size) in BX
; Exit conditions: AH has success or error code value,
; sector copied to buffer,
; other register values unchanged
; *****************************************************************
ReadSector:
push BX
push CX
push DX
push AX
mov AH,02H ; read sector service number
mov AL,01H ; number of sectors to read
mov DL,00H ; drive number 0=a: floppy drive
int 13H ; BIOS Disk services
pop BX ; popping AX into BX
mov AL,BL ; restore AL to original value
pop DX
pop CX
pop BX
; AH has success/error code
ret
; *****************************************************************
; Subroutine name: WriteSector
; Function: Writes a buffer to a specified sector
; Entry conditions: Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector (200H in size) in BX
; Exit conditions: AH has success or error code value,
; buffer copied to sector,
; other register values unchanged
; *****************************************************************
WriteSector:
push BX
push CX
push DX
push AX
mov AH,03H ; write sector service number
mov AL,01H ; number of sectors to read
mov DL,0H ; drive number 0=a: floppy drive
int 13H ; BIOS Disk services
pop BX ; popping AX into BX
mov AL,BL ; restore AL to original value
pop DX
pop CX
pop BX
; AH has success/error code
ret
; *****************************************************************
; Subroutine name: InitSector
; Function: Sets bytes of specified sector to given value
; – initialises with value buffer before writing
; Entry conditions: byte value for initialisation in AL
; Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector operation (200H in size) in BX
; Exit conditions: AH has success or error code value,
; buffer copied to sector,
; other register values unchanged
; *****************************************************************
InitSector:
;copy 200H bytes into buffer starting at address BX
push cx
push bx
mov cx,200H
initSectorInitBuffer:
mov [bx],al
inc bx
loop initSectorInitBuffer
pop bx ;move the buffer address to its starting location
pop cx
;write sector; return value in AH
call WriteSector
ret
; *****************************************************************
; Subroutine name: GetByteAt
; Function: gets byte at specified location in specifed sector
; – gets sector into buffer – then gets byte
; Entry conditions: byte location in SI
; Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector operation (200H in size) in BX
; Exit conditions: AH has success or error code value,
; AL has byte from sector,
; other register values unchanged
; *****************************************************************
GetByteAt:
call ReadSector ;read sector into buffer
mov al, [bx+si] ;copy the byte in AL
ret
; *****************************************************************
; Subroutine name: SetByteAt
; Function: sets byte at specified location in specifed sector
; to given value – gets sector into buffer -
; sets byte value,then writes buffer back to sector
; Entry conditions: byte location in DI
; byte value to assign to location in DL
; Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector operation (200H in size) in BX
; Exit conditions: AH has success or error code value,
; other register values unchanged
; *****************************************************************
SetByteAt:
call ReadSector
mov [bx+di],dl
call WriteSector
ret
; *****************************************************************
; Subroutine name: GetSubSector
; Function: gets copy of specified subsector of given sector
; – gets sector into buffer – then gets subsector
; Entry conditions: byte location of start of subsector in SI
; length of subsector in AX
; Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector operation (200H in size) in BX
; buffer address for subsector storage in BP
; Exit conditions: AH has success or error code value,
; copy of subsector in buffer addressed by BP,
; other register values unchanged
; *****************************************************************
GetSubSector:
push cx
push si
push di
push es
push ax ;save the length of subsector before readsector call
call ReadSector ;read sector into buffer
pop cx ;get length of subsector into cx
push ds
pop es ;set es to point to data segment register
add si, bx ;add buffer starting address to si (byte location of subsector)
;si is pointing to absolute source index of subsector now
mov di, bp ;destination for subsetor
cld ;clear direction flag to tell CPU to inc si,di in mov instruction
;The movsb (move string, bytes) fetches the byte at address ds:si,
;stores it at address es:di, and then increments or decrements the si and di
;registers by one. If the rep prefix is present, the CPU checks cx to see if it
;contains zero. If not, then it moves the byte from ds:si to es:di and decrements
;the cx register. This process repeats until cx becomes zero.
rep movsb ;copy cx bytes from ds:si to es:di
;restore saved registers
pop es
pop di
pop si
pop cx
ret
; *****************************************************************
; Subroutine name: SetSubSector
; Function: sets specified subsector of given sector to
; value of array specified
; – gets sector into buffer – then sets subsector
; in buffer, then writes buffer to sector
; Entry conditions: byte location of start of subsector in DI
; length of subsector in AX
; Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector operation (200H in size) in BX
; buffer address for subsector storage in BP
; Exit conditions: AH has success or error code value,
; subsector in buffer addressed by BP copied into sector,
; other register values unchanged
; *****************************************************************
SetSubSector:
push si
push di
push es
push cx
push dx
push ax ;save the length of subsector before readsector call
call ReadSector ;read sector into buffer
pop cx ;get length of subsector into cx
push ds
pop es ;set es to point to data segment register
cld ;clear direction flag to tell CPU to inc si,di in mov instruction
add di, bx ;add buffer starting address to di (start byte location of subsector)
;di is pointing to absolute point in buffer where we need to start copying
mov si, bp ;source for subsetor
;The movsb (move string, bytes) fetches the byte at address ds:si,
;stores it at address es:di, and then increments or decrements the si and di
;registers by one. If the rep prefix is present, the CPU checks cx to see if it
;contains zero. If not, then it moves the byte from ds:si to es:di and decrements
;the cx register. This process repeats until cx becomes zero.
rep movsb ;copy cx bytes from ds:si to es:di
pop dx
pop cx ;restore arguments for write sector call
call WriteSector
;restore saved registers
pop es
pop di
pop si
ret
; *****************************************************************
; Subroutine name: SectorCompare
; Function: compares 2 sectors for equality – returns FF
; if equal and 0 if not
; – get 2 specified sectors into buffers – compare
; buffers,return result
; Entry conditions: 1st sector – disk head in DH, cylinder in CH, sector in BH
; 2nd sector – disk head in DL, cylinder in CL, sector in BL
; buffer address for first sector (200H in size) in SI
; buffer address for second sector in DI
; Exit conditions: AH has success or error code value,
; AL is FF if sectors have identical contents, 0 otherwise
; other register values unchanged
; *****************************************************************
SectorCompare:
;save registers
push bx
push cx
push dx
push si
push di
;copy parameters on stack for second ReadSector call later
push bx
push cx
push dx
mov cl, bh ;move argument sector on track into CL
mov bx,si ;move argument buffer address in to BX
call ReadSector
;restore original arguments
pop dx
pop cx
pop bx
mov dh,dl ;argument disk head
mov ch,cl ;argument cylinder
mov cl,bl ;argument sector on track
mov bx,DI ;argument buffer address
call ReadSector
;both sectors copied to SI, DI locations respectively. Now we will compare them
mov cx, 200H
keepComparing:
mov al, [si]
cmp [di], al
jne sectorCompareNotEqual
inc si
inc di
loop keepComparing
;if control reach here , it means we have traversed complete sector and all bytes are equal
;set the return value to FF to represent this
mov al, 0FFH
jmp endCompare
sectorCompareNotEqual:
;if control comes here, it means we have found the non equal byte. Set al to 0 and return
mov al,0
endCompare:
;restore registers
pop di
pop si
pop dx
pop cx
pop bx
ret
; *****************************************************************
; Subroutine name: SectorCopy
; Function: copies source sector to destination sector
; – get source sector into buffer – copy to second buffer
; – write second buffer to destination sector
; Entry conditions: 1st sector – disk head in DH, cylinder in CH, sector in BH
; 2nd sector – disk head in DL, cylinder in CL, sector in BL
; buffer address for source sector (200H in size) in SI
; buffer address for destination sector in DI
; Exit conditions: AH has success or error code value,
; other register values unchanged
; *****************************************************************
SectorCopy:
;save registers
push bx
push cx
push dx
push si
push di
push es
;push parameters on stack for second time use for WriteSector call later
push bx
push cx
push dx
push di
push si
mov cl, bh ;move argument sector on track into CL
mov bx,si ;move argument buffer address in to BX
call ReadSector
;copy buffer1 onto buffer2
mov cx, 200H
push ds
pop es
cld ;clear direction flad
rep movsb
;restore original arguments
pop si
pop di
pop dx
pop cx
pop bx
mov dh,dl ;argument disk head
mov ch,cl ;argument cylinder
mov cl,bl ;argument sector on track
mov bx,DI ;argument buffer address
call WriteSector
;save registers
pop es
pop di
pop si
pop dx
pop cx
pop bx
ret
; *****************************************************************
; Subroutine name: DisplaySector
; Function: displays to console window contents of given sector
; display format is
; 32 (20H) lines, each line displays 16 bytes of the sector
; as ASCII characters and then as 4 digit hex numbers
; so a line consists of
; 16 ASCII characters, a 2 space separator, 16 bytes as hex numbers,
; then a newline – for readability you will need a
; space between each of the 4 digit hex numbers
; Entry conditions: Disk Head (0 or 1) in DH
; cylinder (track) number (00H to 4FH) in CH
; sector on track (01H to 12H) in CL
; buffer address for sector (200H in size) in BX
; Exit conditions: AH has success or error code value,
; sector displayed in console window -
; NOTE – since console window is 80×25 the whole
; of the sector cannot be displayed in the console
; window in one go – redirection can be used
; to send console output to a file for reading using
; an editor – thus e.g. at the dos prompt you can type
; sector-editor > filename
; filename wil contain all console output generated by
; sector-editor
; other register values unchanged
; *****************************************************************
DisplaySector:
push bx
push cx
push dx
push si
call ReadSector
mov cx,20H ;no of lines
mov si,0
outerLoop: ;outer loop for no of lines
push cx ;save outer loop counter
mov cx,10H ;no of bytes on each line
innerLoop1:
;display 16 bytes as ascii
mov dl,[bx+si]
call Putch
inc si
loop innerLoop1
mov dl,32 ;ascii for space character
call Putch
mov cx,10H ;no of bytes to be printed in hex
sub si,10H ;revind si to point to the start byte for this line
innerLoop2:
mov dh,32
call Putch
;display 16 bytes as HEX
mov dh,[bx+si]
call PutHex
inc si
loop innerLoop2
call Putln ;display end of line
pop cx ;restore outer loop counter
loop outerLoop
pop si
pop dx
pop cx
pop bx
ret
; End of user defined subroutines *********************************
%include “stdio.asm”
SECTION .data ; data segment for initialised data – also put constants here
MsgEqual db ‘Sectors are equal’,0
MsgNotEqual db ‘Sectors are NOT equal’,0
SECTION .bss ; data segment for unitialised data
Sector1 resb 512
Sector2 resb 512
SubSector1 resb 16 ;to test getSubSector and setSubSector
; you may need other buffers
JosephTham©
Important: If you taking this code or working on any projects, please quoted a references on it.




0 comments:
Post a Comment