2023-04-23
This week I did some work on ldosboot, the checksumming companion repo, and lDebug.
The new checksumming stage is called checkpl. It is based on the earlier nullpl, which would just pass along control to its payload. Unlike the prior checksumming implementation, this stage is loaded as a payload by iniload, and in turn passes control to its own payload. That means it needs to be able to handle device driver and application mode entries. In turn, it also works in those modes rather than only when bootloaded.
Unlike the prior method, this checksums only part of its own payload as well as (for now) its own relocation and checksumming code. To allow debuggers to proceed past the checksumming, an int3 breakpoint is hardcoded behind the call instruction. There will probably be an option to checksum only part of the payload, without the checksumming code itself.
The reason that not the entire payload is checksummed is to allow use of a FreeDOS kernel CONFIG block early in the payload. To this end, the first 256 bytes of the checkpl stage's payload are not included in the checksum.
The checksum header format as well as the checksum
program are both unchanged from the prior revision. The inicheck
file which contains the assembly implementation of the checksumming was modified slightly to accommodate that the image to sum does not start at the checksummer's code segment, and that the checksum header is most likely not addressed with that code segment either.
For now the checksummer processes its image in 64 KiB chunks, so the di
input that indicates the segment of the checksum header needs to be calculated to match the 64 KiB chunk in which the header will be found. Likewise the offset of the checksum field needs to be calculated relative to this chunk. To allow access from the checkpl's code segment, a different label was added.
These changes are optimisations intended to reduce memory use, or address things differently to reduce utilisation of a certain segment.
The first is to discard all boot-loaded mode specific code when loading in application or device driver mode. To this end, the code in question (in boot.asm
) was moved to the end of the lDEBUG_CODE
segment. This saves about 9 kB of resident memory use when not boot loaded.
The second is to move a number of long help messages into the new "message segment". For lDebugX an additional selector is allocated to address this segment. This moves about 22 kB out of the process/data/entry/stack segment, into the new segment.
The third is to discard the ?BOOT
online help page if not in boot loaded mode. Similarly to the code change, the message was moved to the end of the "message segment" first. The message data is overwritten with a shorter message that indicates the help page is not available, requiring no changes to the resident code. This saves more than 2 kB of resident memory use.
A bugfix: The QC command to quit a device driver mode debugger after its device is already installed would fail if the debugger's sub-MCB memory block was not at the end of the container MCB.
Most of these changes are to the mktables
table generation program, with some changes to how the assembler and disassembler use these tables and very minor changes to the table source files.
mktables
changes include:
Switch to specify a different table output filename.
Switches to limit the tables to certain machine levels, most importantly 186
, 286
, and 386
.
Unused operand lists (oplists) can now be discarded by mktables
rather than including them with merely a warning message.
A new switch, nooffset
, allows to suppress the offset display comments in the oplist and mnemonic tables. This is intended to help compare the output of different runs. For now, however, the default remains to include the offsets.
Most of the prior mechanisms to support re-ordering of oplist structures were thrown out. Instead, the assembler table and mnemonic table that are built internally by mktables
now (crucially) refer to the kp→value
values directly, which reference the original position of each oplist structure in the array. Next, the merging and required re-ordering is done. Then, the "final L" value is assigned in the new order, only accounting for oplists that are in use. When the internal tables are read back to create the output file, the "final L" value is read from the structure.
The "final L" value is an index into the list of oplists, as used by the variant
macro for the assembler and in the optypes
disassembler table. The offsets are still calculated, but are used only for the offset display comments.
Other changes include that assembling a lone fs
or gs
prefix will now emit a [needs 386]
message if the assembler machine is set up as below a 386. And the build option _DISASM_32BIT
can be disabled to save a few bytes in the disassembler by dropping its support for 32-bit address size and operand size.
All the other changes to the debugger's sources are about supporting the new different table formats. The _TABLENAME
build option can be used to select a table filename other than the default debugtbl.inc
. The da23
code will work correctly even if passed a zero-length table. The existence of the MN_BSWAP
, MN_O32
, and MN_GS
defines is checked using %ifdef
to make some code conditional on whether the table includes these mnemonics.