Table of Contents
Mid September work on the debugger, symbolic option, ident86
2026-09-20
Of note, I finally added three subrepos to the lDebug repo, namely lmacros, scanptab, and symsnip. This allows the makefiles to properly reference the source text files in these subrepos as dependencies.
symsnip
- Add section_of_function directives to some labels.
ETA:
- Identicalise a jump (between
-f objand-f binbuilds) by chaining to another conditional jump. (This jump's distance was close to the rel8 limit, which appears to cause differing behaviour from NASM for the two builds.)
lmacros
- Add a third parameter to lpar, which can be needframe or notneedframe. The latter doesn't define the lpar label and allows to omit the frame setup if lframe_needonlyregistered is used. This is useful for using lret with a calculated imm16 to the retn or retf instruction, but without accessing the frame at any point. Used for the restore_scratchsel shim function for _PM=0 builds.
lDebug (experimental)
- Update attribution year of loadeld.asm
- Fix Z LIST sense for hiding linear address's h suffix (hide for Z LIST ADD, show otherwise).
- In Z LIST list the upper byte of smFlags (if nonzero).
- Speed up zero-init of XMS symbol table, particularly in Protected Mode. Previous code wrote 16 bytes at a time, so more than 128 Ki calls were needed to init the full Z /S=MAX table (ca 2 MiB + 64 KiB). Now, after the first two 16 Bytes steps the step size doubles for every write, so there's much fewer total steps possible. (XMS moves always either preserve the source data in the destination or fail the call on overlapping source and destination ranges. So we can't init one small part then copy it with RLE-style overlap to init the entire block at once.)
- Update OUT protocol comment of dd_store, it doesn't write a blank any longer. (Didn't since before dx.eld was created, in fact. ETA: Didn't since 2020-04-03 when the DB/DW/DD commands were first introduced.)
- Use include files from subrepos.
- Add debugger links for new ELD, dxms.eld (Dump XMS memory).
- Set the zz_no_pm_xms flag by default even for _SYMBOLIC=0 debugger, to prepare for its use by dxms.eld (The flag is needed because dosemu2's Protected Mode XMS entrypoint doesn't appear to work.)
- Add new Extension for lDebug, dxms.eld (Dump XMS memory). During testing, I found that the autorepeat of this command works even if the ELD isn't installed residently. This questionable "feature" is not disabled yet, but it does suggest more consideration. Typically a non-resident ELD is considered stale once cmd3 is entered. (This ELD was used to validate the symbolic XMS init change added earlier.)
- Harden the stack_check.internal function so a too large value in AX will return CY.
- Re-order extseg variables to prepare for ELD support in dualret_helper. Technically this isn't required, extseg and extcssel just need to be consecutive and
extseg - code_segneeds to be below 256. But it is neater this way. - Do not align the LINKCALL entrypoints, saving a few bytes.
- Add dualcall support to LINKCALL, needs about 90h bytes now rather than 80h.
- Fix the sense of symbolasm_error equate conditional in debug.asm
- Drop support for dual2call possibly being near despite a far dualcall. Now dual2call is always an alias of dualcall.
- Add support for dualcall code links to the link info tables. This uses one of the two previously reserved words in the link table header structure. As we can depend on this always being zero for prior revisions, it doesn't require a new incompatible table format. Similar to the ELD header, the new use of this word is as the length of the table including extensions. So additional future extensions could also indicate their presence using this same word in a compatible way.
- Add support for dualcall calls to the Extensions for lDebug linker, and the ELD code macros. (This worked as intended immediately, except for the dualcall mmacro at first adding to the wrong relocations list smacro previously prepared for a separate table. The actual implementation re-uses the same table, but sets a new flag to indicate that a dualcall is being linked rather than an extcall. This allows almost completely re-using the linker's code for extcall code links to implement dualcall code links.)
- Add section_of directives for various functions, including symbolic ones.
- Add section_of_function directives to some labels.
- Add two test Extensions for lDebug, using dualcall macros.
- Re-use part of the ELD_INSTANCE structure to hold LINKCALL code. The last field, 14 bytes reserved for eldiListing, is never used for LINKCALL so there is little reason not to re-use it. The first byte is always a NUL byte so even if someone were to read it they'd find an empty string. This allows the LINKCALL ELD to fit in 80h bytes again, and places the cmd3 entrypoint at offset 0079h again.
- Harden the duallink_return_error entry to set UP and reset the segments to point to SS.
- Add notneedframe lpar parameter to the lmacros2.mac macro file.
- Make push_if, pop_if, save_scratchsel, and restore_scratchsel functions dual functions. Add shims for _PM=0 builds that only include the 86 Mode code for these.
- Add another test ELD to test the new dualcall functions.
- Add _doscall_return_es dualcall links, if dual2distance equals dualdistance (always now).
- Add new test ELD to call _doscall_return_es
- Use dualcall invocations for some existing ELDs (co.eld, dpb.eld, dxms.eld, enamelib.eld).
- Fix some manual references to the ELD linker, "eldlink.eld" is not itself an ELD that exists.
- Update and add Error Return Codes used by dxms.eld
- Document ELD dualcall macros, code, and tables.
- More exactly word a reference to the debugger's /Y switch in the manual to indicate the debugger must be started with it.
- Fix the ..@hh_readmem sectioning directives. (Hint: Possibly add a check to section_of that a prior section_of didn't declare a conflicting section?)
- In the assembler tables don't use __SECT__ to restore a section, as this clashes with the trace listing file generation. The problem is that __SECT__ never emits a section change
%note, so it would make the listing conversion script believe it was in a different section. As the __SECT__ uses always were to the same section (ASMTABLE1) anyway, just replace them by explicit references to this section. Identicalised change.
ETA:
- Add alignment for the lDEBUG_DATA_ENTRY section for
-f binbuild. This is the same change as done on 2026-03-10 to several files during the-f objbuild work. It is needed because under-f obj, the highest alignment within a segpart will align the entire segpart, so if some subsequent data is aligned eg usingalign 16, then the beginning of the segpart is aligned just as much. To simulate this in the-f bin_LINK_COMPAT build, an explicit alignment directive has to be added. - Similarly, add alignment for lDEBUG_CODE2.
- Add the chain jump change to symsnip as a commit of the subrepo state.
- Address the stack explicitly if _LINK_COMPAT, as the optimisation of depending on ..@init_behind == stack only worked in
-f bin. I reported to NASM that this comparison should perhaps cause a warning, as it isn't very meaningful to compare two extern labels in an%ifstatement.
ident86
I'm working on the identicalisation program to help on comparing the -f bin and -f obj builds of lDebug. The dualcall and nearcall mmacros need to handle their trailing word as word-sized data rather than instructions. Long dispatch tables need to handle their data as words even if the first difference in a range happens to fall in the continued machine code dump line (so that the found offset points to this continued line rather than the first line).
ETA:
- Optimise matchsize performance by returning early if a directive has been matched.
- First revision of detecting long call mmacro directives (nearcall, dualcall, extcall) as disassembly except for a word data field at the end. This severely complicated the matchsize function, which needs to input an amount and return a tuple now, giving the size/type detected as well as an adjust value in case of a long call. (Hint: Exactly 5 bytes could be a far imm16:imm16 call? So better do not detect as a long call then?)
- Update some debugging output that used to use matchdata variable, which is now confined to the matchsize function.
- If there's no tls directive corresponding to the beginning of a disassembly run, invent one with the most recent found size. Not sure this is correct but oh well. It does appear to work.
- Fix: Avoid parens around a string used for % formatting, as this appears to be unsupported.
- Set the priortlssize variable to the foundtuplesizes tuple element. Another take on getting partial dumps into an acceptable format.
- Add tls directives from the earlier loop (which is mainly to detect instruction boundaries) and handle a nonzero matchedadj return (ie, long call mmacro where first difference is in the data word rather than in the instruction).
- Treat extcallcall as an alternative long call mmacro. Used by some sources that are shared between debugger and Extensions for lDebug.
- Rework the dump and newdump uses in the two loops (instruction boundary loop, subsequent tls directive gather loop).
- Fix to some of the above, treat long call instructions before the word data as instructions to disassemble (type 'u').
- Same fix to the other loop.
- Add debugging display of disassemble function parameters.
- Magic code that sets the start variable correctly.
- Prior magic change was so poorly understood it pessimised the usual case where firstdifference doesn't match any exact startnew or startold. Fix this to always set start. It is set from startnew if neither startnew nor startold exactly match firstdifference. Also adds the start value to debugging output.
- Optimise (as much as 50% time saved), always break upon first found = 1 case. This optimisation was likely intended much earlier. The conditions to reach found = 1 already read as follows:
if firstdifference - int(args.offset, 0) >= newoffset_line + newamount:
continue
if newoffset_line > firstdifference - int(args.offset, 0):
continue
This only falls through if firstdifference is below the end of this machine code dump and above-or-equal the beginning of this machine code dump. Assuming a well-formed trace listing file, a more exact match will not be found later on, so the search might as well stop here.
Privately, I have indicated that I don't always understand ident86 intricacies. I've likened this to "vibe coding" minus the generative AI, going by my own vibes. Someone suggested calling this "evolutionary coding", with "no idea of what you're doing, just testing if it works and moving on". I'm not proud of that but as long as my attempts aren't futile permanently, it does get the job done.
