In my previous article I showed how to make a private non-bootable
bootsector for 1.44 Mb floppy disks. Unfortunately, there was no way yet to
write that non-bootsector to a floppy disk....
Enter this code. It is the accompanying bootsector writer for floppy disks.
It assumes that your A: drive is the 1.44 Mb floppy disk drive and I dare
say that this will be true in the majority of cases.
The assembler used
As usual, I have written this code in A86 format. Until now, not many
aspects of the A86 extensions have been used, but, believe me, in future
articles this will be done.
A86 is particularly useful for people that make syntax errors. It will
insert the errormessages into the sourcefile so that you can easily find
them back. In the next assembler run the error messages are removed again.
To fully use this aspect of A86 programming, I made a small batchfile that
will let me choose between several options while writing the code. Below
you can see the file. After an error, I choose to go back into the editor.
When there are no errors, I might decided to do a trial run. Or to quit to
DOS.
This is all done by means of the WACHT command which waits for a keypress.
It returns (in errorlevel) the indexed position in the command tail table
of th key which was pressed.
Rapid assembly prototyping.
For easy processing and running sourcefiles I use a small batchfile, which
looks like:
----------- Run.Bat --------------------------------------- Start ---------
@echo off
if "%1" == "" goto leave
:start
ed %1.a86
a86 %1.a86 %2 %3 %4 %5 %6
:menu
Echo *
Echo Options:
Echo *Escape = stop
Echo * L = LIST
echo * ;-() = back to the editor
echo * space = test-run of %1.com
echo *Period = debugger-run with %1.com/sym
wacht .\=-[]';-()/":?><{}|+_LCE
if errorlevel 27 goto start
if errorlevel 26 goto screen
if errorlevel 25 goto list
if errorlevel 4 goto start
if errorlevel 3 goto debugger
if errorlevel 2 goto execute
if errorlevel 1 exit
goto menu
:execute
%1
if errorlevel 9 echo Errorlevel = 9+
if errorlevel 8 echo Errorlevel = 8
if errorlevel 7 echo Errorlevel = 7
if errorlevel 6 echo Errorlevel = 6
if errorlevel 5 echo Errorlevel = 5
if errorlevel 4 echo Errorlevel = 4
if errorlevel 3 echo Errorlevel = 3
if errorlevel 2 echo Errorlevel = 2
if errorlevel 1 echo Errorlevel = 1
goto menu
:debugger
vgamode 3
d86 %1
goto menu
:list
list
goto menu
:screen
vgamode 3
goto menu
:leave
echo No file specified
----------- Run.Bat ---------------------------------------- End ----------
This BAT file relies heavily on my computer system. For one, I use DR-DOS 6
which means that I can use the EXIT word to get out of a Batchfile.
Also, I switch videomodes back to Mode 3 with "Vgamode 3" and you will have
to use another command for that, like "Mode co80" or using the utillity
that came with your videocard.
The program "List" is Vernon Buerg's file lister which I use to track down
errors in all kinds of files.
How to write a sector to disk.
Globally there are three methods. The first would be to program the floppy
disk controller, but that is just downright difficult. A second approach
would be to use INT 026, the way DOS does things.
I chose for the BIOS method. For non-partitioned diskstructures this is the
easiest way. Just select track, head and side and write data to the sectors
on that disk.
The bootsector is the very first sector on a disk. For a floppy disk this
boils down to track 0, head 0 and sector 1 (sectors are counted from 1, not
from 0!).
The code is very straightforward. What it does is:
- reset disk drive controller
- open the file to transfer to the bootsector
- read file into internal buffer
- close the file
- repeat 5 times:
- try to tranfer buffer to bootsector of drive A:
- shut down and return to DOS.
- if an error occurs, the user is informed about it.
That's all there's to it.
The Source.
Below is the sourcecode for this short utillity. I have commented just
about any line I thought fit for it.
----------- Wrs.A86 --------------------------------------- Start ---------
name wrs
title WRite Sector
page 80, 120
stdout = 1 ; the "standard" equates
lf = 10
cr = 13
DATA segment ; define the volatile data area
buffer db 512 dup (?) ; this is enough for one sector
EVEN ; make sure WORD starts at an even address
Handle dw ? ; handle number of file to write
; ----------------------
CODE segment ; start of the actualk code
; no ORG, so we start at offset 0100
jmp main ; jump forward to entry point
db 'VeRsIoN=0.2', 0
db 'CoPyRiGhT=CopyLeft 1999, Jan Verhoeven, '
db '{
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
}', 0
; ----------------------
filename db 'BootLoad.bin', 0 ; name of file to send to disk
Mess001 db 'Cannot open file BootLoad.bin. '
db 'Operation aborted.', cr, lf
Len001 = $ - Mess001
Mess002 db 'Something went wrong while writing to disk.', cr, lf
Len002 = $ - Mess002
Mess003 db 'The floppy disk subsytem reported an error. '
db 'Trying once more.', cr, lf
Len003 = $ - Mess003
Mess004 db cr, lf, 'Bootsector written. '
db 'Thank you for using this software.'
db cr, lf, 'This program is GNU GPL free software and you use '
db 'it at your won risk.'
db cr, lf, 'Please study the GNU '
db 'General Public License for more details.', cr, lf
Len004 = $ - Mess004
; ----------------------
Error1: mov dx, offset mess001 ; process "cannot open file"
mov cx, len001
mov bx, stdout
mov ah, 040
int 021 ; print via DOS
mov ax, 04C01 ; exit with errorcode = 1
int 021
; ----------------------
Error2: mov dx, offset mess002 ; process "disk error"
mov cx, len002
mov bx, stdout
mov ah, 040
int 021 ; via DOS
mov ax, 04C02 ; exit with errorcode = 2
int 021
; ----------------------
Error2a: push ax, bx, cx, dx ; process "Disk not ready"
mov dx, offset mess003 ; point to message
mov cx, len003 ; this many bytes
mov bx, stdout ; to the console
mov ah, 040 ; do a write
int 021 ; via DOS
pop dx, cx, bx, ax ; restore state of machine
ret ; and return to caller
; ----------------------
main: mov dl, 0 ; choose drive A:
mov ah, 0 ; select funtion 0 ...
int 013 ; ... reset diskdrives
mov dx, offset filename ; point to name of file
mov ax, 03D00 ; to open
int 021 ; via DOS
jc Error1 ; if error, take action
mov [Handle], ax ; no error, => ax = handle
mov dx, offset buffer ; setup pointer, ...
mov cx, 512 ; ... byte count, ...
mov bx, ax ; ... and handle
mov ah, 03F ; to read data from file
int 021 ; via DOS
mov bx, [Handle]
mov ah, 03E
int 021 ; close this file
mov cx, 5 ; prepare for a five times LOOP
L0: push cx
mov bx, offset buffer
mov es, ds ; es:bx = buffer to read from
mov dx, 0000 ; drive A:, head 0
mov cx, 0001 ; Track 0, Sector 1
mov ax, 0301 ; Write sectors, 1 sector
int 013 ; via BIOS
jnc >L1 ; if no error, jump forward
pop cx ; Houston, we have an error!
call error2a ; inform the user
loop L0 ; and try again
jc error2 ; after five times still no go....
L1: mov dx, offset Mess004 ; Signal that we're successful
mov cx, Len004
mov bx, stdout ; to the console
mov ah, 040
int 021 ; via DOS (so it can be redirected)
mov ax, 04C00 ; mention that there were no errors
int 021 ; and return to DOS
----------- Wrs.A86 ---------------------------------------- End ----------
Have fun experimenting with bootsectors. But take care that this will NOT
work on a hard disk.
Hard disk structure.
A hard disk uses another layout for it's structure. The very first sector
of a HDD is the MBR (Master BootRecord). It is the only sensible sector in
the first track of a normal HDD. The rest is just empty.
Each partition starts at a cylinder boundary, so the first one starts at
cylinder 1 (track 1, side 0, sector 1). The very first sector of a bootable
partition is the bootsector.
The MBR contains the partition table, indicating where partitions start and
end and whether they are bootable or not. Plus some code to interpret that
table and to find the bootsector that was selected.
If you write a floppy disk bootsector to the very first sector of a HDD,
you wipe out the MBR and hence make inaccesable all data on that disk. The
data will still be there, but the system will not be able anymore to find
or use it.
So please take care that this software is NOT used for drive (DL=) 080.
{
This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
}
|