Table of Contents

lDebug and ldosboot changes

2023-03-05

The file I am currently writing is blog26.txt, the 26th blog entry that I am writing on the HP 95LX.

lDebug changes

The MMX support of the debugger was severely lacking. The RM command was broken ever since the auxiliary buffer had been moved to its own segment, which is many years ago. The expression evaluator read of an MMX register's half was broken since the data code split in 2019. Fixing it required to load the code section's segment to do its SMC patch, plus in Protected Mode lDebugX needs to set up a writable data selector rather than using the code selector (which isn't writable). Finally, the R command simply rejected any MMX register write as being to a read-only variable, not supporting the special return values from isvariable? that also had been defined for a long time already.

All of these deficits were fixed. Additionally, lDebugX can now re-detect MMX support whenever it switches modes between Protected Mode and Real/Virtual 86 Mode. This is important because dosemu2 on the server does not support MMX when running in 86 Mode (without KVM or V86M supported by the host), but does support it when running in Protected Mode with native DPMI enabled. Previously I would enter PM then patch the MMX flag to nonzero manually, but that was more work of course.

More changes include the IF EXISTS R variable THEN construct which tries to parse a variable (using isvariable?) and will run the following command depending on the result. Some changes were made to the internals of isvariable? so that some invalid constructs will return with CY from the function call instead of jumping to the error handler. The most difficult part, however, was to decide how to skip past a candidate variable name if the parsing has failed. That is necessary to parse the THEN in that case, and also to run the command if NOT is specified to the IF. Eventually it was decided to skip until a comma, blank, or EOL is reached, except for potential index expressions in parentheses (…) which are skipped by parsing them with getexpression.

As an aside, the MMX register read support allows to specify the register number either as a single digit from 0 to 7, or as a digit enclosed in parentheses. However, this is not an index expression, as it doesn't use the expression evaluator. I decided not to document the parenthetical case for now until I decide what is to be done about this.

During the MMX adventures I also came up with an easy way to save about 400 bytes in the first code section. This was done by moving all of the code in fptostr.asm into the second code section if dual code is enabled. There is only a single function in that file which is called from elsewhere (in rr.asm), which was easily converted to a dual-callable function.

Last, I changed the MMX register dump RM command so it accepts an optional size keyword, which can be BYTES, WORDS, DWORDS, or QWORDS. The default behaviour is preserved, which matches the BYTES keyword: Dump the 64-bit MMX register contents as if byte-wise dumping memory, the least-significant byte first. The larger sizes will dump larger items instead. As a side-effect, the QWORDS size keyword can be used in range parameters' lengths as well as in VALUE … IN construct value or match ranges like FROM … LENGTH now as well.

lDOS boot loader changes

A number of optimisation refactorings were done on the lDOS boot loaders, mostly the initial loader (iniload). By refactoring I mean that the behaviour should not have changed from these edits at all.

It was documented that the incoming bp register value should be even for iniload prior to 2023-March. This is to avoid the possibility of accessing a word at offset FFFFh during the use of movsw and lodsw to load and check for a command line. Such an access would cause a General Protection Fault in a typically set up 86 Mode environment on a 286+ machine. (In V86M the VMM would receive the GPF, in R86M an interrupt 0Dh call would occur.)

A non-refactoring change was to check for a minimum value of the incoming bp before loading the candidate command line. This eliminates the potential GPF, as the pointer arithmetic cannot underflow below offset zero if bp is large enough. Some optimisations and a bit of further spaghettification were required to make space for this new check.

One of the refactorings was to change the definition and use of clust_to_first_sector in iniload so as to eliminate one of its outputs and instead have it output the adjusted sectors per cluster (spc) value. This also meant that the spc is loaded into a register only once in this function, and the register is read twice and then returned as an output as well. This optimisation is a 1-to-1 copy from boot32.asm where it had been applied a while ago.

Another refactoring was for clust_next to read its input from the dx:ax register pair instead of another. This optimisation was actually applicable to both iniload and boot32 as well, but had not yet been discovered for boot32 prior to now.

All the other changes are simpler refactorings. Refer to the ldosboot repo for details.

Additional information

The MMX register returns for isvariable? had been present all the way back to the initial commit on 2010-10-24.

The auxiliary buffer was moved to its own segment on 2018-10-17.

The data-code-split branch was merged into the default branch on 2019-06-09.

The dosemu2 file src/base/core/int.c returns the dumb mode flag on DOS_HELPER_GET_TERM_TYPE (interrupt E6h function 0x0055) since 2021-03-03. I was pointed to this in a bug report about a FreeCOM display problem which ended up addressing several different issues.