2

Let's say I have built an assembly program (a basic print), so I have got a .BIN file.
Now I want to make it a bootable floppy disc image (a virtual one), so that when I start an OS (in the vm), it will first execute the assembly instructions from my program which is located on that virtual floppy disc.
How to do that correctly?

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
Radu Aramă
  • 195
  • 1
  • 1
  • 10
  • 1
    Related on SE Retrocomputing [What makes a floppy disk bootable?](https://retrocomputing.stackexchange.com/questions/5251/what-makes-a-floppy-disk-bootable/5253) – Weather Vane Nov 18 '21 at 09:07
  • 2
    @ecm In your answer you wrote: "The register `bl` receives the ROM-BIOS unit you were booted from" I wonder, is `bl` a typo or did you purposely not want to use `DL` like BIOS normally has. Sorry for not commenting below your answer, but sometimes my browser just puts the answer window on top of other stuff. I was not able to click "Add comment". – Sep Roland Nov 23 '21 at 19:19
  • 2
    @Sep Roland: `bl` is not actually a typo! The FreeDOS load protocol (transferring from boot sector loader to the kernel file, also implemented by eg dosemu2, GRUB, and my bootable debugger) does differ in this from the ROM-BIOS to MBR / boot sector protocol, and likewise the MBR to partition boot sector protocol. And of course most boot sector loader to load file protocols. (My own lDOS protocol only passes the load unit in the BPB pointed to by `ss:bp` either in the FAT32 EBPB new fields or the FAT12/16 BPB new fields. In practice FreeDOS's load protocol also provides this.) Links tba. – ecm Nov 23 '21 at 19:31
  • 2
    @Sep Roland: Here's [the point at which the FreeDOS kernel's FAT12 / FAT16 loader](https://github.com/FDOS/kernel/blob/571cf111113e89cfb1a3a517688eb56ad1f2f1f7/boot/boot.asm#L359) transfers to the kernel. This one sets both `dl` and `bl`. Here [the FAT32 CHS loader](https://github.com/FDOS/kernel/blob/571cf111113e89cfb1a3a517688eb56ad1f2f1f7/boot/boot32.asm#L272) (which does not return the same value in `dl`), and here [the FAT32 LBA 386+ loader](https://github.com/FDOS/kernel/blob/571cf111113e89cfb1a3a517688eb56ad1f2f1f7/boot/boot32lb.asm#L241) (likewise does not set `dl` to the unit). – ecm Nov 23 '21 at 19:32
  • @ecm Thanks for the quick response. Nice to see that it wasn't a typo. – Sep Roland Nov 23 '21 at 19:36
  • @Sep Roland: I added to the answer. Also, I checked and my own loaders do not set `dl`, not even incidentally, if the build define `_SET_DL_UNIT` is zero. In `boot32.asm` the FSIBOOT [transfers control back here](https://hg.pushbx.org/ecm/ldosboot/file/07f4ba0ef8cd/boot32.asm#l1524) where `read_sector` or `clust_next` last set `dx`. In `boot.asm` the `dx` register [likewise holds a sector number](https://hg.pushbx.org/ecm/ldosboot/file/07f4ba0ef8cd/boot.asm#l1663). Only the debugger [always sets](https://hg.pushbx.org/ecm/ldebug/file/5019aab4a254/source/boot.asm#l2332) `dl`. – ecm Nov 23 '21 at 19:59

1 Answers1

2

You can use my boot sector loaders (ldosboot boot.asm for FAT12 / FAT16 FS) and my boot image creation script to make a 1440 KiB file system image preloaded with your kernel executable and a loader in the first sector. You'll also need my macro collection. Here's an example shell session to clone the repos and build an image. This is using hg (Mercurial) to load the repos, wget to get a release of my debugger as an example program, Info-ZIP's unzip to unpack it, NASM to assemble the loader and image, and qemu to run everything once assembled.

$ hg clone https://hg.pushbx.org/ecm/lmacros
destination directory: lmacros
requesting all changes
adding changesets
adding manifests
adding file changes
added 143 changesets with 171 changes to 38 files
new changesets 3a982025dd94:323cc150061e
updating to branch default
29 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone https://hg.pushbx.org/ecm/ldosboot
destination directory: ldosboot
requesting all changes
adding changesets
adding manifests
adding file changes
added 588 changesets with 650 changes to 15 files (+2 heads)
new changesets 13cf6bb0b5f5:07f4ba0ef8cd
updating to branch default
15 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg clone https://hg.pushbx.org/ecm/bootimg
destination directory: bootimg
requesting all changes
adding changesets
adding manifests
adding file changes
added 88 changesets with 88 changes to 1 files
new changesets 966f8a094eca:fa44558212e7
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ wget https://pushbx.org/ecm/download/ldebug.zip
--2021-11-18 13:05:18--  https://pushbx.org/ecm/download/ldebug.zip
Resolving pushbx.org (pushbx.org)... 2a01:488:66:1000:b01c:1258:0:1, 176.28.18.88
Connecting to pushbx.org (pushbx.org)|2a01:488:66:1000:b01c:1258:0:1|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7131575 (6.8M) [application/zip]
Saving to: 'ldebug.zip'

ldebug.zip           100%[=====================>]   6.80M  --.-KB/s    in 0.03s

2021-11-18 13:05:18 (259 MB/s) - 'ldebug.zip' saved [7131575/7131575]

$ unzip ldebug.zip bin/ldebugu.com
Archive:  ldebug.zip
  inflating: bin/ldebugu.com
$ nasm -I lmacros/ -I ldosboot/ ldosboot/boot.asm -D_COMPAT_FREEDOS -D_QUERY_GEOMETRY=0 -D_LBA=0 -D_USE_PART_INFO=0 -o boot.bin
ldosboot/boot.asm:420: warning: Possibly crossing 64 KiB boundary while reading file (sector size >= 1024) [-w+user]
ldosboot/boot.asm:1851: warning: FAT12: 18 bytes still available. [-w+user]
$ nasm -I lmacros/ -I bootimg/ bootimg/bootimg.asm -D_BOOTFILE="'boot.bin'" -D_PAYLOADFILE="::rename,'bin/ldebugu.com','KERNEL.SYS'" -o diskette.img
$ qemu-system-i386 -fda diskette.img -boot order=a -curses

The documentation for bootimg is in a comment at the top of the main source file. I used the _BOOTFILE define (set to a twice quoted string so NASM receives a quoted string) to indicate a boot sector file, and the main _PAYLOADFILE define to specify inclusion of the debugger executable, renaming it to KERNEL.SYS so that the default name used by the _COMPAT_FREEDOS loader will find our executable.

Aside from the FreeDOS compatibility selection, boot.asm needs some additional switches to disable features not needed to boot a 1440 KiB diskette image. This is because the FreeDOS compatible loader needs more space than my (lDOS) default.

Finally, the file that you specify to be loaded (either a default like KERNEL.SYS or one in a filename specified using the boot.asm defines _LOAD_NAME and _LOAD_EXT) needs to be in the correct format. The FreeDOS load protocol is fairly simple: Your entire file is loaded to address 600h, addressable using the segmented address 60h:0, and cs:ip are set up exactly as 60h:0. The register bl receives the ROM-BIOS unit you were booted from and ss:bp points to a copy of the FS's boot sector somewhere in memory. All other registers, particularly the segment registers, are indeterminate and must be initialised by your code if you want to use them.

Note that the FreeDOS load protocol differs from most other load protocols at this level in that bl is set to the load unit. Depending on which loader is used dl may differ from bl in which case bl is correct, and dl incorrect. The load unit can also be found in the boot sector copy pointed to by ss:bp, either in byte [ss:bp + 40h] for FAT32 or byte [ss:bp + 24h] for FAT12 and FAT16.

ecm
  • 2,583
  • 4
  • 21
  • 29