rgoff
asked on
How do I use Int 13h (BIOS call) to directly read from and write to hard disks?
I am attempting to create a program that will allow me to make a cloned image of my hard disk. In other words, my system has 2 hard drives, in which one disk is my boot drive, and the second drive is supposed to be a mirror of the first drive. Both drives are alike, with 16 heads and 63 sectors per cylinder each.
I have included an assembly language (Turbo Assembler) listing of my program, below. Any insight as to why my program is not functing properly would be greatly appreciated. Please note that my e-mail address has changed: it is now RAYIDEA464@CS.COM
.model small
.386
.data
disk_buffer dw 16128 dup(?) ;512 bytes * 63
.stack 16384
.code
mov sp,16384 ;Place stack hi
begin: jmp short main
main proc near
mov ax,@data
mov ds,ax
mov es,ax ;Point ES to disk buf
mov ch,0 ;1st cylinder of disk
mov cl,1 ;1st sector of disk
mov dh,0 ;1st read-write head
Retry:
mov ah,2 ;Read a sector to mem
mov al,63 ;Entire track (cyl)
mov bx,offset disk_buffer ;Sectors go to memory
mov dl,80h ;1st hard disk.
push si
push di
int 13h
pop di
pop si
mov ah,3 ;Write sect to drive
mov al,63 ;Entire track (cyl)
mov bx,offset disk_buffer ;Sects go to 2nd disk
mov dl,81h ;2nd hard disk
push si
push di
int 13h
pop di
pop si
inc ch
cmp ch,255
jb Retry
inc dh
mov ch,0
cmp dh,15
jbe Retry
mov ax,4c00h ;Exit to
int 21h ;DOS
main endp
end begin
I have included an assembly language (Turbo Assembler) listing of my program, below. Any insight as to why my program is not functing properly would be greatly appreciated. Please note that my e-mail address has changed: it is now RAYIDEA464@CS.COM
.model small
.386
.data
disk_buffer dw 16128 dup(?) ;512 bytes * 63
.stack 16384
.code
mov sp,16384 ;Place stack hi
begin: jmp short main
main proc near
mov ax,@data
mov ds,ax
mov es,ax ;Point ES to disk buf
mov ch,0 ;1st cylinder of disk
mov cl,1 ;1st sector of disk
mov dh,0 ;1st read-write head
Retry:
mov ah,2 ;Read a sector to mem
mov al,63 ;Entire track (cyl)
mov bx,offset disk_buffer ;Sectors go to memory
mov dl,80h ;1st hard disk.
push si
push di
int 13h
pop di
pop si
mov ah,3 ;Write sect to drive
mov al,63 ;Entire track (cyl)
mov bx,offset disk_buffer ;Sects go to 2nd disk
mov dl,81h ;2nd hard disk
push si
push di
int 13h
pop di
pop si
inc ch
cmp ch,255
jb Retry
inc dh
mov ch,0
cmp dh,15
jbe Retry
mov ax,4c00h ;Exit to
int 21h ;DOS
main endp
end begin
You skipped two important clues, one, what makes you think it is not working (error msg?), two, what you think is working about it?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
See also:
http://turing.csc.smith.edu/~thiebaut/ArtOfAssembly/CH13/CH13-2.html#HEADING2-73
Noting, only 128 sectors can be accessed at a time (64K DMA limit) and that DMA can only transfer to one memory segment at a time, up to 64K but not across border. ES:BX buffer must fit into the 64K starting with ES or DMA may report error (likely # 09H). You might consider going flexible, increasing buffer to max then commenting how much is used for the special case.
http://turing.csc.smith.edu/~thiebaut/ArtOfAssembly/CH13/CH13-2.html#HEADING2-73
Noting, only 128 sectors can be accessed at a time (64K DMA limit) and that DMA can only transfer to one memory segment at a time, up to 64K but not across border. ES:BX buffer must fit into the 64K starting with ES or DMA may report error (likely # 09H). You might consider going flexible, increasing buffer to max then commenting how much is used for the special case.
Newz?
SunBow suggests displaying results at critical stages as I do.
After the call to Int 13H, examine the carry flag. This should be clear if the read is successful. AH should also be 00H and AL will be set to the number of sectors transfered.
If the carry flag is set, look at AH to determine the status in Int 13H, Function 01H.
Be aware of ECC corrected data errors (AH = 11H). In this case, AL contains the burst length. The data returned is probably good but there's a small chance the data was not corrected properly.
(Another common mistake is not remembering that the upper 2 bits of the 10-bit cylinder number are placed in the upper 2 bits of CL).
How about using Function 04H to verify the destination?
How about performing a compare of the contents of both drives after each write to confirm they are the same. This could easily be added to the code after the write portion and the results displayed on the screen.
(Another common oversight is with multi-sector transfers where the operation was terminated after the sector containing the read error).
Other than that, I'm gonna have to get my text books out.... and nobody likes to do that, do they?
After the call to Int 13H, examine the carry flag. This should be clear if the read is successful. AH should also be 00H and AL will be set to the number of sectors transfered.
If the carry flag is set, look at AH to determine the status in Int 13H, Function 01H.
Be aware of ECC corrected data errors (AH = 11H). In this case, AL contains the burst length. The data returned is probably good but there's a small chance the data was not corrected properly.
(Another common mistake is not remembering that the upper 2 bits of the 10-bit cylinder number are placed in the upper 2 bits of CL).
How about using Function 04H to verify the destination?
How about performing a compare of the contents of both drives after each write to confirm they are the same. This could easily be added to the code after the write portion and the results displayed on the screen.
(Another common oversight is with multi-sector transfers where the operation was terminated after the sector containing the read error).
Other than that, I'm gonna have to get my text books out.... and nobody likes to do that, do they?
ASKER
Dear SunBow: Thank you for your info. If you would like to
provide any additional information, my email address is:
RAYIDEA464@CS.COM
provide any additional information, my email address is:
RAYIDEA464@CS.COM