2022-11-13
The optimisations of ldosboot continue, although I previously considered it impossible to optimise further.
First, iniload saved a few bytes by falling through in .int13_retry to re-use the .int13_preserve_lpcount code instead of calling it then doing retn
.
Next, the FAT16 boot sector loader will pass the FAT buffer segment into the variable used by iniload at a later point where it is already materialised into a register, saving two bytes previously used for the immediate operand.
Further, the minimum file size for the lDOS protocol has been increased from 1536 (600h) bytes to 4096 (1000h) bytes. This saves a byte in the FAT12 and FAT16 loaders because they can compare just bh
(to 3) instead of bx
(to 300h), where previously the full bx
comparison (to 260h) was needed.
In iniload we optimised the MS6/IBMDOS and MS7 entrypoints a bit, shuffling some code and re-using the zero cx
already initialised for MS6/IBMDOS. Another optimisation was not to load from cs
for the load segment calculation when it is known to contain a constant 70h.
Previously, ldosboot shipped a patch.sld (Script for lDebug) file that would find and directly patch one of three code sequences in iniload to force use of CHS access or to not query CHS geometry using service 13.08.
Apart from some smaller updates to this old style patch facility, the query patch handling was added. This adds some code with a recognisable magic byte sequence to iniload, which will initialise register al
with some flags. The patch sequence actually initialises ax
, but depending on whether the load unit is a diskette or a hard disk (ie, depending on the sign bit) one of the two bytes is written to al
and thereafter only al
is used.
The query patch support allows to do both patches that were done with the old style patches (force CHS access, do not query CHS geometry), as well as a third patch: Force LBA access.
Theoretically there are 5 unused bits to be patched, but it seems unlikely that those will be put to use, at least not early during iniload's operation. The 1536 bytes limit of the initial lDOS, MS6, and IBMDOS load protocols is nearly fully utilised and does not allow any more features.
The patch.sld script was adapted to allow new style patches. lDebug also gained its /F switch and an associated DCO6 option in order to load files as flat format binaries even if (like iniload) they contain an MZ executable header. For normal (FreeDOS load protocol enabled) iniload files this allows offline patching using patch.sld, rather than online within bootable lDebug. (If arbitrary data is appended and this makes the file exceed the available memory size then it both cannot be loaded with ldebug /f
and also cannot be used with the FreeDOS load protocol.)
During and after writing the article comparing bootable lDebug to the Debug/X variant DebugB, I updated the ldosboot documentation and also uploaded it to the pushbx.org/ecm/doc/ directory. This file documents the lDOS load protocol (sector to iniload) as well as the internal iniload to kernel image protocol.
I added descriptions of the reserved memory top area, the lDbC signature of lCDebug, the fact that the FreeDOS load protocol was extended to allow an lDOS style kernel command line, and the expectation that the passed boot sector should contain an ASCII-only SFN in blank-padded FCB format to indicate the kernel filename.
The new 4096 bytes minimum file size of iniload that supports the FAT12/FAT16 loader optimisation is also documented now. Finally, the new query patch implementation is documented as well.
Just today I've been working on a few more patches to ldosboot:
First, an _LBA_SKIP_ANY option which makes it so that any error (regardless ah
return value, CY or CF unchanged) from the LBA read sector function will cause the code to attempt a CHS read.
Second, the option _CHECK_ATTRIB to boot.asm, making its directory search insure not to match directories or volume labels (or LFN entries). (The FAT32 FSIBOOT's dirsearch function already includes this check unconditionally.)
Third, some shuffling of code and leaving some words on the stack in order to reduce the size needed for the attributes check from 7 bytes to 6 bytes. (However, for the MS6 and IBMDOS protocols this appears to require one byte more instead.) This is still in progress, but I hope to finish it today.
With the byte saved from the shuffling, we can enable the attribute check and even insert a stc
before the 13.42 call and just so fill the FAT12 and FAT16 loaders up to capacity (0 bytes left free) with the lDOS load protocol.
There's one more change that by design does not affect the build, but it increases quality of life for developers: lDebug's makinst.sh script will now utilise the mktmpinc.pl script, if found, to improve the listing files created for ldosboot's FAT12 and FAT16 loaders, that is boot.asm.
This feature allows to read the original source, including blanks and comments, for the read_sector and error functions alongside the listing of what machine code this source assembles to. This was broken previously by putting these functions into macros, to allow re-ordering their placement in the source file without editing the file or having to duplicate all of the code. NASM's multi-line macros, if listed, will collapse all blanks and strip comments in the listing part that shows the machine code. While the macro's definition can be listed too, and will include the blanks and comments, this listing does not include the machine code.
This change should be propagated to the ldosboot/test/test.sh script as well, as that also assembles boot.asm with a listing.
Another odd bit is that boot.asm appears to allow multiple protocol specifications while boot32.asm prohibits them.