\cfg{chapter}{Section}

\cfg{text-filename}{ldebug.txt}
\cfg{text-chapter-numeric}{true}
\cfg{text-indent-preamble}{false}
\cfg{text-quotes}{"}{"}
\cfg{text-indent}{4}
\cfg{text-width}{72}

\cfg{html-chapter-numeric}{true}
\cfg{html-suppress-address}{true}
\cfg{html-single-filename}{ldebug.htm}
\cfg{html-leaf-level}{0}
\cfg{html-template-fragment}{%k}{%b}
\cfg{html-head-end}{<meta name="viewport" content="width=device-width, initial-scale=1.0">}
\cfg{html-leaf-contains-contents}{true}

\cfg{pdf-filename}{ldebug.pdf}

\cfg{ps-filename}{ldebug.ps}

\cfg{info-filename}{ldebug.info}

\cfg{chm-filename}{ldebug.chm}

\cfg{winhelp-filename}{ldebug.hlp}

\cfg{man-filename}{ldebug.7}
\cfg{man-identity}{ldebug}{7}{2020}{}{C. Masloch}

\title lDebug manual

\copyright 2020 by C. Masloch.
Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.
DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

This document has been compiled on \date{%Y-%m-%d}.


\C{overview} Overview and highlights

lDebug is a 86-DOS debugger based on the MS-DOS Debug clone FreeDOS Debug.
It features DPMI client support for 32-bit and 16-bit segments,
a 686-level assembler and disassembler, an expression evaluator,
an InDOS and a bootloaded mode, script file reading, serial port I/O,
permanent breakpoints, conditional tracing, buffered tracing,
and auto-repetition of some commands.
There is also a symbolic debugging branch being developed.


\C{news} News

\# \H{news-r5} Release 5 (future)


\H{news-r4} Release 4 (2022-03-08)

\b Recognise LF as linebreak in serial input

\b E interactive mode fixes:

\lcont{

\b Support LF to exit interactive mode
(that is, accept Linux style linebreaks)

\b Support DEL sent by serial terminal

\b In lDebugX correctly handle 32-bit offsets

\b Also write new value when minus is entered

\b Honour blank for continue to next byte,
CR or dot for exit interactive mode

\b Always correctly read value
even if blank is entered afterwards

\b Improve E interactive mode compatibility
across different input sources
(like stdin file, script file, serial terminal)

\b Display linebreak upon new address displayed

}

\b Fix: Register variable \cq{CH} would be misparsed as
\cq{CHAR} type instead of the expected variable

\b Allow DI command to receive an IN value list
similar to the y in a VALUE x IN y construct

\b Fix: Allow to set a breakpoint on an interrupt 21h handler
and do not crash or corrupt state if the debuggee then terminates.
(That is, do not call service 4Dh before restoring breakpoints.)

\b Fix: Too long N command could crash the debugger

\b Fix: DDebug TSR quit would not work correctly
due to overflowing a rel8 \cw{jmp}

\b Add R, M, and L key letters to DI command
(always 86 Mode, show MCB names, follow AMIS interrupt lists)

\b Fix: \cw{R WORD [memory]} prompt would not consider the size keyword
as part of the input line prompt

\b Add AMIS private function 30h - Update IISP Header

\b In DI command in 86 Mode follow IISP headers

\b Add \cw{QQCODE} variable

\b Add \cw{BOOT[L|Y|S][UNIT|PART]} variables, \cw{BOOTUNITFL(x)} variables

\b Add bzpack compression method

\b Drop DPS variable when building without DPMI support

\b Fix PSP variables in Protected Mode:
PSP is always a 86 Mode segment,
PSPS is a segment or selector,
and PPR and PPI work

\b Add \cw{HHRESULT} variable


\H{news-r3} Release 3 (2021-08-15)

\b Add workaround with extra int 23h and int 22h handlers
and raw mode-switching
to use interrupt 21h service 0Ah in PM.
DCO2 flag 800h clear by default.

\b Add TRYAMISNUM variable to try a specific AMIS multiplex number first

\b Add DCO4 flag 2 to allow disabling lDebugX's int 2Fh hook

\b Build option \cw{_MEMREF_AMOUNT} enabled by default

\b mktables switches \cw{direction} and \cw{stackhinting}
enabled by default

\b Fix DOS application script file reading
to honour InDOS status

\b Fix H BASE= command with GROUP=
sometimes displaying trailing garbage

\b Fix DDebugX hooking random PM interrupts

\b Fix trailing blanks in DI command

\b Added a number of automated acceptance tests

\b Add variable \cw{AMISNUM} to read the multiplex number

\b Fix an old bug in the assembler that happened to make
instructions like \cq{mov ax, 0} fail to assemble now

\b Made interrupt 8 hook optional, default-off

\b Added optional, default-off interrupt 2Dh hook

\b Properly unhook interrupts utilising IISP header chains,
if the debugger's interrupt handlers are reachable.
Added DCO4 flags (upper 16 bits) to force unhooking
if a handler is unreachable.
If a handler is both unreachable and not forcibly unhooked
then it stays hooked. The Q command fails in that case.

\b Fix to allow \cq{$} prefix to segments in DebugX
while in Real/Virtual 86 Mode

\b Debugger's 86 Mode entrypoints now use
the IBM Interrupt Sharing Protocol header.
(However, it is still assumed that the debugger
\e{owns} the interrupt entrypoints.)

\b Add \cw{WIDTH=} keyword handling to \cw{H BASE=}

\b Introduce variables IOL and IOF to control
how many levels of execution are cancelled by Control-C

\b Scripts with CR LF linebreaks
at the end or after calling another script
no longer cause superfluous empty lines to be processed

\b Control-C aborts script file reading that is in progress

\b Bugfix, when calling three nested levels of Y script files
while bootloaded then
the outermost script's already buffered content
would not rewind properly

\b Fix so that Control-C from ROM-BIOS keypress buffer
is consumed properly while reading script file,
instead of looping forever

\b Check for Control-C in ROM-BIOS's circular keypress buffer,
add variables IOS and IOE

\b Extend Control-C handling so RE buffer execution is aborted by it

\b Add a simple \cw{BOOT DIR} command
(SFN name only, attributes, size (using FAT+), datetime)

\b Add string literals \cw{#"..."} to expression evaluator

\b Add \cw{H BASE=} command

\b Add \cw{merge} and \cw{debug} switches to mktables.
Both are default off for now.
Merging means redundant operand list tails are merged.

\b Bugfix, accessing the variable SRC caused an infinite loop

\b LZMA-lzip depacker fixed to not use \cw{cs xlatb},
as the segment override prefix may be ignored on CPUs below 386

\b Added conditional \cw{?? ::} construct operator

\b Merged branch \cw{uumemref} and made memrefs available in default branch.
The build option \cw{_MEMREF_AMOUNT} must be enabled to use them.

\b Memory access direction and stack hinting
in the assembler and disassembler tables.
Switches named \cw{direction} and \cw{stackhinting} to mktables program.
(Default off for now.)

\b LINEAR term allowed in expressions

\b VALUE IN construct allowed in expressions

\b Commas are only allowed between expressions,
no longer within expressions

\b If DCO2 flag 8000h is set during RE buffer execution
and SILENT 1 was used do actually only display last RE output


\H{news-r2} Release 2 (2021-05-05)

\b Documented SLEEP command

\b Line editing history for raw terminal/serial input
(in a fixed segment of size 8 KiB currently)

\b Fix missing register dump after T/TP/P
which ends up matching a non-pass non-hit breakpoint

\b Fix: Entering a literal as 3#102002022201221111211
or #4294967296
would overflow silently to zero instead of causing an error

\b Reset high words of EIP and ESP when trying to terminate client process

\b Add change highlighting to R register dump

\b Assembler internals: Allow ASM_ESCAPE usage when needed

\b If BL command is given an unused index do not display incorrect WHEN

\b Reset segment registers when trying to terminate client process

\b Handle unusual SIB bytes correctly in P command's disassembly

\b Bugfix, Y script file called by another Y script file would turn quiet

\b Bugfix, if permanent breakpoint WHEN condition was in use
then the wrong index and ID would be displayed in the pass/hit message

\b Acknowledge IRQ to secondary PIC too if applicable
(if using a high IRQ for the serial I/O interrupt)

\b Bugfix, in BOOT commands do not prepend a word to the auxbuff anymore

\b Only create manual in HTML, text, and PDF formats

\b Add files doc/fdbuild.txt and doc/LDEBUG.LSM for FreeDOS packages

\b BOOT: work around qemu bug with \cq{LOOPNZ}

\b BOOT: retry CHS reads up to 16 times

\b Add instsect and lDebug command help to manual

\b Expression evaluator allows \cq{OR=} as synonym for \cq{|=}
(especially useful if shell does not allow specifying pipe symbol for /C)

\b Assembler: Allow specifying \cq{LOOPxx destination, (E)CX}
as in NASM instruction reference to specify address size

\b For assembler allow specifying \cq{INT BYTE 3} to get CDh encoding
and display it this way in disassembler

\b Only adjust offset saved in PSP's SPSAV variable if it points to our stack

\b In assembler do not allow sizeless memory operand
when immediate matches IMMS8 (eg \cq{add [100], 12})


\H{news-r1} Release 1 (2021-02-15) and earlier

\b \cq{G REMEMBER} command to work with the saved temporary breakpoint list

\b WHEN conditions for permanent breakpoints

\b RIxxO/S/L variables (read-only view of IVT entry)

\b 3BYTE type for \cq{R var} and indirection in expression evaluator

\b In disassembler handle unusual SIB byte contents correctly

\b IDs for listing permanent breakpoints

\b In disassembler correctly dump far memory operands,
double memory operands (BOUND), and do a32 addressing

\b Add \cq{S range REVERSE} command

\b Fix corner case of S command:
The commands \cq{f 100 l 10 0} \\ \cq{s 100 l 10 0}
should result in 16 matches

\b SROx and SRC search result variables

\b SLEEP command

\b H command displays decimal numeric value (when given a single expression)

\b In disassembler display WORD keyword when o16 in 32-bit CS

\b Bugfix, in XR do not skip first digit of allocation size

\b G and T/TP/P breakpoints work reliably in DebugX
when the client enters, leaves, or switches from/to Protected Mode

\b F and S command allow accepting \cq{RANGE} specifications for source data

\b Add TTC/TPC/PPC default step counts for T/TP/P commands

\b DW/DD commands to dump memory in words or doublewords

\b Manual added (this document)

\b RE buffer execution to run almost arbitrary commands
when T/TP/P/G intend to dump register contents

\b Conditional control flow with IF and GOTO in a script file

\b /C command line option to pass commands to the debugger on startup

\b In assembler allow specifying SHORT/NEAR/FAR for jumps and calls

\b Script file reading

\b Pass point functionality (inspired by DR-DOS's SID) using counters

\b G LIST command to list the saved temporary breakpoint list

\b Auto-repetition for G command, G AGAIN command

\b DebugX's DPMI entrypoint hooking automatically checked
instead of always avoiding it on MSW and dosemu

\b Serial port I/O, with defaults (for COM2) that
can be reconfigured using debugger variables

\b Permanent breakpoints

\b Buffered tracing using \cq{P/TP/T ... SILENT}
which writes to an internal buffer during the run
then replays the last entries from it upon finishing the run

\b TP command which is like T except it
handles repeated string operations like P

\b DM command lists MCB sizes in decimal Bytes/KiB

\b Conditional tracing using \cq{P/TP/T ... WHILE} conditions

\b L and W commands allow drive letters instead of numbers

\b Bootloaded mode and its BOOT commands

\b NASM style address disassembly, blanks after commas, keywords uncapitalised

\b TSR mode and command to enter it

\b R command allows treating flags (CF, ZF, etc), debugger variables,
registers, and memory variables (byte, word, 3byte, dword) as variables

\b Conditional "jumping" and "not jumping" notices
in register dump's single-line disassembly

\b Options DCO1, DCO2, DCO3, DAO to modify some behaviour

\b Extended online help pages

\b _DEBUG option which swaps the exception handlers and
thus allows debugging most of the debugger itself
(_DEBUG builds are not included in the package
and have to be created by building them specifically)

\b Arbitrary unsigned 32-bit expression evaluator

\b Paging for long command output

\b Usage conditions changed to Fair License
(having asked Paul Vojta and received his confirmation),
prior conditions also allowed as alternatives


\C{building} Building the debugger

Building lDebug is not supported on conventional DOS-like systems.
(DJGPP environments may suffice but are not tested.)


\H{buildingcomponents} Components for building

The following components are required to build with the provided scripts:

\b bash - to run mak* scripts

\b perl - to patch binaries (overwrite unused revision IDs)

\b grep - to detect whether boot loading is in use, and to export variables

\b sed - to filter dosemu2 output

\b hg (Mercurial) - to retrieve revision IDs

\b python - to run hg and to run the test suite

\b C compiler - to compile supporting programs

\b dosemu2 - to run build decompression tests (optional)

\b qemu - to run build decompression tests (optional)

\b nasm - to assemble. NASM versions to choose:

\lcont{

\b NASM versions up to 2.07 fail -- \cq{%deftok} is not supported

\b NASM versions prior to 2.09.02 fail -- \cq{%deftok} is implemented wrongly

\b NASM version 2.09.02 works (last tested 2019-11)

\b NASM versions 2.09.03 to 2.09.10 all fail -- \cq{%assign %$foo%[bar] quux} doesn't function right

\b NASM version 2.10.09 works (last tested 2019-11)

\b NASM version 2.14.03 works (last tested 2020-12)

\b NASM version 2.15.03 works (last tested 2020-12)

\b NASM version 2.16 (current git head) fails, due to
\W{https://bugzilla.nasm.us/show_bug.cgi?id=3392732}{a bug with %strcat}
and
\W{https://bugzilla.nasm.us/show_bug.cgi?id=3392733}{a bug with %assign ?%1}

}

\b halibut - to build this manual

\b supporting programs:

\lcont{

\b mktables (included in debugger source)

\b tellsize (included in separate repo called tellsize)

\b crc16-t/iniload/checksum (included in separate repo called crc16-t,
to add checksumming, optional)

\b a 86-DOS kernel and shell (to run build decompression tests
or the test suite, optional)

}

\b additional sources (must be referenced in cfg.sh or ovr.sh):

\lcont{

\b lmacros (macro collection)

\b scanptab (partition table scanning for bootable debugger)

\b ldosboot (iniload frame for bootable debugger, boot sector loaders)

\b instsect (application to install boot sector loaders)

\b bootimg (to run decompression test with qemu
and create boot image for qemu to use for the test suite)

\b inicomp (if to use compression support), also needs one of:

\lcont{

\b brieflz (blzpack)

\b lz4 (lz4c)

\b snappy (snzip)

\b exomizer -- recommended as this usually results in the smallest files

\b x-compressor

\b heatshrink

\b lzip -- usually even smaller than Exomizer but takes longer to decompress

\b lzop

\b lzsa

\b apultra

\b bzpack

}

\b crc16-t/iniload (if to add checksumming)

\b symsnip (only for symbolic branch)

}


\H{buildingprocess} How to build

\n Clone the mercurial repo from
\W{https://hg.pushbx.org/ecm/ldebug}{https://hg.pushbx.org/ecm/ldebug}
or in an existing repo use \cq{hg pull} to update the repo

\n Update the repo to either the default branch with \cq{hg up default}
or the symbolic branch with \cq{hg up symbolic}
or any other available commit you want to build

\n Clone the other needed repos from
\W{https://hg.pushbx.org/ecm/}{https://hg.pushbx.org/ecm/}
or in existing repos use \cq{hg fetch}
or the sequence of \cq{hg pull} then \cq{hg up}
to update the repos.
(Usually the additional source repos do not have multiple branches.)

\n Copy the ldebug/source/cfg.sh file to ovr.sh in the same directory

\n Edit ovr.sh to point to the repos

\n Edit \cw{INICOMP_METHOD} in ovr.sh to
select none, one, or several compression methods.
Surround multiple values with quotes and delimit with blanks.
If the value "none" is used no compression will occur.
If several values are given the smallest of the resulting files
will be used as the \cw{ldebug.com} result.
This favours LZMA-lzip (lzd) and Exomizer 3 (exodecr) compression
as they result in the best ratios.
The uncompressed \cw{ldebugu.com} file will always be generated,
you can rename or copy or symlink it to use it as \cw{ldebug.com} if you want.

\n If you have dosemu2 or qemu,
you may enable the \cw{use_build_decomp_test} option.
This insures that the compressed executables
will actually succeed in decompression when entered in EXE mode,
and will lower the required minimum allocation given in the EXE header to
the minimally required value so that decompression will still succeed.
This defaults to using dosemu2, which must have a DOS installed
that allows filesystem redirection.
\cw{DEFAULT_MACHINE} can be used to select qemu instead.
The options \cw{BOOT_KERNEL}, \cw{BOOT_COMMAND}, and \cw{BOOT_PROTOCOL}
must be set up then to allow building a bootable diskette.
(This is needed because qemu does not offer filesystem redirection for DOS.)

\n The \cw{use_build_revision_id} option is by default on.
It requires that the sources are in hg (Mercurial) repos
and that the hg command is available to run \cq{hg id}.
The resulting revision IDs are embedded into the executable
and will be shown for the ?B (long) and ?BUILD (short) commands.

\n In ovr.sh you can also specify which tools to use.
For example, the variable \cw{$NASM} specifies the nasm executable to use,
with path if needed.

\n If you want to rebuild debugtbl.inc you should compile mktables then run it.
While in the ldebug/source directory,
run \cq{./makec} (or use whatever C compiler to build mktables)
then \cq{./mktables} next.
Note that mktables only needs to be used
if either the source files (instr.*) changed or
the mktables program itself has been altered.
If the assembler and disassembler tables are not to change
then mktables need not be used.

\n Finally, run \cq{./mak.sh} from the ldebug/source directory.
You may pass environment variables to it, such as
\cq{INICOMP_METHOD=exodecr ./mak.sh} to select Exomizer compression.
You may also pass it parameters which will be passed to the main
assembly command, such as \cq{./mak.sh -D_DEBUG4} to enable debugging messages.

The mak.sh script expects that the current working directory
is equal to the directory that it resides in.
So you'll always want to run it as \cq{./mak.sh} from that directory.
The same is true of the make* scripts.

The make* scripts work as follows:

\dt make

\dd calls mak.sh to create debug and debugx

\dt maked

\dd calls mak.sh to create ddebug and ddebugx

\dt maker

\dd calls mak.sh to create only debug

\dt makerd

\dd calls mak.sh to create only ddebug

\dt makex

\dd calls mak.sh to create only debugx

\dt makexd

\dd calls mak.sh to create only ddebugx

ldebug/tmp, ldebug/lst, and ldebug/bin will receive
the files created by the mak script.
The following filenames are for the default when running mak.sh on its own
which is to create debug.
(When ddebug, debugx, or ddebugx are created, the names change accordingly.)
In the ldebug/bin subdirectory, \cw{debug.com}
will be a nonbootable executable (even if the \cw{_BOOTLDR} option is enabled).
This executable can safely be compressed using EXE packers such as the UPX.
(In cfg.sh the option \cw{use_build_shim} now controls whether
\cw{debug.com} is created. It defaults to disable this output file.)
If the \cw{_BOOTLDR} option is enabled,
\cw{ldebug.com} will be a compressed bootable executable
(if any compression method is selected),
whereas \cw{ldebugu.com} will be an uncompressed bootable executable.
These bootable executables must not be compressed using any other programs.
Doing that would render the kernel mode entrypoints unusable.
Incidentally, UPX rejects these files because
their \q{last page size} MZ EXE header field holds an invalid value.

The bootable executables can be used as
MS-DOS 6 protocol \cw{IO.SYS},
MS-DOS 7/8 \cw{IO.SYS},
PC-DOS 6/7 \cw{IBMBIO.COM},
FreeDOS \cw{KERNEL.SYS},
RxDOS.3 \cw{RXDOS.COM},
or as a Multiboot specification or Multiboot2 specification kernel.
In any kernel load protocol case,
the root FS that is being loaded from should be
a valid FAT12, FAT16, or FAT32 file system
on an unpartitioned (super)floppy diskette (unit number up to 127)
or MBR-partitioned hard disk (unit number above 127).
In addition, the bootable executables also
are valid 86-DOS application programs that can be loaded in EXE mode.
(Internally, all the .com files are MZ executables with a header,
but they are named with a .COM file name extension for compatibility.)

It is valid to append additional data, such as a .ZIP archive,
to any of the executables.
However, if too large this may render loading with
the FreeDOS load protocol impossible.
All the other protocols work even in
the presence of arbitrarily large appended data.


\S{buildinginstsect} How to build the instsect application

\n Clone the mercurial repo from
\W{https://hg.pushbx.org/ecm/ldebug}{https://hg.pushbx.org/ecm/ldebug}
or in an existing repo use \cq{hg pull} to update the repo

\n Update the repo to either the default branch with \cq{hg up default}
or the symbolic branch with \cq{hg up symbolic}
or any other available commit you want to build

\n Clone the other needed repos (lmacros, ldosboot, instsect) from
\W{https://hg.pushbx.org/ecm/}{https://hg.pushbx.org/ecm/}
or in existing repos use \cq{hg fetch}
or the sequence of \cq{hg pull} then \cq{hg up}
to update the repos.
(Usually the additional source repos do not have multiple branches.)

\n Copy the ldebug/source/cfg.sh file to ovr.sh in the same directory

\n Edit ovr.sh to point to the repos

\n In ovr.sh you can also specify which tools to use.
For example, the variable \cw{$NASM} specifies the nasm executable to use,
with path if needed.

\n Finally, run \cq{./makinst.sh} from the ldebug/source directory.
You may pass environment variables to it.
You may also pass it parameters which will be passed to the
assembly commands.

The makinst.sh script expects that the current working directory
is equal to the directory that it resides in.
So you'll always want to run it as \cq{./makinst.sh} from that directory.

ldebug/tmp, ldebug/lst, and ldebug/bin will receive
the files created by the makinst script.
ldebug/bin/instsect.com will be the instsect application,
which has boot sector loaders for FAT12, FAT16, and FAT32 embedded.
The default protocol is lDOS and the default kernel name LDEBUG.COM.
Read the instsect help page for instructions on how to use it.
Refer to \k{cmdhelp-instsect} for the instsect help.
The help can also be obtained by running \cw{instsect.com /?} from DOS.
The kernel name can be modified with the \cw{/F=} switch to instsect.
For instance, \cq{instsect.com /f=lddebugu.com a:} installs the loader
onto drive A: with the name set up to load the uncompressed lDDebug.

Current lDOS boot32 uses the FSIBOOT4 protocol for an additional stage.
This is interoperable with the upcoming RxDOS version 7.25's use of
the FSIBOOT4 protocol, as well as with loaders that use
a different sector for their additional stage (like Microsoft's),
or those that do not use an additional stage (like FreeDOS's).


\S{buildingtest} How to prepare the test suite

The test suite (test/test.py) by default uses qemu.
(dosemu2 tends to need more than 5 seconds to start
while qemu manages in 2 seconds or less.)

If the debugger is run as a DOS application
and qemu is used then a boot image containing a DOS kernel,
shell, autoexec.bat, and quit program must be created.
If the build option use_build_qimg is enabled
then calls to mak.sh will create such an image.
The script file makqimg.sh carries out this task.

If the debugger is run as a DOS application
and dosemu2 is used then the DOS installed in dosemu is used.
The -K and -E switches to dosemu2 are used to
mount a host directory and execute the debugger.

If the debugger is bootloaded (in either qemu or dosemu2)
then a boot image with only the debugger executable
and a startup boot script file must be created.
If the build option use_build_bimg is enabled
then calls to mak.sh will create such an image.
The script file makbimg.sh carries out this task.

The test script creates symlinks to bin/ and
tmp/qemutest/ and tmp/bdbgtest/ on its own.
It can be executed from any directory,
as it should find its files based on its own location.
The test suite uses pseudoterminals, qemu or dosemu2, and
the default Python unittest module.

The DPMI tests currently require manual setup,
with a directory test/dpmitest/ containing the
dpmitest programs (for dosemu2) or a diskette image
test/dpmi.img containing the programs as well as
the HDPMI host executable (for qemu).


\H{buildingoptions} Build options

\dt _DEBUG

\dd Make the program debuggable.
A \q{D} is usually prepended to the program name.
This means that the program's handlers are only installed
within the function run,
and are uninstalled within the function intrtn1_code.
This allows debugging everything except this section.
This is intended to be used with a default build of lDebug
as the outer debugger.
However, there is nothing preventing usage of a different debugger.
To indicate that the debuggable debugger is running,
its default command prompts are prepended by a tilde \cq{~}.

\lcont{

(To debug everything including the section from run to intrtn1_code,
or the DPMI entry of lDebugX,
a lower-level debugger must be used, such as dosemu's dosdebug
or other debuggers that are integrated into emulators.)

}

\dt _PM

\dd Make the program DPMI-capable.
An \q{X} is usually appended to the program name.
If possible, the interrupt 2Fh function 1687h is hooked and made to
return lDebugX's entrypoint.
Otherwise, the initial entry into protected mode must be traced.
Upon entry lDebugX will install itself as if it is the actual client,
initialise itself, then set up the original client
as if that had entered protected mode.
The assembler and disassembler will detect and support 32-bit code segments.
Other commands will also use 32-bit addressing to allow using 32-bit segments.
To indicate that the debugger is in protected mode,
its default command prompt changes from the dash \cq{-} to a hash sign \cq{#}.
(lDDebugX prepends its tilde to that resulting in \cq{~#}.)

\dt _BOOTLDR

\dd Makes the program support being bootloaded.
This additionally requires the lDOS iniload stage wrapped
around the MZ .EXE image of the debugger.
The mak.sh script prepends an \q{l} to the base filename
to create the names for the bootable files.
For building debug, this results in \cw{ldebugu.com} and \cw{ldebug.com}.
In bootloaded mode, I/O is never done using DOS,
as if InDOS mode was always on.
The DOS's current PSP is not switched during debugger operation.
The MCB chain can only be displayed using the DM command
by specifying the start segment explicitly.
The BOOT commands are supported, refer to \k{helpboot}.

\dt _HISTORY

\dd Enables the line editing history for raw terminal and serial input.
Defaults to on.
Size can be specified using _HISTORY_SIZE.
Whether a separate segment is used can be controlled
using the _HISTORY_SEPARATE_FIXED option.
Defaults to an 8 KiB separate segment buffer.

\dt _MEMREF_AMOUNT

\dd Indicates number of memref structures to include.
Default 4 (on).
If enabled without a value, the default (4) is selected.
When enabling this option, you most likely want to first rebuild
the assembler and disassembler tables using the command
\cw{./mktables direction stackhinting}.
(These mktables switches are now default enabled.)
This allows for memrefs to indicate whether an explicit memory operand
is a read or write (\cw{direction}),
as well as for stack accesses
like \cw{push}, \cw{pop}, \cw{call}, \cw{retn}
to be recognised in memrefs (\cw{stackhinting}).
Memrefs are initialised by disassembly.
Memrefs can be accessed using the access variables
like \cw{READADR0}, \cw{READLEN0}, etc. Refer to \k{varaccess}.
The access variables are written
after an R command's register dump and disassembly
(refer to \k{cmdr}).
Access variables can be accessed using special keywords
behind the \cw{IN} of a \cw{VALUE x IN y} construct (refer to \k{exprvaluein}).

\lcont{

Note that memrefs are not always exact.
For instance, accesses by some instructions
are not detected (eg \cw{lgdt}, \cw{sgdt}, \cw{fsave}).
Some instructions' accesses are not always correctly detected,
such as \cw{enter} with non-zero second operand,
string instructions spanning segment boundaries,
or instructions using \cw{ss} after
a write to \cw{ss} that causes disassembly repetition.
Some types of accesses are never detected either,
such as GDT/LDT accesses to load descriptors.
The stack access of software interrupt instructions
is correctly detected only when tracing interrupts
(Trace Mode set to 1, refer to \k{cmdtm});
if the interrupt call is proceeded past then
like any proceeded-past function call it may use more stack space.

}


\C{gettingstartedrelease} Getting started with the release

The stand-alone and FreeDOS release packages contain
the following files:

In the \cw{bin} or \cw{BIN} directory:

\dt \cw{ldebugu.com}

\dd Uncompressed bootable debugger, build without DPMI support

\dt \cw{ldebug.com}

\dd Compressed bootable debugger, build without DPMI support

\dt \cw{ldebugxu.com}

\dd Uncompressed bootable debugger, build with DPMI support

\dt \cw{ldebugx.com}

\dd Compressed bootable debugger, build with DPMI support

\dt \cw{instsect.com}

\dd Application to install boot sector loaders,
with lDOS loaders that default to load \cw{LDEBUG.COM}
from a FAT12, FAT16, or FAT32 file system


The \cw{tmp} or \cw{SOURCE/LDEBUG/ldebug/tmp} directory
contains subdirectories for each used compression method.
For example, there is a subdirectory named \cw{lz4}.
These subdirectories contain the compressed executables
\cw{ldebug.com} and \cw{ldebugx.com} built
with the corresponding compression method.

NB: The default choice of compression method (LZMA-lzip)
is chosen based purely on the smallest possible executable size.
It may be unsuitable for use on low-end systems
where it may take several minutes to decompress the application.
In this case, the uncompressed executables may be used,
or those compressed with another method
(as found in the \cw{tmp} subdirectories).


In the \cw{doc} directory, or \cw{DOC/LDEBUG}:

\dt \cw{ldebug.htm}

\dd This manual in HTML, preferred form

\dt \cw{ldebug.txt}

\dd Manual in plain text (FreeDOS package: with CR LF line endings)

\dt \cw{ldebug.pdf}

\dd Manual in PDF

\dt \cw{fdbuild.txt}

\dd FreeDOS package build instructions

\dt \cw{LDEBUG.LSM}

\dd LSM file for lDebug FreeDOS package


In the root directory, or also \cw{DOC/LDEBUG}:

\dt \cw{license.txt}

\dd Full license texts for lDebug


In the \cw{APPINFO} directory, only for FreeDOS package:

\dt \cw{LDEBUG.LSM}

\dd LSM file for lDebug FreeDOS package


In the \cw{lst} or \cw{SOURCE/LDEBUG/ldebug/lst} directory:

\dt \cw{debug.lst}

\dd Assembly listing corresponding to \cw{ldebug.com} and \cw{ldebugu.com}

\dt \cw{debug.map}

\dd Assembly map corresponding to \cw{ldebug.com} and \cw{ldebugu.com}

\dt \cw{debugx.lst}

\dd Assembly listing corresponding to \cw{ldebugx.com} and \cw{ldebugxu.com}

\dt \cw{debugx.map}

\dd Assembly map corresponding to \cw{ldebugx.com} and \cw{ldebugxu.com}


\C{invoking} Invoking the debugger

\H{invoking-boot} Invoking the debugger in boot loaded mode

The debugger can be loaded as a variety of kernel formats.

The Multiboot1 and Multiboot2 entrypoints
will expect that a kernel command line is provided.
The RxDOS.3 and lDOS load protocols allow specifying
a kernel command line, but it is optional.

If a kernel command line is detected then its contents
are entered into the command line buffer.
Unescaped semicolons are translated into Carriage Returns.
Semicolons and backslashes may be escaped with backslashes.

If no kernel command line is given, the debugger assumes
a default. It is equivalent to checking for a file and label using
the IF command (\k{cmdif}), then if found to execute that script file.
The IF condition is like \c{if exists y ldp/LDEBUG.SLD :bootstartup then}
and the subsequent script command is \c{y ldp/LDEBUG.SLD :bootstartup}
(\k{cmdy}).
The filename is however \c{LDDEBUG.SLD} for DDebug builds.

Executing the \cw{Q} command (\k{cmdq}) makes the debugger
uninstall itself then continue running whatever code
the debuggee is in.
Executing the \cw{BOOT QUIT} command (\k{helpboot})
makes the debugger attempt to shut down the machine.
First it will try to call a dosemu-specific callback.
Next it will attempt shutting down with APM.
(This works in qemu.)
Finally it will give up if no attempt worked.


\H{invoking-app} Invoking the debugger as an application

The debugger is internally an MZ .EXE style application.
It may need MS-DOS version 3 level features.
A few switches are supported:

\dt \cw{/?}

\dd Show the command help page about invoking the debugger.
Refer to \k{cmdhelp-ldebug} for a copy of that help.

\dt \cw{/c}

\dd Put the text following this switch into the command line buffer.
Unquoted unescaped blanks indicate the end of the text.
Parts may be quoted using single quote marks or double quote marks.
Unescaped semicolons are translated into Carriage Returns.
Semicolons, backslashes, quote marks, and blanks
may be escaped with backslashes.

\dt \cw{/s}

\dd This switch is only used by the symbolic branch.
It can be used to set the size of the symbol tables early,
before loading a debuggee application.

After the switches a filename may follow.
After the filename, command line contents for the process
to be debugged may follow.
These are both passed to the N command.
Then, an L command for loading an application is run.

Executing the \cw{Q} command (\k{cmdq}) makes the debugger
try to terminate the debuggee application
and to then terminate itself.
The debugger returns to whatever application called it.

If the TSR command (\k{cmdtsr}) is used, the debugger
patches the parent of the currently running application
to be the debugger's parent.
A subsequent \cw{Q} command will then behave much like
it does in boot loaded mode:
The debugger uninstalls itself and continues execution
in the current debuggee context.


\H{invoking-test} Invoking the test suite

Use the test.py script in the test subdirectory.
Use the -v switch to do verbose output.
Specify test name patterns to use with -k,
or omit to run all tests.
The script uses the following environment variables:

\dt build_name

\dd Build name to use.
Either debug (default), debugx, ddebug, or ddebugx.

\dt test_booting

\dd If set to a nonzero number, boot into the debugger.
Otherwise, a DOS is loaded and
the debugger is run as an application.
Some tests are booting only,
some other tests are non-booting only.
The unsupported tests are skipped automatically.

\dt test_initialise_commands

\dd Commands to be executed by the test set up method
right after establishing serial I/O.
Semicolons are replaced by Carriage Returns.

\dt DEFAULT_MACHINE

\dd qemu or dosemu

\dt DOSEMU

\dd dosemu executable to use

\dt QEMU

\dd qemu executable to use

\dt DEBUG

\dd If set to a nonzero number, dump all serial I/O
and all debugging messages.


\C{interface} Interface Reference


\H{interface-output} Interface Output

The debugger provides a line-based text interface.
The interface is written to DOS standard output by default.
If InDOS mode is entered or the debugger is bootloaded
then the interface is written to the terminal using interrupt 10h.
Serial I/O can be enabled to write the interface to the serial port.


\H{interface-input} Interface Input

The default command prompt indicates that a command may be entered.
It is a dash \cq{-} by default,
or a hash sign \cq{#} when DebugX is in Protected Mode.
An exclamation point \cq{!} is prepended
by a DOS application debugger (not bootloaded)
while DOS's InDOS flag is set.
A tilde \cq{~} is prepended for DDebug.

If DOS command line input is done as raw input
(eg if DCO option 800h is set)
or the input is from a raw (ROM-BIOS) terminal,
or from a serial port, then the line editing history is enabled.
Prior commands may be recalled using the Up arrow key.
The Down arrow key may also be used to reverse the recall.
As soon as any prior or new line is edited
the history recall is disabled.

Long command output may be paged.
In that case, once a screenful has been displayed,
a \cq{[more]} prompt is displayed to pause the output.
After pressing any key the output is continued.
If Control-C is pressed, the current command is aborted.


\H{interface-serial} Enabling serial I/O

Refer to \k{varserial} for the serial configuration variables.
Setting the DCO flag 4000h enables serial I/O.
Upon enabling serial I/O a prompt is sent to the serial port.
This prompt looks like the following example:

\c lDebug connected to serial port. Enter KEEP to confirm.
\c =

(The name of the debugger is modified to
indicate DebugX, DDebug, or DDebugX.
The prompt indicator is \cq{~= } for DDebug.)
If the keep prompt is successfully displayed
by the serial terminal and is responded to
with the requested \cq{KEEP} keyword
then serial I/O is established.

If the confirmation does not occur after a timeout
then serial I/O is disabled again.
The timeout defaults to about 15 seconds.
In this case the debugger itself clears the DCO flag 4000h.

If the DCO flag 4000h is cleared then serial I/O is disabled.


\H{interface-rdump} Register dumping

The R command (refer to \k{cmdr}) without any parameters
dumps the current register values.
Then it disassembles a single instruction,
or occasionally more than one.
The register dump looks like this by default:

\c -r
\c AX=0000 BX=0001 CX=58A0 DX=0000 SP=0800 BP=0000 SI=0000 DI=0000
\c DS=1BEC ES=1BEC SS=35A9 CS=1BEC IP=0140 NV UP EI PL ZR NA PE NC
\c 1BEC:0140 8CC8              mov     ax, cs
\c -

If the \cq{RX} command was used
to switch on 32-bit register dumping,
then the register dump looks like this:

\c -r
\c EAX=00000000 EBX=00000001 ECX=000058A0 EDX=00000000 ESP=00000800 EBP=00000000
\c ESI=00000000 EDI=00000000 NV UP EI PL ZR NA PE NC
\c DS=1BEC ES=1BEC SS=35A9 CS=1BEC FS=0000 GS=0000 EIP=00000140
\c 1BEC:0140 8CC8              mov     ax, cs
\c -

The RE command (\k{cmdre}) runs the RE buffer commands.
The default RE buffer content is a single \cq{@R} command.
After running the program being debugged,
usually the RE buffer commands are also being run.
This includes a step with the T, TP, or P commands.
(\K{cmdt}, \k{cmdtp}, \k{cmdp}.)
It also includes a run with the G command. (\K{cmdg}.)
Further, a permanent breakpoint
which is configured as a pass point being passed
also runs the RE buffer commands. (\K{cmdb}.)

Setting the flags 10000 or 40000 in the DCO3 variable
enables register change highlighting.
When output is written to DOS standard output
or to a serial port
then ANSI escape sequences are used to highlight.
Specifically, \cq{\\x1B[7m} is used to reverse video
and then \cq{\\x1B[m} to reset the colours.

For DOS standard output it may be needed to install
an ANSI escape sequence parser.

For serial I/O the terminal connected to the debugger
is expected to handle the escape sequences.

If the output is to a terminal using interrupt 10h
and DCO3 flag 20000 is clear and the terminal is
detected as functional then highlighting is
done using interrupt 10h video attributes.

The functionality check is done by calling
interrupt 10h service 03h.
If the indicated current column is nonzero
then the terminal is considered functional.
(Current dosemu2 in \cw{-dumb} terminal mode
is detected as not being functional.)

If this check fails or the DCO3 flag 20000 is set
then escape sequences are written using interrupt 10h.


\H{interface-mdump} Memory dumping

Another basic command is the D command (\k{cmdd}).
It is used to dump memory contents.
For example, to dump part of a program:

\c -d
\c 1BEC:0140  8C C8 31 DB 05 70 14 50-53 CB 70 03 91 67 BC 45 ..1..p.PS.p..g.E
\c 1BEC:0150  3F 10 C1 6F F9 70 BA 22-7C 71 C3 72 0A 81 0A 81 ?..o.p."|q.r....
\c 1BEC:0160  47 74 68 76 6C 77 32 72-A7 2F BD 78 4B 16 9F 7B Gthvlw2r./.xK..{
\c 1BEC:0170  C9 2B 09 37 0A 81 81 7D-E2 7E AC A0 00 00 00 00 .+.7...}.~......
\c 1BEC:0180  10 49 00 00 0F 00 00 00-00 00 00 00 10 49 00 00 .I...........I..
\c 1BEC:0190  0F 00 00 00 F8 30 80 00-00 00 00 00 80 00 00 00 .....0..........
\c 1BEC:01A0  07 00 00 00 07 00 00 00-00 00 00 00 00 00 00 00 ................
\c 1BEC:01B0  00 00 00 00 97 65 00 00-00 00 00 00 00 00 00 00 .....e..........
\c -

Or, to dump the stack as words:

\c -dw ss:sp
\c header     0    2    4    6    8    A    C    E    0123456789ABCDEF
\c 35A9:0800  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0810  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0820  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0830  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0840  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0850  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0860  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c 35A9:0870  0000 0000 0000 0000-0000 0000 0000 0000 ................
\c -


\H{interface-disasm} Disassembly

The U command is used to disassemble one or several instructions.
Example:

\c -u
\c 305C:0000 8CD0              mov     ax, ss
\c 305C:0002 8CDA              mov     dx, ds
\c 305C:0004 29D0              sub     ax, dx
\c 305C:0006 31D2              xor     dx, dx
\c 305C:0008 B90400            mov     cx, 0004
\c 305C:000B D1E0              shl     ax, 1
\c 305C:000D D1D2              rcl     dx, 1
\c 305C:000F E2FA              loop    000B
\c 305C:0011 50                push    ax
\c 305C:0012 01E0              add     ax, sp
\c 305C:0014 83D200            adc     dx, +00
\c 305C:0017 83C00F            add     ax, +0F
\c 305C:001A 83D200            adc     dx, +00
\c 305C:001D 24F0              and     al, F0
\c 305C:001F 83FA01            cmp     dx, +01
\c -


\H{interface-help} Help

The online help can be accessed using the \cq{?} command.
Refer to \k{helptopics} for copies of the online help.


\C{parref} Parameter Reference

\H{parnumber} Number

Plain numbers are evaluated as expressions.
Refer to \k{exprref}.
Expressions consist of any number of the following:

\b Unary operators

\b Binary operators

\b Operands

Plain number parsing for an expression continues for as long as
a valid expression is continued.
For example, in the command \cq{D 100 + 20 L 10} the starting address
(its offset to be specific) is calculated as \q{100 + 20}.
Then the expression evaluator encounters the \cq{L},
which is not a valid binary operator.
Plain number expression parameters are used by a lot of commands.
Sometimes, the plain number parameter type
is called \q{count} or \q{value}.


\H{paraddress} Address

An address parameter is calculated with a default segment.
First, a plain number is parsed.
If it is followed by a colon, the first number is taken as segment,
and then another number is parsed for the offset.
Otherwise, the first number is used as the offset.
Offsets may be 16 bits or 32 bits wide,
though 32-bit offsets are only valid for DebugX and only in 32-bit segments.
Address parameters are used by a lot of commands.


\H{parrange} Range

A range parameter may have a default length,
or it may be disallowed to omit a length.
Parsing a range starts with parsing an address.
Then, if the end of the line is not yet reached,
an end for the range may be specified.
The end may be a plain number,
which is taken as the offset of the last byte to include in the range.
The address of the last byte to include must be equal or above
the address of the first byte that is included in the range.

The end may instead be specified with an \cq{L} or \cq{LENGTH} keyword.
In that case, the keyword is followed by a plain number
and an optional item size keyword.
A length of zero is not valid.
The item size keyword may be \cq{BYTES}, \cq{WORDS}, or \cq{DWORDS}.
For the latter two, the plain number will be multiplied by 2 or 4.
The \cq{BYTES} keyword is only provided for symmetry;
currently all commands taking ranges default to byte size
for the \cq{LENGTH} number.

For example, the command \cq{DD 100 LENGTH 4 DWORDS} will
dump memory from address 0100h (in the current data segment)
in dword units, for a length of 4*4 = 16 bytes.
The item size keywords were introduced
primarily for the \cq{DW} and \cq{DD} commands
(refer to \k{cmdd}),
but they can be used for any command that accepts a range.

Range parameters are used by a lot of commands.


\H{parlist} List

A list is made up of a sequence of items.
Each item is either a plain number or a quoted string.
List parsing continues until the end of the line.
Each plain number represents a single byte.
Quoted strings represent as many bytes as there are quoted.
List parameters are used by the E, F, and S commands.
Refer to \k{cmde}, \k{cmdf}, and \k{cmds}.


\H{parlistorrange} List or range

A list or range can be specified for this parameter.
The range is identified by a leading \cq{RANGE} keyword.
Otherwise, a list is parsed.
A list or range parameter is as yet used by
the S command and the F command, refer to \k{cmds} and \k{cmdf}.


\H{parkeyword} Keyword

A keyword is checked insensitive to capitalisation.
Keywords depend on each command.
Only the keywords used to specify a range's length are shared
by all commands that parse ranges.


\H{parindex} Index

An index is a plain number that specifies a breakpoint index.
It allows operating on one specific breakpoint.
The index parameter type is used by the B commands,
refer to \k{cmdb}.


\H{parsegment} Segment

A segment is a plain number for parsing purposes.
The segment parameter type is used by the DM command
and some BOOT commands,
refer to \k{cmddm} and \k{helpboot}.


\H{parbreakpoints} Breakpoint

Each breakpoint is a single address, which defaults to the code segment.
The address may instead be specified starting with an AT sign \cq{@},
followed by a blank or an opening parenthesis.
In that case, the following plain number
specifies the non-segmented linear address to use.
The breakpoint parameter type is used by the B and G commands,
refer to \k{cmdb} and \k{cmdg}.


\H{parlabel} Label

A label is a (not quoted) string keyword.
It may start with an optional colon.
A label can be used by the GOTO and Y commands,
refer to \k{cmdgoto} and \k{cmdy}.


\H{parport} Port

A port is a plain number for parsing purposes.
The port parameter type is used by the I and O commands,
refer to \k{cmdi} and \k{cmdo}.


\H{pardrive} Drive

A drive may be either an alphabetic letter followed by a colon,
or a plain number. The number zero corresponds to drive A: then.
The drive parameter type is used by the L and W sector commands,
refer to \k{cmdls} and \k{cmdws}.
The N and Y commands (\k{cmdn} and \k{cmdy})
also accept drive parameters, but only as part of their filenames.
These must be in the drive letter followed by colon format.


\H{parsector} Sector

A sector is a plain number, which can be equal to any 32-bit value.
The sector parameter type is used by the L and W sector commands,
refer to \k{cmdls} and \k{cmdws}.
Some BOOT commands also use sector numbers, refer to \k{helpboot}.


\H{parcond} Condition

A condition is a plain number.
It is evaluated either to nonzero (true) or zero (false).
The condition parameter type is used by the IF command,
as well as the P, TP, and T commands
when specified with a \cq{WHILE} keyword.
The BW and BP (with a \cq{WHEN} keyword) commands also use conditions.
Refer to \k{cmdif}, \k{cmdp}, \k{cmdt}, \k{cmdbw}, \k{cmdbp}.
The length of a condition for B commands is
limited by how much space is left
in the permanent breakpoint conditions buffer.
This buffer currently defaults to 1024 bytes.
It is shared for all conditions of all permanent breakpoints.


\H{parregister} Register

A register specifies an internal variable of the debugger.
Most prominently these include the debuggee's registers
as stored by the debugger in its data segment.
A register or variable may be an operand in a plain number's expression.
However, several forms of the R command also use register parameters.
These allow reading and writing the register values.
Refer to \k{cmdr}.


\H{parcommand} Command

Command is a special parameter type that is used only by
the RE.APPEND and RE.REPLACE commands (\k{cmdredot}).
It is read verbatim and entered into the RE command buffer.
Semicolons within a command parameter are not parsed as
end of line comment markers.
Instead, they are converted to CR (13) codes in the RE buffer.
This delimits the parts of the parameter into several commands.
A semicolon may be prefixed by a backslash to escape it and thus
enter a literal semicolon into the RE buffer.


\H{parid} ID

ID is a special parameter type that is used only by
the BP and BI commands (\k{cmdbp} and \k{cmdbi}).
Leading and trailing whitespace is ignored.
An ID can be empty, or contain up to 63 bytes of data.
The length of an ID is also limited by how much space
is left in the permanent breakpoint ID buffer.
This buffer currently defaults to 384 bytes.
It is shared for all IDs of all permanent breakpoints.


\C{exprref} Expression Reference

\H{exprliteral} Literals

Literals consist of one or more digits.
A literal must start with a digit or hash sign \cq{#}.
Embedded underscores \cq{_} are skipped.
Literals must not overflow 4 giga binary minus 1, that is FFFF_FFFFh.

The default base for literals is sixteen (hexadecimal).
A hash sign \cq{#} indicates a base change.
If nothing preceeds the hash sign the base is changed to ten (decimal).
Otherwise, the number before the hash sign is read in the prior base
and taken as the base to change to.
The base must be between 2 and 36.
Multiple hash signs are allowed in the same literal.


\H{exprstringliteral} String literals

String literals consist of up to 4 bytes.
The bytes are specified starting with a hash sign \cq{#}
followed by a single-quote mark \cw{'} or double-quote mark \cw{"}.
The same quote mark is used to end the string literal.
Strings are read in a little-endian order, same as NASM does.
That is, the first byte of a multi-byte string
is read into the lowest byte of the numeric value.
This matches the order obtained by writing the string to memory
and reading it as a word, 3byte, or dword.


\H{exprvariable} Variables

A variable consists of a variable name,
possibly followed by parentheses with an index expression.
Variable names are capitalisation insensitive.
Variables differ in size, there are variables
consisting of 8, 16, 24, or 32 bits.
Variables can be written to using the R command.
Some variables are read-only.
A few variables allow writing some but not all bits.


\H{exprindirection} Indirection

Indirection is indicated by square brackets.
Within the brackets an address is parsed,
defaulting to \cw{ds} as the segment.
The size of the indirect access can be specified
with a type specifier before the brackets.
The usual types are
\cw{BYTE}, \cw{WORD}, \cw{3BYTE}, and \cw{DWORD}.
Like variables, indirection terms can be written to using the R command.


\H{exprparens} Parentheses

Parentheses can be used to force a different order of operations.


\H{exprlinear} \cw{LINEAR} keyword

A keyword reading \cw{LINEAR} introduces an address to parse.
The address defaults to \cw{ds} as the segment.
The address may be separated from subsequent text with a comma.
If the expression is to be separated from a subsequent element
using a comma after a \cw{LINEAR} address then two commas are needed.
Depending on the segmentation scheme of the current mode
the segmented address is converted into a linear address.
If DebugX is in Protected Mode and the segment base cannot
be determined the expression is rejected as an error.


\H{exprvaluein} \cw{VALUE IN} construct

A keyword reading \cw{VALUE} starts a \cw{VALUE IN} construct.
Between the \cw{VALUE} and subsequent \cw{IN} keyword
there is a single value expression,
or a range of the form
\cw{FROM expression TO expression} or
\cw{FROM expression LENGTH expression}.
Next follows the \cw{IN} keyword.
After this, there is a list of match ranges.
A match range is either a single value expression,
or a range of the form
\cw{FROM expression TO expression} or
\cw{FROM expression LENGTH expression}.
After each match range a comma indicates another match range follows.

In a \cw{FROM TO} specification the first expression
has to evaluate to unsigned below-or-equal the second expression.
In a \cw{FROM LENGTH} specification the length
must be nonzero.
If these conditions are not met
then the value or match range in question
is always considered as not matching.

The entire \cw{VALUE IN} construct evaluates to how many
of the match ranges match the value range.
The construct only evaluates to zero if no matches occurred.
A nonzero value indicates that at least one match occurred.


\S{exprvaluein-keywords} \cw{VALUE IN} construct keywords

Instead of a value or match range as specified here,
the keyword \cw{EXECUTING} may be specified.
This expands to the following input:

\c FROM LINEAR cs:eip LENGTH abo - eip

If the \cw{_MEMREF_AMOUNT} build option is enabled
and paired with the \cw{direction} and \cw{stackhinting} switches to mktables
then additional keywords are available for \cw{VALUE IN} match ranges.
That is, these keywords must be specified behind the \cw{IN} and
cannot be specified between the \cw{VALUE} and \cw{IN}.

These keywords are as follows:

\dt \cw{READING}

\dd Expands to a comma-separated list of \cw{FROM readadr0 LENGTH readlen0}
constructs, for every read access variable pair (refer to \k{varaccess}).

\dt \cw{WRITING}

\dd Expands to a comma-separated list of \cw{FROM writadr0 LENGTH writlen0}
constructs, for every write access variable pair (refer to \k{varaccess}).

\dt \cw{ACCESSING}

\dd Expands to \cw{READING, WRITING, EXECUTING}.


\H{exprconditional} Conditional \cw{?? ::} construct

The ternary conditional operator takes three operands.
It is the only ternary operator.

The first operand, the condition, is specified before the \cw{??} keyword.
Note that the \cw{??} keyword must be terminated by a blank
or an opening square bracket or round parenthesis.

The second operand is specified between the \cw{??} keyword
and the \cw{::} keyword.
Its value is used as the construct's return value if the condition is true.

The third operand is specified after the \cw{::} keyword.
Its value is used as the construct's return value if the condition is false.

The conditional operator can be nested freely.
The conditional operator must not be combined into
the R command's assignment operator as in \cw{??:=}.
The third operand may be separated from subsequent text with a comma.
If the expression is to be separated from a subsequent element
using a comma after a conditional's third operand then two commas are needed.


\C{cmdref} Command Reference


\H{cmdautorepeat} Empty command - Autorepeat

Entering an empty command at an interactive prompt results in autorepeat.
Interactive prompts for this purpose include:

\b the debugger as a DOS application (\cw{int 21h})

\b the debugger in InDOS mode or as a bootloaded program
(\cw{int 16h}/\cw{int 10h})

\b the debugger across a serial port (port I/O)

Input that does not count as an interactive prompt includes:

\b reading from a file redirected as stdin using DOS (\cw{int 21h})

\b reading from a Y script file using DOS (\cw{int 21h})

\b reading from a Y script file while bootloaded (\cw{int 13h})

\b reading from the command line buffer

\b reading from the RE buffer

Autorepeat is not supported by all commands.
The following commands support autorepeat:

\dt D/DB/DW/DD

\dd Continues memory dump behind the last prior dumped position.
Continues with the same size as the prior dump.
As for if the command is executed with an address lacking a length,
the default length (128 bytes) is used.

\dt DZ/D$/D#/DW#

\dd Continues string dump behind the last prior dumped string.
Continues with the same type of string as the prior dump.

\dt DX

\dd Continues memory dump.

\dt G

\dd Repeats a step running the debuggee.
An equals address given to the prior Go command is not used again.
The same G breakpoints as used by the prior Go command are used
(same as G AGAIN).
The exception is that wherever a breakpoint matches the
\cw{CS:(E)IP} at the start of the command's execution, it is skipped once.

\dt P

\dd Repeats a step running the debuggee.
An equals address given to the prior Proceed command is not used again.
A count given to the prior Proceed command is not used again,
autorepeat always runs as if not given a count.
(That means the PPC variable is used as the effective count.
Refer to \k{varcounts}.)

\dt T

\dd Repeats a step running the debuggee.
An equals address given to the prior Trace command is not used again.
A count given to the prior Trace command is not used again,
autorepeat always runs as if not given a count.
(That means the TTC variable is used as the effective count.
Refer to \k{varcounts}.)

\dt TP

\dd Repeats a step running the debuggee.
An equals address given to the prior Trace/Proceed command is not used again.
A count given to the prior Trace/Proceed command is not used again,
autorepeat always runs as if not given a count.
(That means the TPC variable is used as the effective count.
Refer to \k{varcounts}.)

\dt U

\dd Repeats disassembly behind the last prior disassembled instruction.
As for if the command is executed with an address lacking a length,
the default length (32 bytes) is used.


\H{cmdquestionmark} ? command

\c Online help    ?

The question mark command (?) lists the main online help screen.


\S{cmdhelptopics}

There are additional help topics that can be listed by using
the question mark command with an additional letter or keyword.
These keywords are as follows:

\c Registers      ?R
\c Flags          ?F
\c Conditionals   ?C
\c Expressions    ?E
\c Variables      ?V
\c R Extended     ?RE
\c Run keywords   ?RUN
\c Options        ?O
\c Boot loading   ?BOOT
\c lDebug build   ?BUILD
\c lDebug build   ?B
\c lDebug sources ?SOURCE
\c lDebug license ?L

The full help pages are listed in \k{helptopics}.


\H{cmdcolon} : prefix - GOTO label

A leading colon indicates a destination label for GOTO, see \k{cmdgoto}.


\H{cmda} A command - Assemble

\c assemble        A [address]

Starts assembly at the indicated address (which defaults to CS segment),
or if no address is specified, at the "a_addr" (AAS:AAO variables).

Assembly mode has its own prompt.
Entering a single dot (.) or an empty line terminates assembly mode.
Comments can be given with a prefixed semicolon.
In assembly mode, whereever an immediate number occurs
an expression can be given surrounded by parentheses ( and ).
In such expressions, register names like AX are evaluated
to the values held by the registers at assembly time.
To refer to a register as an assembly operand, it must occur
outside parentheses.


\H{cmdb} B commands - Permanent breakpoints

There are a fixed number of permanent breakpoints provided by the debugger.
The default is to provide 16 permanent breakpoints.
They are specified by indices ranging from 00 to 0F.
A breakpoint can be unused, used while enabled, or used while disabled.
A breakpoint that is in use has a specific linear address.
It is allowed, though not advised,
for several breakpoints to be set to the same address.

When running the debuggee with the commands G, T, TP, or P,
hitting a permanent breakpoint stops execution,
and indicates in a message "Hit permanent breakpoint XX"
where XX is replaced by the hexadecimal byte index of the breakpoint.
If the breakpoint counter is not equal to 8000h when the breakpoint is hit,
then the "Hit" message is followed by a "counter=YYYY" indicator.
If the breakpoint ID is not empty, then
the ID is shown with an "ID: " prefix.
The ID is shown either on the same line as the "Hit" message,
or on the next line if the ID exceeds 28 bytes.
After that message a register dump occurs,
same as for default breaking for the Run commands.


The exceptions are as follows:

\b If the CS:(E)IP at the first step of a G command matches any breakpoints,
then G does a TP-like step with all breakpoints other than
the "cseip"-breakpoint written,
while the "cseip"-breakpoint is not written.
After that, the "cseip"-breakpoint is written
and execution resumes as normal for G.

\b If T.NB or TP.NB or P.NB is used,
no permanent breakpoints are written at all.

\b If T.SB or TP.SB or P.SB is used,
then during the first step no permanent breakpoints are written.
If a counter higher than 1 is given, then during subsequent steps
permanent breakpoints are written.


Each breakpoint has a breakpoint counter,
which defaults to 8000h if not set explicitly by the BP or BN commands.
The breakpoint counter behaves as follows:

\b If (counter & 3FFFh) equals zero then the counter
is considered to be at a terminal state.

\b If the point breaks while the counter is not at a terminal state,
then the counter is decremented.

\b If the counter is decremented to 0 or 4000h, then the point is hit.

\b If the counter is decremented to 8000h or C000h,
or was already at either count without being decremented,
then the point is hit.

\b If the point is not hit but the bit (counter & 4000h) is set,
then the point is passed.


The point being passed means that during running the debuggee
with a Run command, execution is not stopped, but a message indicating
"Passed permanent breakpoint XX, counter=YYYY" is displayed.
As for the "Hit" message the ID, if any, is also shown.
After that message, a register dump occurs.
Then execution is continued in accordance with
the command that is running debuggee code.

Each breakpoint can have a breakpoint condition.
If the condition expression evaluates to false when
the point breaks, then the point is not considered hit or passed.
The breakpoint counter is not stepped then either.


\S{cmdbp} BP command - Set breakpoint

\c set breakpoint  BP index|AT|NEW address
\c                   [[NUMBER=]number] [WHEN=cond] [ID=id]

BP initialises the breakpoint with the given index.
It must be a yet unused breakpoint.
If the index is specified as the keyword NEW,
the lowest unused breakpoint (if any) is selected.
If there is the keyword AT instead of an index or a keyword NEW,
then an existing breakpoint at the same linear address is reset,
or a new one is added (same as if given the NEW keyword).

The address can be given in a segmented format,
which defaults to CS, and which in DebugX
is subject to either PM or 86M segmentation semantics
depending on which mode the debugger is in.
The address can also be given with an @ specifier
(followed by an opening parenthesis or whitespace)
in which case it is specified as the 32-bit linear address.
Debug without DPMI support limits breakpoints to 24-bit addresses,
of which 21 bits are usable.

The optional number, which defaults to 8000h,
sets the breakpoint counter to that number.

The optional WHEN keyword introduces a breakpoint condition.
If the breakpoint is reached then the condition, if specified,
is checked before stepping the counters.
If the condition is false at that point the point is not
considered hit or passed and its counter is not stepped.

There is an optional OFFSET keyword (not shown in the example)
which allows overriding the breakpoint's preferred offset.
Refer to \k{cmdbo} for details.

The optional ID keyword allows setting the breakpoint ID.
The ID is displayed by BL and when a breakpoint is hit or passed.
The default ID is an empty ID.
Note that the ID extends for the remainder of the line.
There cannot be a breakpoint counter number
nor WHEN condition nor OFFSET after the ID keyword.


\S{cmdbi} BI command - Set breakpoint ID

\c  set ID         BI index|AT address [ID=]id

BI sets the breakpoint ID of the specified breakpoint.
The ID is displayed by BL and when a breakpoint is hit or passed.
The ID may be specified as empty.


\S{cmdbw} BW command - Set breakpoint condition

\c  set condition  BW index|AT address [WHEN=]cond

The BW command sets the breakpoint condition.
If the WHEN keyword and the condition are absent
then the condition is reset.
That means the point is no longer conditional.


\S{cmdbo} BO command - Set breakpoint preferred offset

\c  set offset     BO index|AT address [OFFSET=]number

The BO command sets the breakpoint preferred offset.
The preferred offset is used only by the BL command.
It is used to determine the segmented address to display.
The offset is a word variable for Debug and a dword variable for DebugX.
If the OFFSET keyword and the number are absent
then the offset is disabled,
as if the breakpoint was specified with a linear address.
(Internally this is done by setting the offset to all 1 bits.
The offset can be explicitly set to FFFFh (Debug) or FFFF_FFFFh (DebugX)
for the same effect.)


\S{cmdbn} BN command - Set breakpoint number

\c  set number     BN index|AT address|ALL number

BN sets the breakpoint counter of
the specified breakpoint with the given index,
or all used breakpoints when given the keyword ALL,
or the first breakpoint with a matching linear address
when given the AT keyword.
The number defaults to 8000h.


\S{cmdbc} BC command - Clear breakpoint

\c  clear          BC index|AT address|ALL

BC clears the specified breakpoint with the given index,
or all breakpoints when given the keyword ALL,
or the first breakpoint with a matching linear address
when given the AT keyword.
This returns the specified breakpoint (or all of them) to the unused state.
Any associated ID or condition is deleted by BC too.


\S{cmdbd} BD command - Disable breakpoint

\c  disable        BD index|AT address|ALL

Given an index or the keyword ALL or the keyword AT (like BC),
BD disables breakpoints that are in use.
A disabled breakpoint's address is retained and BP
will not allow initialising it anew (except with AT),
but it is otherwise skipped in breakpoint handling.


\S{cmdbe} BE command - Enable breakpoint

\c  enable         BE index|AT address|ALL

Like BD, but enables breakpoints.


\S{cmdbt} BT command - Toggle breakpoint

\c  toggle         BT index|AT address|ALL

Like BE and BD, but toggles breakpoints:
A disabled breakpoint is enabled, while an enabled breakpoint is disabled.


\S{cmdbl} BL command - List breakpoints

\c  list           BL [index|AT address|ALL]

BL lists a specific breakpoint given by its index,
or all used breakpoints if given the keyword ALL
or given neither an index nor the keyword.
When given the AT keyword,
all breakpoints with a matching linear address are listed.
(This differs from all other B commands,
which only select the first matching breakpoint when the AT keyword is given.)

When listing all breakpoints
only used breakpoints are displayed.

The output format for unused breakpoints is as follows:

\b "BP"

\b The byte index given as two hexadecimal digits

\b "Unused"


The output format for used breakpoints is as follows:

\b "BP"

\b The byte index given as two hexadecimal digits

\b A plus sign if the breakpoint is enabled, a minus sign if it is disabled.

\b "Lin=" followed by the linear address of this breakpoint.

\b The segmented address of this breakpoint.
Only displayed if the breakpoint was initially
specified with a segmented address, or
it had a preferred offset specified with the BP OFFSET= keyword
or to the BO command.

\b The breakpoint content byte given in parentheses (generally "CC").

\b "Counter=" followed by the breakpoint counter.

\b "ID: " followed by the breakpoint ID, if any.
Depending on the length the ID is shown on the first line
or on a second line.

\b "WHEN " followed by the breakpoint condition, if any.
This is always written to a line on its own.

Example output of BL:

\c -bp at 100 id = start
\c -bp at 103 counter = 4000
\c -bp at 105 when al == 7
\c -bl
\c BP 00 + Lin=01_BB70  1BA7:0100 (CC) Counter=8000, ID: start
\c BP 01 + Lin=01_BB73  1BA7:0103 (CC) Counter=4000
\c BP 02 + Lin=01_BB75  1BA7:0105 (CC) Counter=8000
\c  WHEN al == 7
\c -


\H{cmdbu} BU command - Break Upwards

\c break upwards   BU

This command, which is only supported by Debuggable lDebug builds (DDebug),
causes the debugger to execute an int3 instruction in its own code segment.
This breaks to the next debugger that was installed prior to DDebug.
Prior to the breakpoint, the message "Breaking to next instance." is displayed.

In non-debuggable lDebug builds, the following error message
is displayed instead:

\c -bu
\c Already in topmost instance. (This is no debugging build of lDebug.)
\c -


\H{cmdc} C command - Compare memory

\c compare         C range address

Given a range, the address of which defaults to DS,
and another address that also defaults to DS,
this command compares strings of bytes,
and lists the bytes that differ.


\H{cmdd} D command - Dump memory

\c dump            D [range]
\c dump bytes      DB [range]
\c dump words      DW [range]
\c dump dwords     DD [range]

Given a range, the address of which defaults to DS,
this command dumps memory in hexadecimal and as ASCII characters.
If the DCO option 4 is set, characters with the high bit set (80h to FFh)
are displayed as-is in the character dump.
Otherwise, they will be treated like control characters,
which means replaced by dots.

If no range is specified, the D command continues dumping at "d_addr"
(ADS:ADO),
which is updated by each D command to point after the last shown byte.

The default is for D to dump bytes.
After a DW or DD command,
the autorepeat and plain D (without a range) default to the last-used size.
If the default range should be used but the size should be reset to bytes,
the DB command can be used.
The D command with a range always acts the same as DB.


\H{cmddi} DI command - Dump Interrupts

\c dump interrupts DI[R][M][L] interrupt [count]

The DI command dumps interrupt vectors from the IVT (86M) or IDT (PM).
In PM, for the vectors 00h to 1Fh, the exception handlers are also dumped.
In 86 Mode, an interrupt chain is displayed
if more than one entrypoint is reachable from the topmost handler.
To make the next handler reachable, a handler
must match one of several header / entry formats:

\b IBM Interrupt Sharing Protocol (IISP) header (fully standard,
with 10EBh entrypoint and EBh jump to hardware reset
- this matches what Ralf Brown's AMIS programs recognise)

\b Non-standard IISP header

\b iHPFS-style uninstalled IISP header (EA90h entrypoint)

\b FreeDOS kernel relocation (near call followed by far jump immediate)

\b Just a far jump immediate


If the R is specified (directly after DI)
then 86 Mode handlers are dumped even if in PM.

If the M is specified
then MCB names are displayed.

If the L is specified
then AMIS interrupt lists are queried for
the interrupt number being dumped.
This is so that the involved multiplex numbers
and interrupt list indices can be displayed,
and also so that hidden chains can be dumped.
This means chains that are not reachable
from the topmost IVT handler, but are found through
the AMIS "Determine Chained Interrupts" call
(either 03h pointer or 04h list return).
The list index is displayed as FFFFh if
the handler was found with 03h pointer return.
Otherwise it indicates how many list entries
precede the found handler's entry.
For example, \cq{list:0000h} means that
the first list entry matched, and
\cq{list:0001h} means that the second list entry matched.

Specifying the L makes the debugger use
its auxiliary buffer.
That means the DIL command cannot be used
from the RE buffer if
either a T/TP/P WHILE condition is used,
or the T/TP/P silent buffer is used, or both.
In addition, note that with the default
buffer size, no more than about a 1000
handlers can be handled.
(The actual limit may be as low as 500 handlers
if a lot of hidden chains occur.)
If the limit is exceeded then the DIL command
will display an error.
The same error can also occur if the chain
loops, or references a single handler from
more than one other handler, or
a single handler is listed
by more than one multiplexer.


\H{cmddm} DM command - Dump MCBs

\c dump MCB chain  DM [segment]

The DM command dumps an MCB chain.
If not given a start MCB segment,
and the debugger is running as an 86-DOS application,
the start of DOS's MCB chain is used.
If given a start MCB segment, this is used as the starting MCB.
(Note: In current RxDOS builds, the start MCB is always at segment 60h.)

The DM command initially lists the debuggee's PSP.
This is only valid when the debugger is running as an 86-DOS application.

The MCB chain dump is continued until an MCB is encountered that
has neither an M nor a Z signature letter,
or the MCB address wraps around the 1 MiB boundary.
In particular, this means that a disabled UMB link MCB
(usually pointing to the MCB at segment 9FFFh
if there is no EBDA nor any pre-boot-loaded programs)
will not end the dump.

Example output:

\c -dm
\c PSP: 1A73
\c 02B4 4D 0008 0016    352 B SD
\c 02CB 4D 02CC 00BC    2 KiB COMMAND
\c 0388 4D 039D 0013    304 B SYSTEM
\c 039C 4D 039D 0034    832 B SYSTEM
\c 03D1 4D 04A3 0013    304 B LDEBUG
\c 03E5 4D 03E6 00BC    2 KiB COMMAND
\c 04A2 4D 04A3 15CF   87 KiB LDEBUG
\c 1A72 5A 1A73 858C  534 KiB DEBUGGEE
\c 9FFF 4D 0008 3100  196 KiB SC
\c D100 4D 0008 1EFF  123 KiB SC
\c F000 4D 02CC 0040   1024 B COMMAND
\c F041 4D 0000 0492   18 KiB
\c F4D4 4D 0000 0619   24 KiB
\c FAEE 4D 0000 0090    2 KiB
\c FB7F 5A 03E6 0080   2048 B COMMAND
\c -

The columns are as follows:

\n Segment address of MCB in hexadecimal.
Always one less than the segment of the memory block contents.

\n Signature letter in hexadecimal.
Usually 4D (\cq{M}) for linking MCB and 5A (\cq{Z}) otherwise.

\n Owner of the MCB in hexadecimal.
Values below 50h are special system values.
0 indicates an unused MCB.
8 is the usual \cw{SC}/\cw{SD}/\cw{S} system MCB owner.
Higher values are generally process segments.
A process segment is usually a memory block that is
preceded by an MCB, which is owned by that block itself.

\n Size in paragraphs of the MCB in hexadecimal.
A value of zero is valid and indicates an MCB
with an empty corresponding memory block.

\n Size in bytes or kibibytes, in decimal.

\n Name of the owner of this MCB.
Free MCBs do not have a name.
System MCBs have a name that is up to two letters long.
Otherwise, the name is read from the MCB owner's own MCB.
In this case the name is up to 8 letters long.


\H{cmddstring} DZ/D$/D#/DW# commands - Dump strings

\c display strings DZ/D$/D[W]# [address]

The D string commands each dump a string at a specified address,
which defaults to DS as the segment.

\b DZ displays an ASCIZ string, terminated by a byte with the value 0.

\b D$ displays a CP/M-style string, terminated by a dollar sign character $.

\b D# displays a Pascal-style string with a length count in the first byte.

\b DW# displays a string with a length count in the first word.


\H{cmde} E command - Enter memory

\c enter           E address [list]

The E command is used to enter values into memory.
If the list is specified, its contents are written
to the address specified.
Otherwise, the interactive enter mode starts at the address specified.

In the interactive enter mode, the segmented address is displayed,
and then the current byte value (2 hexadecimal digits)
found at that address yet.
Following the value a dot is displayed.
For example:

\c -e 100
\c 1FFE:0100  C3.

At this point the debugger accepts several different inputs:

\b One or two hexadecimal digits:
To enter a new value to be written at this address

\b A blank:
To write the new value (if any) and proceed to the next byte

\b A minus:
To write the new value (if any) and proceed to the prior byte

\b Carriage Return, Line Feed, or a period:
To write the new value (if any) and quit interactive enter mode

\b Backspace:
To delete the most recently entered digit of a candidate new value

\b All other inputs are ignored

After entering a blank, the debugger will either display
the next byte's current value in the same line or
start a new line with the current segmented address and
then the current byte value.
A new line is started if the current offset is divisible by 8.
For example, after entering 8 blanks:

\c -e 100
\c 1FFE:0100  C3.     CC.     CC.     CC.     CC.     CC.     CC.     CC.
\c 1FFE:0108  CC.

After entering a minus, the minus is displayed on the current line
and then (always) a new line is started to display
the new segmented address (with its offset decremented).
For example, entering a new value (\cq{A0}), then a blank,
then a minus, and then another new value (\cq{A1}), then a CR:

\c -e 100
\c 1FFE:0100  C3.A0   CC.-
\c 1FFE:0100  A0.A1
\c -


\H{cmdf} F command - Fill memory

\c fill            F range [RANGE range|list]

The F command fills memory with a byte pattern.
The first parameter is the range to fill.
The next parameter can be a list, in which case
it provides the pattern with which to fill.
If the RANGE keyword is provided then the pattern
is read from memory as indicated by
the range parameter that follows the keyword.
The pattern is repeated so as to fill the destination.
If the RANGE keyword is used, then the length of the
pattern address range is optional.
If the length is absent, it is assumed to equal that
of the destination range.


\H{cmdg} G command - Go

\c go              G [=address] [breakpts]

The G command runs the debuggee.
It can be given a start address (the segment of which defaults to CS),
prefixed by an equals sign,
in which case CS:EIP is set to that start address upon running.
Note that if there is an error parsing the command line,
CS:EIP is not changed.
Further, if a breakpoint fails to be written initially,
CS:EIP also is not changed.

The G command allows specifying breakpoints,
which are either segmented addresses
(86M or PM addresses depending on DebugX's mode)
or linear addresses prefixed by an "@ " or "@(",
similar to how the BP command allows a breakpoint specification.
G breakpoints are identified by their position in the command line,
as the 1st, 2nd, 3rd, etc.
By default, 16 G breakpoints are supported.

The G AGAIN command re-uses the breakpoints given
to the last (successfully parsed) G command.
It also allows an equals-sign-prefixed start address like the plain G command,
in front of the AGAIN keyword.
After the AGAIN keyword, additional breakpoints may be specified.

If the command repetition of G is used,
it is handled as if "G AGAIN" was entered,
that is it re-uses the same breakpoints as those given to the prior G command.

A G command that fails to parse will not modify the stored G breakpoint list.
If an error occurs during writing breakpoints,
the list will have been modified already however.

The G LIST command lists the breakpoints given
to the last (successfully parsed) G command.

The "content" byte in G LIST is usually CCh (the int3 instruction opcode),
but retains its original value
if a failure occurs during breakpoint byte restoration.

Example output of G LIST:

\c -g 100 103 105
\c AX=3000 BX=0000 CX=0200 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
\c DS=1BA7 ES=1BA7 SS=1BA7 CS=1BA7 IP=0103 NV UP EI PL ZR NA PE NC
\c 1BA7:0103 CD21              int     21
\c -g list
\c    1st G breakpoint, linear 0001_BB70  1BA7:0100, content CC
\c    2nd G breakpoint, linear 0001_BB73  1BA7:0103, content CC (is at CS:IP)
\c    3rd G breakpoint, linear 0001_BB75  1BA7:0105, content CC
\c -

The output is as follows:

\b The 1-based index ordinal of the point.

\b The linear address of the point.
(21-bit for Debug, 32-bit for DebugX.)

\b The segmented address of the point.
Only listed if the point was specified in a segmented form.
That is, if the point was specified with a "@ " or "@(" prefix
then no segmented address is saved along with it.
(Internally, the word or dword "preferred offset" variable
is set to all 1 bits then.)
In Protected Mode, the segment is specified as \cq{CS:} if
the code segment's base matches the preferred offset.
Otherwise, an R86M segment is shown with a dollar sign \cq{$} prefix
if the preferred offset matches any R86M segment.
Failing that the offset is shown with a prefix reading \cq{????:}.

\b The content byte. This is usually CCh.
However, if a breakpoint failed to be restored
then the original value is displayed here.

\b Indicator that this point matches the current CS:IP or CS:EIP.
This is only displayed if such a match is applicable.
Running G AGAIN when this is applicable will
step one time to bypass the corresponding point.

There is another G command:
After any equals sign, AGAIN keyword, and/or specified breakpoints,
the line can be ended with a REMEMBER keyword.
This saves the specified G breakpoint list
and then returns control to the user.
(The equals address, if any, is discarded.)
It allows preparing a G breakpoint list ahead of its use.
Auto-repeat, if enabled, will run like G AGAIN and
actually run the debuggee after a G REMEMBER command.


\H{cmdgoto} GOTO command - Control flow branch

\c goto            GOTO :label

The GOTO command can only be used when executing from a script file,
the command line buffer, or the RE buffer.
It lets execution continue at a different point in the file or buffer.
Labels are identified by lines that start with a colon,
followed by the alphanumeric label name,
and optionally followed by a trailing colon.
The destination label of the GOTO command may be specified
with or without the leading colon.

There are several special cases:

\b If the destination label is :SOF (Start Of File) then
the file or buffer completely rewinds to its start.

\b If the destination label is :EOF (End Of File) then
the file or buffer is closed.

\b If the destination label is not found then
the file or buffer is closed, along with an error message.


\H{cmdh} H command - Hexadecimal add/subtract values

\c hex add/sub     H value1 [value2 [...]]
\c base display    H BASE=number [GROUP=number] [WIDTH=number] value

The H command performs calculation and displays the result.
If a single expression is given then its value is displayed,
in hexadecimal and then in decimal.
If more than one expression is given then
two results are displayed, in hexadecimal only.
The first result is that which is calculated by adding all expressions.
The second result is calculated by subtracting all subsequent
expressions from the first expression's value.

If a value is above or equal to 8000_0000h then
along each display of that value, the value interpreted
as a negative two's complement number is listed in parentheses.

If the form with the \cw{BASE} keyword is given
then only one number is displayed.
The specified base may be between 2 and 36, inclusive.
If the \cw{GROUP} keyword is also used then digits are grouped.
The group separator is the underscore, \cq{_}.
The grouping number must be below or equal 32 (20h).
The default grouping is none, same as \cw{GROUP=0}.
If the \cw{WIDTH} keyword is also used then
at least that many digits are displayed.
The width must be below or equal 32 (20h).
The default width is one digit, same as \cw{WIDTH=0} or \cw{WIDTH=1}.

Examples:

\c -h 1
\c 0001  decimal: 1
\c -h 1 1
\c 0002  0000
\c -h 1 1 1
\c 0003  FFFFFFFF (-0001)
\c -h 1 + 2 * 3
\c 0007  decimal: 7
\c -h cs * 10
\c 0001A730  decimal: 108336
\c -h -26
\c FFFFFFDA (-0026)  decimal: 4294967258 (-38)
\c -h base=2 group=8 AA55
\c 10101010_01010101
\c -h base=2 group=4 width=#16 #1234
\c 0000_0100_1101_0010
\c -h base=#10 group=3 400*400
\c 1_048_576
\c -h base=3 group=3 FFFF_FFFF
\c 102_002_022_201_221_111_210
\c -


\H{cmdi} I command - Input from port

\c input           I[W|D] port

The I commands input from an x86 port.
The port can be any number between 0 and FFFFh.
Plain I inputs a byte from the specified port.
The IW and ID commands input a word or dword respectively.


\H{cmdif} IF command - Control flow conditional

\c if numeric      IF [NOT] (cond) THEN cmd
\c if script file  IF [NOT] EXISTS Y file [:label] THEN cmd

The IF command allows specifying a conditionally executed command.
This is especially useful for creating conditional control flow branches
with the GOTO command (see \k{cmdgoto}).

For the first form, the condition is a numeric expression.
If it evaluates to non-zero it is considered true.
If the NOT keyword is absent then a true condition expression
leads to executing the THEN command.
With the NOT keyword present the logic is reversed.
Note that if an error occurs in parsing,
the THEN command is not executed,
regardless of whether the NOT keyword is present.

The second form specifies a script file
in the same format as accepted by the Y command (refer to \k{cmdy}).
A label may be specified behind the filename, as for the Y command.
If the file is found, and contains the specified label if any,
then the EXISTS clause is considered true.
Depending on the presence of the NOT keyword
the THEN command is executed next, or skipped.
Note that if an error occurs in parsing,
the THEN command is not executed,
regardless of whether the NOT keyword is present.

Likewise, if an unanticipated error occurs during access
then the THEN command is not executed.
Anticipated errors include:

\n The drive or ROM-BIOS unit cannot be accessed at all.
(Determined by sector 0 being unreadable.)

\n The specified partition is not found.

\n A specified directory is not found.

\n The file is not found.

\n A DOS error occurs opening the file.

\n The file is empty.

\n A specified label is not found.


\H{cmdlp} L command - Load Program

\c load program    L [address]


\H{cmdls} L command - Load Sectors

\c load sectors    L address drive sector count


\H{cmdm} M command - Move memory

\c move            M range address


\H{cmdmc} M command - Set Machine mode

\c 80x86/x87 mode  M [0..6|C|NC|C2|?]


\H{cmdn} N command - Set program Name

\c set name        N [[drive:][path]progname.ext [parameters]]


\H{cmdo} O command - Output to port

\c output          O[W|D] port value

The O commands output to an x86 port.
The port can be any number between 0 and FFFFh.
Plain O outputs a byte to the specified port.
The OW and OD commands output a word or dword respectively.
The value to write is specified by the second expression.


\H{cmdp} P command - Proceed

\c proceed         P [=address] [count [WHILE cond] [SILENT [count]]]

The P command causes debuggee to run a proceed step.
This is the same as tracing (T command) for most instructions,
but behaves differently for "call", "loop", and repeated string instructions.
For these, a proceed breakpoint is written behind the instruction
(similarly to how the G command writes breakpoints),
and the debuggee is run without the Trace Flag set.

Like for the G command, a start address can be given to P
prefixed by an equals sign.
Next, a count may be specified,
which causes the command to execute as many P steps as the count indicates.

After a count, a WHILE keyword may be specified,
which must be followed by a conditional expression.
Execution will only continue if the WHILE expression evaluates to true.

After a count (when no WHILE is given) or after a WHILE condition,
a SILENT keyword and optional count may be given.
In this case, the debugger buffers the register dump and
disassembly output of the executed steps,
until control returns to the debugger command line.
Then, the last dumps stored in the buffer are displayed.
If a non-zero count is given, at most that many register dumps are displayed.


\H{cmdq} Q command - Quit

\c quit            Q


\H{cmdr} R command - Display and set Register values

\c register        R [register [value]]

The R command without any register specified dumps the current registers,
either displayed as 16-bit or 32-bit values (depending on the RX option),
and disassembles the instruction at the current CS:(E)IP location.

R with a register, named debugger variable, or memory variable
(of the form BYTE/WORD/3BYTE/DWORD [segment:offset])
displays the current value
of the specified variable.
It then displays a prompt, allowing the user to
enter a new value for that variable.
Entering a dot (.) or an empty line returns to the default debugger command line.

R with a variable, followed by a dot (.),
only displays the current value of that variable.

R with a variable, followed by an optional equals sign,
and followed by an expression,
evaluates the expression and assigns its resulting value to the variable.
The equals sign may instead be a binary operator with a trailing
equals sign, which is handled as an assignment operator.

Examples:

\c -r ax .
\c AX 0000
\c -r ax
\c AX 0000  :1
\c -r ax
\c AX 0001  :.
\c -r ax += 4
\c -r ax
\c AX 0005  :
\c -r word [cs:0]
\c WORD [1867:0000] 20CD  :
\c -r dif .
\c DIF 0100B00B
\c -


\S{cmdre} RE command - Register dump Extended

\c R extended      RE

The RE command runs the RE buffer commands. Refer to \k{helpre}.


\S{cmdredot} RE buffer commands

\c RE commands     RE.LIST|APPEND|REPLACE [commands]

RE.LIST lists the RE buffer contents in a way that can be re-used
as input to RE.REPLACE.

RE.APPEND appends the following commands to the RE buffer.

RE.REPLACE replaces the RE buffer with the following commands.

The RE buffer usage is described in the ?RE help page (\k{helpre}).


\H{cmdrm} RM command - Display MMX Registers

\c MMX register    RM


\H{cmdrn} RN command - Display FPU Registers

\c FPU register    RN


\H{cmdrx} RX command - Toggle 386 Register Extensions display

\c toggle 386 regs RX


\H{cmds} S command - Search memory

\c search          S range [REVERSE] [RANGE range|list]

The S command searches memory for a byte string.
The first range specifies the search space.
By default, searching will begin at the bottom of the search space
and move upwards.
If a REVERSE keyword is specified after the range then searching
will begin at the top of the search space moving downwards.
The search string is specified either with the RANGE keyword
followed by another range, or as a list of byte values.

The read-only variable SRC (Search Result Count) will receive
the 32-bit value that is the amount of matched occurrences.
The variable SRS0 receives the first Search Result Segment.
Likewise SRO0 receives the first Search Result Offset.
SRO1 to SROF hold subsequent Search Result Offsets.
SRO is an alias to SRO0. SRO variables are 32-bit in
the _PM build lDebugX, 16-bit otherwise.
Unused SRO variables are zeroed out by a successful search.

The display of search results is as follows:

\b First, the result's segmented address.

\b Then, a hexadeximal dump of the 16 bytes that
follow the search string match at this point.

\b Finally, the ASCII character dump of these 16 bytes.

There is an option to disable the data dump so as to
only display the match addresses.
If the bit 80_0000h is set in the DCO variable then
the data dump is suppressed.


\H{cmdsleep} SLEEP command

\c sleep           SLEEP count [SECONDS|TICKS]

The SLEEP command sleeps for the indicated length.
The duration defaults to seconds.
If the TICKS keyword is specified then the duration
is taken to mean timer ticks.
(A timer tick is about 1/18 seconds.)
If the input is from DOS or serial I/O
then Control-C from the input terminal
may be used to cancel the sleep.


\H{cmdt} T command - Trace

\c trace           T [=address] [count [WHILE cond] [SILENT [count]]]

The T command is similar to the P command.
However, T traces most instructions.
Depending on the TM option, interrupt instructions
are also traced (into the interrupt handler) or proceeded past.

\S{cmdtp} TP command - Trace/Proceed past string ops

\c trace (exc str) TP [=address] [count [WHILE cond] [SILENT [count]]]

The TP command is alike the T command, but
proceeds past repeated string instructions like the P command would.


\H{cmdtm} TM command - Show or set Trace Mode

\c trace mode      TM [0|1]


\H{cmdtsr} TSR command - Enter TSR mode

\c enter TSR mode  TSR


\H{cmdu} U command - Disassemble

\c unassemble      U [range]


\H{cmdwp} W command - Write Program

\c write program   W [address]


\H{cmdws} W command - Write Sectors

\c write sectors   W address drive sector count


\H{cmdx} X commands - Expanded Memory (EMS) commands

\c expanded mem    XA/XD/XM/XR/XS, X? for help


\H{cmdy} Y command - Run script file

\c run script      Y [partition/][scriptfile] [:label]

The Y command runs a script file.
The script file is specified in two different ways,
depending on whether the debugger is running as an 86-DOS application
or as a boot-loaded kernel replacement.

\b If running as an application, the script name is a regular pathname.
It may be quoted with doublequotes if the pathname includes blanks.
If the indicated drive supports long filenames (LFNs) then
the debugger will first try to open the pathname as an LFN.

\b Otherwise, the script name may start with a partition specification to use.
(Refer to the ?BOOT help page in \k{helpboot} for partition specifications.)
Then, the pathname relative to that partition's root directory follows.
Long filenames are not supported.
Note that it is not valid to run an empty script file when boot-loaded.

Further, a label may be specified to cause execution to start at that
label instead of at the start of the file.
This is equivalent to placing a \cq{GOTO :label} command
at the start of the script file.
The colon to indicate a label is required.

If execution already is within a script file,
then the Y command may be run with only a label
(again with the colon required).
In that case, the current script file is opened in a subsequent level
(handle or boot-loaded script file context) and execution starts at that label.

Opening a script file as DOS application only works
while DOS is available (InDOS not set).
Additionally, if during script file execution
DOS becomes unavailable (InDOS is set)
then the script file execution is paused.
It is resumed once DOS becomes available again.
(Control-C with a non-zero IOL variable may still
be used to cancel script file execution.
DOS is called to close affected handles only if DOS is available.)


\C{varref} Variable Reference

\H{varregisters} Registers

All debuggee registers can be accessed numerically:

\b \cw{al}, \cw{cl}, \cw{dl}, \cw{bl},
\cw{ah}, \cw{ch}, \cw{dh}, \cw{bh}

\b \cw{ax}, \cw{cx}, \cw{dx}, \cw{bx},
\cw{sp}, \cw{bp}, \cw{si}, \cw{di}

\b \cw{eax}, \cw{ecx}, \cw{edx}, \cw{ebx},
\cw{esp}, \cw{ebp}, \cw{esi}, \cw{edi}

\b \cw{es}, \cw{cs}, \cw{ss}, \cw{ds}, \cw{fs}, \cw{gs}

\b \cw{fl}, \cw{efl}, \cw{ip}, \cw{eip}

Each 16-bit register can be used in a register pair, such as:

\b \cw{dxax}

\b \cw{bxcx} (used by \cw{L} load program and \cw{W} write program commands)

\b \cw{sidi}

\b \cw{csip}


\H{varoptions} Options

\S{vardco} DCO - Debugger Common Options

\S{vardcs} DCS - Debugger Common Startup options

\S{vardif} DIF - Debugger Internal Flags

\S{vardao} DAO - Debugger Assembly Options

\S{vardas} DAS - Debugger Assembly Startup options

\S{vardpi} DPI - Debugger Parent Interrupt 22h

\S{vardpr} DPR - Debugger PRocess

\S{vardpp} DPP - Debugger Parent Process

\S{vardps} DPS - Debugger Process Selector

0 while in Real or Virtual 8086 Mode, debugger process selector otherwise.
(The process selector addresses DebugX's PSP and DATA ENTRY section.)


\H{varcounts} Default step counts

\dt PPC

\dd Proceed command (\k{cmdp}) default step count

\dt TPC

\dd Trace/Proceed command (\k{cmdtp}) default step count

\dt TTC

\dd Trace command (\k{cmdt}) default step count

All of these are doublewords and default to 1.
For the respective commands, these counts specify
the number of steps to take if none is specified explicitly.
This includes when a command is run by autorepeat,
refer to \k{cmdautorepeat}.
If one of these is set to zero then it is an error
to not specify a count explicitly for
the corresponding command.


\H{varlimits} Limits

\S{varrelimit} RELIMIT - RE buffer execution command limit

Doubleword.
Default is 256.
If this many commands are executed from the RE buffer,
the execution is aborted and the command that called RE is continued.

\S{varrecount} RECOUNT - RE buffer execution command count

Doubleword.
This is reset to zero when RE buffer execution starts.
Each time a command is executed from the RE buffer,
this variable is incremented.
If it reaches the value of RELIMIT,
RE buffer execution is aborted.


\H{varreturncodes} Return Codes

\S{varrc} RC - Return Code

Word.
This holds the most recent command's return code.
If the most recent command succeeded, then this is zero.

\S{varerc} ERC - Error Return Code

Word.
This holds the most recent non-zero return code.


\H{varaddresses} Addresses

\S{var_a_addr} A address (AAS:AAO)

AAS: word, AAO: doubleword.
Default address for the assembler.
Updated to point after each assembled instruction.

\S{var_d_addr} D address (ADS:ADO)

Default address for memory dumping.
Updated to point after each dumped memory content.

\S{var_b_addr} Address behind R disassembly (ABS:ABO)

\S{var_u_addr} U address (AUS:AUO)

Default address for the disassembler.

\S{var_e_addr} E address (AES:AEO)

Default address for memory entry.

\S{var_z_addr} DZ address (AZS:AZO)

Default address for DZ command, ASCIZ strings. Terminated by zero byte.

\S{var_c_addr} D$ address (ACS:ACO)

Default address for D$ command, CP/M strings. Terminated by dollar sign \cq{$}.

\S{var_p_addr} D# address (APS:APO)

Default address for D# command, Pascal strings. Prefixed by length count byte.

\S{var_w_addr} DW# address (AWS:AWO)

Default address for DW# command. Prefixed by length count word.

\S{var_x_addr} DX address (AXO)

Default address for DX command. (Only included in DebugX.)


\H{vario} I/O configuration

\S{varior} IOR - I/O Rows

Byte.
Default 1.
Sets the number of rows of the terminal used by DOS or BIOS output.
Setting this to zero disables paging to the DOS or BIOS output.
Setting this to 1 uses the automatic selection.
That means the BIOS Data Area byte at address 484h, plus one, is used.
If using that byte and it is zero, paging is disabled.

\S{varioc} IOC - I/O Columns

Byte.
Default 1.
Sets the number of columns of the terminal used by BIOS input.
Setting this to zero selects a default (80).
Setting this to 1 uses the automatic selection.
That means the BIOS Data Area word at address 44Ah is used.
This is used by the line input handling
if inputting from the BIOS terminal (int 16h, int 10h),
or if inputting from a DOS terminal when DCO flag 800h is set.

\S{varios} IOS - I/O Circular Keypress Buffer Start

Word.
Default 0 or 1Eh.
Indicates where the ROM-BIOS's circular keypress buffer starts.
Value can be nonzero to force a particular offset in segment 40h.
Value can be zero to force using the value at \cw{word [40h:80h]},
using an extension not available on all systems.

On startup the debugger checks whether the extension values are valid.
If they are then the default of the IOS variable is left as zero.
Otherwise, the default is set to 1Eh, which is the default buffer location.

This variable is used to check for Ctrl-C keypresses if the InDOS mode is on
(either InDOS flag set, DCO flag 8 set, or in bootloaded mode)
and serial I/O is not in use
and the flag DCO3 2000_0000h is set.
Setting this variable nonzero and equal to IOE disables Ctrl-C checking.

Modifying this variable should only be done while it is not in use.
That means using DOS for input, using serial I/O for input,
or clearing the DCO3 flag 2000_0000h.
Modifying this variable and the IOE variable should be done together,
so that they are valid together when in use.

\S{varioe} IOE - I/O Circular Keypress Buffer End

Word.
Default 0 or 3Eh.
Indicates where the ROM-BIOS's circular keypress buffer ends.
Value can be nonzero to force a particular offset in segment 40h.
Value can be zero to force using the value at \cw{word [40h:82h]},
using an extension not available on all systems.

Refer to IOS description above.

\S{variol} IOL - I/O Amount of Script Levels to Cancel

Word.
Default 255.
Indicates how many levels of script files and RE buffer execution
to cancel when a Control-C input or critical DOS error
is detected by the debugger.
The effective value will be incremented by one
if IOF flag 1 is set and RE buffer execution is in progress.

Zero indicates to only cancel the current command.
One indicates to cancel the current command,
plus the RE buffer execution if any,
else up to one level of script file execution.
Two indicates to cancel two levels of execution:
either the RE buffer execution
and one level of script file execution,
or up to two levels of script file execution.

The debugger always cancels RE buffer execution first
if it is in progress.
Next, the innermost script file execution is cancelled, if any.

\S{variof} IOF - I/O Flags

Word.
Default 1.
Flags for I/O handling.
Currently defined:

\dt 1

\dd Extra IOL level for RE buffer execution.
If set, RE buffer execution being in progress
increments the effective value of the IOL variable.


\H{varserial} Serial configuration

\S{vardsr} DSR - Debugger Serial Rows

Byte.
Default 24.
Sets the number of rows of the terminal connected via serial port.
Setting this to zero disables paging to the serial port.
Setting this to 1 uses the IOR variable handling.

\S{vardsc} DSC - Debugger Serial Columns

Byte.
Default 80.
Sets the number of columns of the terminal connected via serial port.
Setting this to zero selects a default (80).
Setting this to 1 uses the IOC variable handling.
This is used by the line input handling.

\S{vardst} DST - Debugger Serial Timeout

Byte.
Default 15.
This gives the number of seconds that
the KEEP prompt upon serial connection waits.
Setting this to zero waits at the prompt forever.

\S{vardsf} DSF - Debugger Serial FIFO size

Byte.
Default 16.
This gives the size of the 16550A's built-in TX FIFO to use.
Set to 15 if using dosemu before revision gc7f5a828 2019-01-22,
see \W{https://github.com/stsp/dosemu2/issues/748}{https://github.com/stsp/dosemu2/issues/748}.

\S{vardspvi} DSPVI - Debugger Serial Port Variable Interrupt number

Byte.
Default 0Bh, corresponding to COM2.
Use 0Ch for COM1.
This specifies the interrupt number to hook
so as to be notified of serial events.
The use of this variable occurs
only when connecting to serial I/O.
The value at that point in time is cached
for as long as the serial connection is in use.

\S{vardspvm} DSPVM - Debugger Serial Port Variable IRQ Mask

Word.
Default 0000_1000b, corresponding to COM2.
Use 0001_0000b for COM1.
This specifies the IRQ mask of which IRQs to enable.
The low 8 bits correspond to IRQ #0 to #7 and
the high 8 bits correspond to IRQ #8 to #15.
If any bit of the high 8 bits is set then generally
the bit 0100b should be set too, to enable the chained PIC.
This circumstance is not automatically detected.
The use of this variable occurs
only when connecting to serial I/O.
The value at that point in time is cached
for as long as the serial connection is in use.

\S{vardspvp} DSPVP - Debugger Serial Port Variable base Port

Word.
Default 02F8h, corresponding to COM2.
Use 03F8h for COM1.
This specifies the I/O port base to address the UART.
The use of this variable occurs
only when connecting to serial I/O.
The value at that point in time is cached
for as long as the serial connection is in use.

\S{vardspvd} DSPVD - Debugger Serial Port Variable Divisor latch

Word.
Default 12, corresponding to 9600 baud.
This specifies the DL value to set during initialisation.
The use of this variable occurs
only when connecting to serial I/O.

\S{vardspvs} DSPVS - Debugger Serial Port Variable Settings

Byte.
Default 0000_0011b, corresponding to 8n1.
(8n1 = 8 data bits, no parity, 1 stop bit.)
This specifies the settings to set up in LCR.
The high bit (80h) generally must be clear.
The use of this variable occurs
only when connecting to serial I/O.

\S{vardspvf} DSPVF - Debugger Serial Port Variable FIFO select

Byte.
Default 0.
This specifies what to write to the FCR.
The low 3 bits (07h) generally must be clear.
The use of this variable occurs
only when connecting to serial I/O.
The value at that point in time is cached
for as long as the serial connection is in use.


\H{vardebug1} _DEBUG1 variables

These variables are not supported by default.
The build option _DEBUG1 must be enabled to include them.
The Test Counter variables work similarly to permanent breakpoint counters:

\b If the counter AND-masked with 7FFFh is zero, it is at a terminal state.

\b If the counter is not yet at a terminal state, it is decremented.

\b If the counter is decremented to zero, it triggers.

\b If the counter is decremented to 8000h or already at 8000h, it triggers.

The default values for all counters and addresses is zero.

\S{vartrx} TRx - Test Readmem variables

If a fault is injected into readmem, it returns the value given in TRV.

\dt TRC - Test Readmem Counter

\dd Word. Each of the TRC0 to TRCF counters
gives one counter for readmem fault injection testing.

\dt TRA - Test Readmem Address

\dd Doubleword. Each of the TRA0 to TRAF counters
gives one linear address for readmem fault injection testing.

\dt TRV - Test Readmem Value

\dd Byte. Default 0.
If a readmem fault is injected, this byte value
is returned by the read instead of the actual memory content.

\S{vartwx} TWx - Test Writemem variables

If a fault is injected into writemem, it returns failure (CY).

\dt TWC - Test Writemem Counter

\dd Word. Each of the TWC0 to TWCF counters
gives one counter for writemem fault injection testing.

\dt TWA - Test Writemem Address

\dd Doubleword. Each of the TWA0 to TWAF counters
gives one linear address for writemem fault injection testing.

\S{vartlx} TLx - Test getLinear variables

If a fault is injected into getlinear, it returns failure (CY).

\dt TLC - Test getLinear Counter

\dd Word. Each of the TLC0 to TLCF counters
gives one counter for getlinear fault injection testing.

\dt TLA - Test getLinear Address

\dd Doubleword. Each of the TLA0 to TLAF counters
gives one linear address for getlinear fault injection testing.

\S{vartsx} TSx - Test getSegmented variables

If a fault is injected into getsegmented, it returns failure (CY).

\dt TSC - Test getSegmented Counter

\dd Word. Each of the TSC0 to TSCF counters
gives one counter for getsegmented fault injection testing.

\dt TSA - Test getSegmented Address

\dd Doubleword. Each of the TSA0 to TSAF counters
gives one linear address for getsegmented fault injection testing.


\H{vardebug3} _DEBUG3 variables

These variables are not supported by default.
The build option _DEBUG3 must be enabled to include them.
These variables are used to test the read-only masking.
Read-only masking makes it so that bits given in the mask are read-only.
Bits that are clear in the mask are writable.

\S{varmt0} MT0 - Mask Test 0

Doubleword. Default 0. Mask AA55_AA55h.

\S{varmt1} MT1 - Mask Test 1

Doubleword. Default 0011_0022h. Mask 00FF_00FFh.


\H{varyy} Y command variables

Y command variables can be used when
the Y command (as application or bootloaded)
has been used to open a script file.
YSx (Y Script) variables are generic and refer to whatever Y file is opened.
YBx (Y Bootloaded script) variables refer to opened Y files while bootloaded.
YHx (Y Handle script) variables refer to opened Y files as application.

\S{varysf} YSF - Y Script Flags

Word. Partially read-write, partially read-only.

Flag 4000h controls whether script file input is displayed or not.
Prepending an AT sign (@) to a line that is read from a script file
will hide the input of that line.
Setting YSF flag 4000h will hide all input lines instead.
The effect is similar to prepending @ to every line.

YSF variables are only available while executing script files.


\H{varv} V variables - Variables with user-defined purpose

Doubleword. Default zero. V0 to VF or V00 to VFF each specify one variable.
It is valid to refer to any V variable using an index expression.
Index expression means that the variable name (\cw{V})
is immediately followed by an opening parenthesis,
followed by a numeric expression which evaluates
to a number below 100h.


\H{varprocess} PSP variables

\S{varpsp} PSP - Process Segment Prefix

\S{varppr} PPR - Process PaRent

\S{varppi} PPI - Process Parent Interrupt 22h


\H{varsr} SR variables - Search Results

\S{varsrc} SRC - Search Result Count

Doubleword. Read only. Amount of matches found by last S command.

\S{varsrs} SRS - Search Result Segment

Word. Read only. SRS0 to SRSF each specify one variable.
Search result segments of last S command's matches.

\S{varsro} SRO - Search Result Offset

Word or doubleword (DebugX). Read only.
SRO0 to SROF each specify one variable.
Search result offsets of last S command's matches.
It is valid to refer to any SRO variable using an index expression.
Index expression means that the variable name (\cw{SRO})
is immediately followed by an opening parenthesis,
followed by a numeric expression which evaluates
to a number below 10h.


\H{varaccess} Access variables

These variables can be left out of the build.
The build option \cw{_MEMREF_AMOUNT} must be enabled to include them.

\S{varaccess-readadr} READADR

Doubleword. Read only. READADR0 to READADR3 each specify one variable.
(Amount of READADR variables can be configured at build time
with the option _ACCESS_VARIABLES_AMOUNT, which defaults to 4.)
Linear addresses of string, stack, or explicit memory operand reads.
Initialised by the R command.
Unused variables are reset to zero by the R command.
It is valid to refer to any READADR variable using an index expression.
Index expression means that the variable name (\cw{READADR})
is immediately followed by an opening parenthesis,
followed by a numeric expression which evaluates
to a number below 4.

\S{varaccess-readlen} READLEN

Doubleword. Read only. READLEN0 to READLEN3 each specify one variable.
Length of string, stack, or explicit memory operand reads.
Initialised by the R command.
Unused variables are reset to zero by the R command.
It is valid to refer to any READLEN variable using an index expression.

\S{varaccess-writadr} WRITADR

Doubleword. Read only. WRITADR0 to WRITADR3 each specify one variable.
Linear addresses of string, stack, or explicit memory operand writes.
Initialised by the R command.
Unused variables are reset to zero by the R command.
It is valid to refer to any WRITADR variable using an index expression.

\S{varaccess-writlen} WRITLEN

Doubleword. Read only. WRITLEN0 to WRITLEN3 each specify one variable.
Length of string, stack, or explicit memory operand writes.
Initialised by the R command.
Unused variables are reset to zero by the R command.
It is valid to refer to any WRITLEN variable using an index expression.


\C{intref} Interrupt Reference

\H{intmandatory} Mandatory interrupt hooks

\b Interrupt 0 - Divide error

\b Interrupt 1 - Trace

\b Interrupt 3 - Breakpoint

\b Interrupt 6 - Invalid opcode

\b Interrupt 18h - Diskless boot hook

\b Interrupt 19h - Boot load

These interrupts are always hooked by the debugger.
For the non-_DEBUG builds they are
hooked during initialisation and
the debugger attempts to unhook them when quitting.
The highest 8 bits of the dword variable DCO4
control whether they are unhooked
only if reachable (bits in DCO4 zero),
or forcibly so if not reachable (bits in DCO4 ones).
If not forcibly unhooking and an interrupt handler
is not reachable then the Q command fails.

For DDebug, these interrupts are hooked within
the \cw{run} function and unhooked
before the \cw{run} function returns.
This unhooking in DDebug is always forcible;
that is, if not reachable then the interrupts
are unhooked by simply updating
the IVT entries with whatever handlers are
stored as the next vectors in DDebug's entrypoints.


\H{intserial} Serial interrupt

This interrupt hook is optional.
Setting the DCO flag 4000h (enable serial I/O)
instructs the debugger
to set up this interrupt hook.
Clearing the flag or using the \cw{Q} command
instructs the debugger to unhook its handler.
The DCO4 flag 1_0000h controls whether the
interrupt unhooking is forcible (flag set)
or not (flag clear).

The exact interrupt number used as serial interrupt
depends on the DSPVI variable
at the point in time at which serial I/O is enabled.
The default is interrupt 0Bh, corresponding to COM2.


\H{int2F} Interrupt 2Fh - Multiplex (DPMI entrypoint)

This interrupt is only hooked by DebugX.
This interrupt hook is optional.
Setting the DCO4 flag 2 instructs the debugger
to set up this interrupt hook.
The debugger tries to hook this interrupt
if it runs application code in Real or Virtual 86 Mode.
Clearing the flag,
entering Protected Mode, or using the \cw{Q} command
instructs the debugger to unhook its handler.
The DCO4 flag 2_0000h controls whether the
interrupt unhooking is forcible (flag set)
or not (flag clear).

This interrupt is hooked to intercept calls to
function 1687h, used to detect the DPMI entrypoint.
DebugX attempts to hook this service to
return its own entrypoint to the caller.
The hook may fail if the DPMI host handles
interrupt 2Fh calls before chaining to the
86 Mode handler chain.
(MS Windows 4.x and older dosemu are reported to do this.)


\H{int8} Interrupt 8 - Timer

This interrupt hook is optional.
Setting the DCO4 flag 4 instructs the debugger
to set up this interrupt hook.
Clearing the flag or using the \cw{Q} command
instructs the debugger to unhook its handler.
The DCO4 flag 4_0000h controls whether the
interrupt unhooking is forcible (flag set)
or not (flag clear).

This interrupt is used to detect
the double Control-C via serial I/O condition.
If the serial I/O handler of the debugger
receives two Control-C keypresses
while the debugger is busy running an application
then the interrupt 8 hook will interrupt the run.

This interrupt is also used to detect
the Control pressed for 5 seconds condition.
Similarly to the serial I/O double Control-C condition,
this will make the debugger interrupt the current run.


\H{int2D} Interrupt 2Dh - Alternate Multiplex Interrupt

This interrupt hook is optional.
Setting the DCO4 flag 8 instructs the debugger
to set up this interrupt hook.
Clearing the flag or using the \cw{Q} command
instructs the debugger to unhook its handler.
The DCO4 flag 8_0000h controls whether the
interrupt unhooking is forcible (flag set)
or not (flag clear).

This interrupt allows other programs to detect
the debugger in the AMIS interface.
The vendor string is \cq{ecm} and the product string \cq{lDebug}.
The description string contains the same display name
and version as the command line help.
There are two real uses of this.
First, the
AMIS function 4, which will return
the list of interrupt entrypoints of the debugger.
Second, lDebug's private AMIS function 30h.
It is described in the next section.

This interrupt hook only succeeds if the current handler is valid.
That is, an offset not equal to FFFFh and a segment not equal to zero.
Another condition is that the debugger needs to detect
an unused AMIS multiplex number to allocate.
This is done automatically when hooking the interrupt.
If either condition fails then a message is displayed
and the debugger clears the DCO4 flag 8 on its own.

The TRYAMISNUM variable is a writable byte variable.
It defaults to 0.
Its content is tried first when searching a free multiplex number.
After that the debugger currently will search
starting from number 0 up to 255.

The AMISNUM variable is a read-only byte variable.
It contains the actually used multiplex number
while the DIF4 flag 8 is set.
Otherwise its content is not used and likely stale.

\S{int2Dfunc30} AMIS private function 30h - Update IISP Header

This function is provided for use by our programs
that use AMIS multiplexers and
interrupt handler entrypoints with IISP headers.
All TSRs (including RxANSI, lClock, SEEKEXT, KEEPHOOK,
FDAPM, FreeDOS SHARE) and SHUFHOOK use this function.
(Note that the debugger itself does not yet use this function.)

\c lDebug - Update IISP Header
\c INP:    al = 30h
\c         ds:si -> source IISP header (or pseudo header)
\c         es:di -> destination IISP header
\c OUT:    al = FFh to indicate suppported,
\c          si and di both incremented by 6
\c          destination's ieNext field updated from source
\c         al != FFh if not supported,
\c          si and di unchanged
\c CHG:    -
\c REM:    This function is intended to aid in debugging
\c          handler re-ordering, removal, or insertion.
\c          The 32-bit far pointer needs to be updated
\c          as atomically as possible to avoid using
\c          an incorrect pointer.
\c         Test case: Run a program such as our TSRs'
\c          uninstaller or SHUFHOOK and step through it
\c          with "tp fffff" when operating on something
\c          crucial such as interrupt 21h. Without this
\c          function the machine will crash!
\c         To enable this function to be called, enter
\c          the command "r dco4 or= 8" first (install our
\c          AMIS multiplexer handler).
\c         Other workaround: Use SILENT for TP and disable
\c          DCO3 flag 4000_0000 (do not call int 21.0B to
\c          check for Ctrl-C status).
\c         Yet another workaround: Set flag DCO 8 (enable
\c          fake InDOS mode, avoid calling int 21h).
\c REM:    The source may be a pseudo IISP header. In this
\c          case the ieEntry field should hold 0FEEBh
\c          (jmp short $) and the ieSignature field
\c          should indicate the source, eg "VT" for the IVT
\c          or "NH" for inserting a New Handler.


\C{serviceref} Service Reference

These are the sercices called by the debugger.


\H{service10} Interrupt 10h

Used for output while InDOS, DCO flag 8 set, or bootloaded.

\dt Function 02h

\dd Set cursor position
(only used if highlighting)

\dt Function 03h

\dd Get cursor position
(only used if highlighting,
indicates to highlight to int 10h if supported)

\dt Function 08h

\dd Get video attribute
(only used if highlighting)

\dt Function 09h

\dd Set video attribute
(only used if highlighting)

\dt Function 0Eh

\dd Teletype output


\H{service16} Interrupt 16h

Used for input while InDOS, DCO flag 8 set, or bootloaded.

\dt Function 00h

\dd Read keypress (wait until keypress available)

\dt Function 01h

\dd Read keypress (return if no keypress available)


\H{service2F} Interrupt 2Fh

\dt Function 1680h

\dd Idle (Release timeslice to multitasker)

\dt Function 1687h

\dd Get DPMI entrypoint
(used and hooked by lDebugX)

\dt Function 4A06h

\dd RPL adjust base memory size
(called by booted debugger if RPL signature present)


\H{service12} Interrupt 12h

Called by booted debugger to determine base memory size.


\H{servicepm31} Protected Mode Interrupt 31h

Used by lDebugX while in Protected Mode.

\dt Function 0000h

\dt Function 0002h

\dd Get selector from segment

\dt Function 0003h

\dt Function 0006h

\dd Get segment base

\dt Function 0007h

\dd Set segment base

\dt Function 0008h

\dt Function 0009h

\dt Function 000Ah

\dt Function 000Bh

\dd Get descriptor

\dt Function 000Ch

\dd Set descriptor

\dt Function 0200h

\dd Get 86M interrupt vector

\dt Function 0201h

\dd Set 86M interrupt vector

\dt Function 0202h

\dd Get PM exception vector

\dt Function 0203h

\dd Set PM exception vector

\dt Function 0204h

\dd Get PM interrupt vector

\dt Function 0205h

\dd Set PM interrupt vector

\dt Function 0300h

\dd Call Real/Virtual 86 Mode interrupt

\dt Function 0305h

\dd Get raw mode switch save state addresses

\dt Function 0306h

\dd Get raw mode switch addresses

\dt Function 0900h

\dd Disable Virtual Interrupt Flag

\dt Function 0901h

\dd Enable Virtual Interrupt Flag

\dt Function 0902h

\dd Get Virtual Interrupt Flag


\H{servicepm2F} Protected Mode Interrupt 2Fh

\dt Function 1680h

\dd Idle (Release timeslice to multitasker)

\dt Function 168Ah

\dd Determine whether DOS extender is available.


\H{servicepm21} Protected Mode Interrupt 21h

\dt Function 7305h

\dd Read/write sectors from/to DOS drive.
Used to implement L and W command.

\dt Function 4Ch

\dd Terminate DPMI client and process


\H{servicepm25} Protected Mode Interrupt 25h

Read sectors from DOS drive.
Used to implement L command.


\H{servicepm26} Protected Mode Interrupt 26h

Write sectors to DOS drive.
Used to implement W command.



\H{serviceE6} Interrupt E6h

\dt Function bx = 0, ax = -1

\dd Used by booted debugger to implement BOOT QUIT command
when running in dosemu2.


\H{service15} Interrupt 15h

\dt Function 87h

\dd Used by DX command to read memory.

\dt Function 5301h, 530Eh, 5307h

\dd Used by booted debugger to implement BOOT QUIT command
when running in qemu.


\H{service13} Interrupt 13h

Used by the booted debugger to load scripts or kernel executables.

\dt Function 00h

\dd Reset disk system

\dt Function 02h

\dd Read sector with CHS addressing

\dt Function 03h

\dd Write sector with CHS addressing

\dt Function 08h

\dd Query CHS geometry

\dt Function 41h

\dd Detect LBA extensions support

\dt Function 42h

\dd Read sector with LBA

\dt Function 43h

\dd Write sector with LBA


\H{service19} Interrupt 19h

Boot load. Used if booting the debugger fails.


\H{service2D} Interrupt 2Dh

Used to access Alternate Multiplex Interrupt Specification TSRs.
Can be used while bootloaded too.

\dt Function 00h

\dd Installation check.
Determines whether an AMIS number is in use.

\dt Function 04h

\dd Determine chained interrupts.
Determines interrupt entrypoints.


\H{service25} Interrupt 25h

Read sectors from DOS drive.
Used to implement L command.
Only used if the debugger is loaded as a DOS application.


\H{service26} Interrupt 26h

Write sectors to DOS drive.
Used to implement W command.
Only used if the debugger is loaded as a DOS application.


\H{service21} Interrupt 21h

DOS services. Only used while not InDOS.
(Only used if the debugger is loaded as a DOS application.)

\dt Function 08h

\dd Get standard input keypress

\dt Function 0Ah

\dd Line buffered standard input

\dt Function 0Bh

\dd Check standard input available / Check Control-C

\dt Function 19h

\dd Get default drive

\dt Function 25h

\dd Set interrupt vector

\dt Function 29h

\dd Parse filename

\dt Function 3000h

\dd Get DOS version

\dt Function 3306h

\dd Get true DOS version

\dt Function 34h

\dd Get InDOS flag address

\dt Function 35h

\dd Get interrupt vector

\dt Function 3700h

\dd Get switch character

\dt Function 3Ch

\dd Create file

\dt Function 3Dh

\dd Open file

\dt Function 3Eh

\dd Close file

\dt Function 3Fh

\dd Read from file

\dt Function 40h

\dd Write to file
(Used to write to stdout too)

\dt Function 41h

\dd Delete file

\dt Function 42h

\dd Seek in file

\dt Function 45h

\dd Duplicate file handle

\dt Function 4400h

\dd Used in initialisation
to determine whether handle is to a device

\dt Function 440Dh

\dd Used to lock and unlock drives
by L or W commands

\dt Function 48h

\dd Allocate memory

\dt Function 4Ah

\dd Resize memory

\dt Function 4B01h

\dd Load executable and return to debugger

\dt Function 4Ch

\dd Terminate process

\dt Function 4Dh

\dd Get process return code

\dt Function 50h

\dd Set PSP

\dt Function 51h

\dd Get PSP

\dt Function 52h

\dd Get List of Lists

\dt Function 55h

\dd Create child PSP

\dt Function 58h

\dd Get or set memory allocation strategy and UMB link status

\dt Function 5D06h

\dd Get DOS SDA address (used to switch active PSP)

\dt Function 6Ch

\dd Extended open/create

\dt Function 716Ch

\dd Extended open/create with LFN

\dt Function 71A0h

\dd Get LFN volume information

\dt Function 7305h

\dd Read/write sectors from/to DOS drive.
Used to implement L and W command.


\H{service67} Interrupt 67h

EMS services. Used by X commands.


\C{cmdhelp} Command help

\H{cmdhelp-ldebug} lDebug help

\c lDebug (YYYY-MM-DD), debugger.
\c
\c Usage: LDEBUG[.COM] [/C=commands] [[drive:][path]progname.ext [parameters]]
\c
\c /C=commands   semicolon-separated list of commands (quote spaces)
\c progname.ext  (executable) file to debug or examine
\c parameters    parameters given to program
\c
\c For a list of debugging commands, run LDEBUG and type ? at the prompt.


\H{cmdhelp-instsect} INSTSECT help

\c INSTSECT: Install boot sectors. 2018 by C. Masloch
\c
\c Usage of the works is permitted provided that this
\c instrument is retained with the works, so that any entity
\c that uses the works is notified of this instrument.
\c
\c DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
\c
\c Options:
\c
\c a:              load or update boot sectors of specified drive
\c /M=filename     operate on FS image file instead of drive
\c /MN             operate on drive instead of image file (default)
\c /MS=number      set sector size of FS image file (default 512)
\c /MO=number      set offset in image file in bytes (default 0)
\c /MOx=number     set offset (x = S sectors, K 1024, M 1024 * 1024)
\c
\c /Fx=filename    replace Xth name in the boot sector, X = 1 to 4
\c /F=filename     alias to /F1=filename
\c
\c /U KEEP         keep default/current boot unit handling (default)
\c /U AUTO         patch boot loader to use auto boot unit handling
\c /U xx           patch boot loader to use XXh as a fixed unit
\c
\c /SR             do not read boot sector from source file (default)
\c /S=filename     read boot sector loader from source file
\c /S12=filename   as /S=filename but only for FAT12 (also /S16, /S32)
\c /SV             validate boot sector jump and FS ID (default)
\c /SN             do not validate boot sector jump and FS ID
\c
\c /BS             write boot sector to drive's boot sector (default)
\c /B=filename     write boot sector to file, not to drive
\c /BN             do not write boot sector
\c /BR             replace boot sector loader with built-in one (default)
\c /BO             keep original boot sector
\c /BC             restore boot sector from backup copy
\c
\c Only applicable for FAT32 with sector size below or equal to 512 bytes:
\c
\c /IS             write FSIBOOT to drive's FSINFO sector (default)
\c /I=filename     write FSIBOOT to file, not to drive
\c /IB             write FSIBOOT to boot sector file (see /B=filename)
\c /IN             do not write FSIBOOT
\c /IR             replace reserved field with built-in FSIBOOT (default)
\c /IO             keep original reserved fields (including FSIBOOT area)
\c /IC             restore FSINFO from backup copy
\c /IZ             zero out reserved fields (including FSIBOOT area)
\c /II             leave invalid FSINFO structure
\c /IV             make valid FSINFO if there is none (default)
\c
\c Only applicable for FAT32:
\c
\c /C              force writing to backup copies
\c /CB             force writing sector to backup copy
\c /CI             force writing info to backup copy
\c /CN             disable writing to backup copies
\c /CNB            disable writing sector to backup copy
\c /CNI            disable writing info to backup copy
\c /CS             only write backup copies if writing sectors (default)
\c /CSB            only write sector to backup copy if writing sector
\c /CSI            only write info to backup copy if writing sector


\C{helptopics} Online help pages

\H{helpmain} ? - Main online help

\c lDebug (YYYY-MM-DD) help screen
\c assemble        A [address]
\c set breakpoint  BP index|AT|NEW address
\c                   [[NUMBER=]number] [WHEN=cond] [ID=id]
\c  set ID         BI index|AT address [ID=]id
\c  set condition  BW index|AT address [WHEN=]cond
\c  set offset     BO index|AT address [OFFSET=]number
\c  set number     BN index|AT address|ALL number
\c  clear          BC index|AT address|ALL
\c  disable        BD index|AT address|ALL
\c  enable         BE index|AT address|ALL
\c  toggle         BT index|AT address|ALL
\c  list           BL [index|AT address|ALL]
\c compare         C range address
\c dump            D [range]
\c dump bytes      DB [range]
\c dump words      DW [range]
\c dump dwords     DD [range]
\c dump interrupts DI[R][M][L] interrupt [count]
\c dump MCB chain  DM [segment]
\c display strings DZ/D$/D[W]# [address]
\c enter           E address [list]
\c fill            F range [RANGE range|list]
\c go              G [=address] [breakpts]
\c goto            GOTO :label
\c hex add/sub     H value1 [value2 [...]]
\c base display    H BASE=number [GROUP=number] [WIDTH=number] value
\c input           I[W|D] port
\c if numeric      IF [NOT] (cond) THEN cmd
\c if script file  IF [NOT] EXISTS Y file [:label] THEN cmd
\c load program    L [address]
\c load sectors    L address drive sector count
\c move            M range address
\c 80x86/x87 mode  M [0..6|C|NC|C2|?]
\c set name        N [[drive:][path]progname.ext [parameters]]
\c output          O[W|D] port value
\c proceed         P [=address] [count [WHILE cond] [SILENT [count]]]
\c quit            Q
\c register        R [register [value]]
\c R extended      RE
\c RE commands     RE.LIST|APPEND|REPLACE [commands]
\c MMX register    RM
\c FPU register    RN
\c toggle 386 regs RX
\c search          S range [REVERSE] [RANGE range|list]
\c sleep           SLEEP count [SECONDS|TICKS]
\c trace           T [=address] [count [WHILE cond] [SILENT [count]]]
\c trace (exc str) TP [=address] [count [WHILE cond] [SILENT [count]]]
\c trace mode      TM [0|1]
\c enter TSR mode  TSR
\c unassemble      U [range]
\c write program   W [address]
\c write sectors   W address drive sector count
\c expanded mem    XA/XD/XM/XR/XS, X? for help
\c run script      Y [partition/][scriptfile] [:label]
\c
\c Additional help topics:
\c  Registers      ?R
\c  Flags          ?F
\c  Conditionals   ?C
\c  Expressions    ?E
\c  Variables      ?V
\c  R Extended     ?RE
\c  Run keywords   ?RUN
\c  Options        ?O
\c  Boot loading   ?BOOT
\c  lDebug build   ?BUILD
\c  lDebug build   ?B
\c  lDebug sources ?SOURCE
\c  lDebug license ?L


\H{helpr} ?R - Registers

\c Available 16-bit registers:             Available 32-bit registers: (386+)
\c AX      Accumulator                     EAX
\c BX      Base register                   EBX
\c CX      Counter                         ECX
\c DX      Data register                   EDX
\c SP      Stack pointer                   ESP
\c BP      Base pointer                    EBP
\c SI      Source index                    ESI
\c DI      Destination index               EDI
\c DS      Data segment
\c ES      Extra segment
\c SS      Stack segment
\c CS      Code segment
\c FS      Extra segment 2 (386+)
\c GS      Extra segment 3 (386+)
\c IP      Instruction pointer             EIP
\c FL      Flags                           EFL

Enter ?F to display the recognized flags.


\H{helpf} ?F - Flags

Recognized flags:

\c Value   Name                      Set                     Clear
\c 0800  OF  Overflow Flag         OV  Overflow            NV  No overflow
\c 0400  DF  Direction Flag        DN  Down                UP  Up
\c 0200  IF  Interrupt Flag        EI  Enable interrupts   DI  Disable interrupts
\c 0080  SF  Sign Flag             NG  Negative            PL  Plus
\c 0040  ZF  Zero Flag             ZR  Zero                NZ  Not zero
\c 0010  AF  Auxiliary Flag        AC  Auxiliary carry     NA  No auxiliary carry
\c 0004  PF  Parity Flag           PE  Parity even         PO  Parity odd
\c 0001  CF  Carry Flag            CY  Carry               NC  No carry

The short names of the flag states are displayed when dumping registers
and can be entered to modify the symbolic F register with R. The short
names of the flags can be modified by R.


\H{helpc} ?C - Conditionals

In the register dump displayed by the R, T, P and G commands, conditional
jumps are displayed with a notice that shows whether the instruction will
cause a jump depending on its condition and the current register and flag
contents. This notice shows either "jumping" or "not jumping" as appropriate.

The conditional jumps use these conditions: (second column negates)

\c  jo             jno             OF
\c  jc jb jnae     jnc jnb jae     CF
\c  jz je          jnz jne         ZF
\c  jbe jna        jnbe ja         ZF||CF
\c  js             jns             SF
\c  jp jpe         jnp jpo         PF
\c  jl jnge        jnl jge         OF^^SF
\c  jle jng        jnle jg         OF^^SF || ZF
\c  j(e)cxz                        (e)cx==0
\c  loop                           (e)cx!=1
\c  loopz loope                    (e)cx!=1 && ZF
\c  loopnz loopne                  (e)cx!=1 && !ZF

Enter ?F to display a description of the flag names.


\H{helpe} ?E - Expressions

Recognized operators in expressions:

\c |       bitwise OR              ||      boolean OR
\c ^       bitwise XOR             ^^      boolean XOR
\c &       bitwise AND             &&      boolean AND
\c >>      bit-shift right         >       test if above
\c >>>     signed bit-shift right  <       test if below
\c <<      bit-shift left          >=      test if above-or-equal
\c ><      bit-mirror              <=      test if below-or-equal
\c +       addition                ==      test if equal
\c -       subtraction             !=      test if not equal
\c *       multiplication          =>      same as >=
\c /       division                =<      same as <=
\c %       modulo (A-(A/B*B))      <>      same as !=
\c **      power

Implicit operater precedence is handled in the listed order, with increasing
precedence: (Brackets specify explicit precedence of an expression.)

\c  boolean operators OR, XOR, AND (each has a different precedence)
\c  comparison operators
\c  bitwise operators OR, XOR, AND (each has a different precedence)
\c  shift and bit-mirror operators
\c  addition and subtraction operators
\c  multiplication, division and modulo operators
\c  power operator

Recognized unary operators: (modifying the next number)

\c +       positive (does nothing)
\c -       negative
\c ~       bitwise NOT
\c !       boolean NOT
\c ?       absolute value
\c !!      convert to boolean

Note that the power operator does not affect unary operator handling.
For instance, "- 2 ** 2" is parsed as "(-2) ** 2" and evaluates to 4.

Although a negative unary and signed bit-shift right operator are provided
the expression evaluator is intrinsically unsigned. Particularly the division,
multiplication, modulo and all comparison operators operate unsigned. Due to
this, the expression "-1 < 0" evaluates to zero.

Recognized terms in an expression:

\c  32-bit immediates
\c  8-bit registers
\c  16-bit registers including segment registers (except FS, GS)
\c  32-bit compound registers made of two 16-bit registers (eg DXAX)
\c  32-bit registers and FS, GS only if running on a 386+
\c  32-bit variables V00..VFF
\c  32-bit special variables DCO, DCS, DAO, DAS, DIF, DPI, PPI
\c  16-bit special variables DPR, DPP, PSP, PPR
\c   (fuller variable reference in the manual)
\c  byte/word/3byte/dword memory content (eg byte [seg:ofs], where both the
\c   optional segment as well as the offset are expressions too)

The expression evaluator case-insensitively checks for names of variables
and registers as well as size specifiers.

Enter ?R to display the recognized register names.
Enter ?V to display the recognized variables.


\H{helpv} ?V - Variables

Available lDebug variables:

\b V0..VF  User-specified usage

\b DCO     Debugger Common Options

\b DAO     Debugger Assembler/disassembler Options

 The following variables cannot be written:

\b PSP     Debuggee Process

\b PPR     Debuggee's Parent Process

\b PPI     Debuggee's Parent Process Interrupt 22h

\b DIF     Debugger Internal Flags

\b DCS     Debugger Common Startup options

\b DAS     Debugger Assembler/disassembler Startup options

\b DPR     Debugger Process

\b DPP     Debugger's Parent Process (zero in TSR mode)

\b DPI     Debugger's Parent process Interrupt 22h (zero in TSR mode)

Enter ?O to display the options and internal flags.


\H{helpre} ?RE - R Extended

The RUN commands (T, TP, P, G) and the RE command use the RE command
buffer to run commands. Most commands are allowed to be run from the
RE buffer. Disallowed commands include program-loading L, A, E that
switches the line input mode, TSR, Q, Y, RE, and further RUN commands.
When the RE buffer is used as input during T, TP, or P with either
of the WHILE or SILENT keywords, commands that use the auxbuff are
also disallowed and will emit an error noting the conflict.

RE.LIST shows the current RE buffer contents in a format usable by
the other RE commands. RE.APPEND appends the following commands to
the buffer, if they fit. RE.REPLACE appends to the start of the
buffer. When specifying commands, an unescaped semicolon is parsed
as a linebreak to break apart individual commands. Backslashes can
be used to escape semicolons and backslashes themselves.

Prefixing a line with an @ (AT sign) causes the command not to be
shown to the standard output of the debugger when run. Otherwise,
the command will be shown with a percent sign % or ~% prompt.

The default RE buffer content is @R. This content is also
detected and handled specifically; if found as the only command
the handler directly calls the register dump implementation
without setting up and tearing down the special execution
environment used to run arbitrary commands from the RE buffer.


\H{helprun} ?RUN - Run keywords

T (trace), TP (trace except proceed past string operations), and P (proceed)
can be followed by a number of repetitions and then the keyword WHILE,
which must be followed by a conditional expression.

The selected run command is repeated as many times as specified by the
number, or until the WHILE condition evaluates no longer to true.

After the number of repetitions or (if present) after the WHILE condition
the keyword SILENT may follow. If that is the case, all register dumps
done during the run are buffered by the debugger and the run remains
silent. After the run, the last dumps are replayed from the buffer
and displayed. At most as many dumps as fit into the buffer are
displayed. (The buffer is currently up to 8 KiB sized.)

If a number follows behind the SILENT keyword, only at most that many
dumps are displayed from the buffer. The dumps that are displayed
are always those last written into the buffer, thus last occurred.


\H{helpo} ?O - Options

Available options: (read/write DCO, read DCS)

\b 0001 RX: 32-bit register display

\b 0002 TM: trace into interrupts

\b 0004 allow dumping of CP-dependant characters

\b 0008 always assume InDOS flag non-zero, to debug DOS or TSRs

\b 0010 disallow paged output to StdOut

\b 0020 allow paged output to non-StdOut

\b 0040 display raw hexadecimal content of FPU registers

\b 0100 when prompting during paging, do not use DOS for input

\b 0200 do not execute HLT instruction to idle

\b 0400 do not idle, the keyboard BIOS idles itself

\b 0800 use rawinput for int 21h interactive input

\b 1000 in disp_*_size use SI units (kB = 1000, etc). overrides 2000!

\b 2000 in disp_*_size use JEDEC units (KB = 1024)

\b 4000 enable serial I/O (port 02F8h interrupt 0Bh)

\b 8000 disable serial I/O when breaking after 5 seconds Ctrl pressed

\b 00010000 gg: do not skip a breakpoint (bb or gg)

\b 00020000 gg: do not auto-repeat

\b 00040000 T/TP/P: do not skip a (bb) breakpoint

\b 00080000 gg: do not auto-repeat after bb hit

\b 00100000 T/TP/P: do not auto-repeat after bb hit

\b 00200000 gg: do not auto-repeat after unexpectedinterrupt

\b 00400000 T/TP/P: do not auto-repeat after unexpectedinterrupt

\b 00800000 S: do not dump data after matches

\b 10000000 R: do not repeat disassembly

\b 20000000 R: do not show memory reference in disassembly

\b 40000000 quiet command line buffer input

\b 80000000 quiet command line buffer output


More options: (read/write DCO2, read DCS2)

\b 0001 DB: show header

\b 0002 DB: show trailer

\b 0010 DW: show header

\b 0020 DW: show trailer

\b 0100 DD: show header

\b 0200 DD: show trailer

\b 0800 use rawinput for int 21h interactive input in DPMI

\b 1000 H: stay compatible to MS-DOS Debug

\b 2000 idle and check for Ctrl-C in getc

\b 4000 idle and check for Ctrl-C in getc in DPMI

\b 8000 T/TP/P/G: cancel run after RE command buffer execution


More options: (read/write DCO3, read DCS3)

\b 0001 T: do not page output

\b 0002 TP: do not page output

\b 0004 P: do not page output

\b 0008 G: do not page output

\b 0100 T/TP/P: modify paging for silent dump

\b 0200 T/TP/P: if 0100 set: turn paging on, else off

\b 010000 R: highlight changed digits (needs ANSI for DOS output)

\b 020000 R: highlight escape sequences to int 10h, else video attributes

\b 040000 R: highlight changed registers (overrides 010000)

\b 080000 R: include highlighting of EIP

\b 02000000 do not call int 2F.1680 for idling

\b 04000000 delay for a tick before writing breakpoints

\b 08000000 do not call other lDebug instance's Update IISP Header call

\b 10000000 disable auto-repeat

\b 20000000 check int 16h buffer for Control-C if inputting from int 16h

\b 40000000 call DOS service 0Bh to check for Control-C

\b 80000000 when Q command is used while TSR, leave TF as is


More options: (read/write DCO4, read DCS4)

\b 0002 enable interrupt 2Fh hook while in 86 Mode

\b 0004 enable interrupt 8 hook

\b 0008 enable interrupt 2Dh hook

\b 00010000 force serial interrupt unhooking

\b 00020000 force interrupt 2Fh unhooking

\b 00040000 force interrupt 8 unhooking

\b 00080000 force interrupt 2Dh unhooking

\b 01000000 force interrupt 0 unhooking

\b 02000000 force interrupt 1 unhooking

\b 04000000 force interrupt 3 unhooking

\b 08000000 force interrupt 6 unhooking

\b 10000000 force interrupt 18h unhooking

\b 20000000 force interrupt 19h unhooking


Internal flags: (read DIF)

\b 000001 Int25/Int26 packet method available

\b 000002 Int21.7305 packet method available

\b 000004 VDD registered and usable

\b 000008 internal flag for paged output

\b 000010 DEBUG's input isn't StdIn

\b 000020 DEBUG's input is a file

\b 000040 DEBUG's output isn't StdOut

\b 000080 DEBUG's output is a file

\b 001000 state of debuggee's A20

\b 002000 state of debugger's A20 (not implemented: same as previous)

\b 004000 debugger booted independent of a DOS

\b 008000 CPU is at least a 386 (32-bit CPU)

\b 010000 internal flag for tab output processing

\b 020000 running inside NTVDM

\b 100000 internal flag for paged output

\b 400000 in TSR mode (detached debugger process)

\b 01000000 running inside dosemu

\b 04000000 T/TP/P: while condition specified

\b 08000000 TP: P specified (proceed past string ops)

\b 10000000 T/TP/P: silent mode (SILENT specified)

\b 20000000 T/TP/P: silent mode is active, writing to silent buffer


Available assembler/disassembler options: (read/write DAO, read DAS)

\b 01 Disassembler: lowercase output

\b 02 Disassembler: output blank behind comma

\b 04 Disassembler: output addresses in NASM syntax

\b 08 Disassembler: lowercase referenced memory location segreg

\b 10 Disassembler: always show SHORT keyword

\b 20 Disassembler: always show NEAR keyword

\b 40 Disassembler: always show FAR keyword


\H{helpboot} ?BOOT - Boot loading

Boot loading commands:

\b BOOT LIST HDA

\b BOOT DIR [partition] [dirname]

\b BOOT READ|WRITE [partition] segment [[HIDDEN=sector] sector] [count]

\b BOOT QUIT       [exits dosemu or shuts down using APM]

\b BOOT [PROTOCOL=SECTOR] partition

\b BOOT PROTOCOL=proto [opt] [partition] [filename1] [filename2] [cmdline]

\b         the following partitions may be specified:

\lcont{

\b          HDAnum first hard disk, num = partition (1-4 primary, 5+ logical)

\b          HDBnum second hard disk (etc), num = partition

\b          HDA    first hard disk (only valid for READ|WRITE|PROTOCOL=SECTOR)

\b          FDA    first floppy disk

\b          FDB    second floppy disk (etc)

\b          LDP    partition the debugger loaded from

\b          YDP    partition the most recent Y command loaded from

\b          SDP    last used partition (default if no partition specified)

\b         filename2 may be double-slash // for none

\b         cmdline is only valid for lDOS, RxDOS.2, RxDOS.3 protocols

\b         files' directory entries are loaded to 500h and 520h
}

Available protocols: (default filenames, load segment, then entrypoint)

\b  LDOS           LDOS.COM or L[D]DEBUG.COM at 200h, 0:400h

\b  FREEDOS        KERNEL.SYS or METAKERN.SYS at 60h, 0:0

\b  DOSC           IPL.SYS at 2000h, 0:0

\b  EDRDOS         DRBIO.SYS at 70h, 0:0

\b  MSDOS6         IO.SYS + MSDOS.SYS at 70h, 0:0

\b  MSDOS7         IO.SYS at 70h, 0:200h

\b  IBMDOS         IBMBIO.COM + IBMDOS.COM at 70h, 0:0

\b  NTLDR          NTLDR at 2000h, 0:0

\b  BOOTMGR        BOOTMGR at 2000h, 0:0

\b  RXDOS.0        RXDOSBIO.SYS + RXDOS.SYS at 70h, 0:0

\b  RXDOS.1        RXBIO.SYS + RXDOS.SYS at 70h, 0:0

\b  RXDOS.2        RXDOS.COM at 70h, 0:400h

\b  RXDOS.3        RXDOS.COM at 200h, 0:400h

\b  CHAIN          BOOTSECT.DOS at 7C0h, -7C0h:7C00h

\b  SECTOR         (default) load partition boot sector or MBR

\b  SECTORALT      as SECTOR, but entry at 07C0h:0

Available options:

\b  MINPARA=num            load at least that many paragraphs

\b  MAXPARA=num            load at most that many paragraphs (0 = as many as fit)

\b  SEGMENT=num            change segment at that the kernel loads

\b  ENTRY=[num:]num        change entrypoint (CS (relative) : IP)

\b  BPB=[num:]num          change BPB load address (segment -1 = auto-BPB)

\b  CHECKOFFSET=num        set address of word to check, must be even

\b  CHECKVALUE=num         set value of word to check (0 = no check)

Boolean options: [opt=bool]

\b  SET_DL_UNIT            set dl to load unit

\b  SET_BL_UNIT            set bl to load unit

\b  SET_SIDI_CLUSTER       set si:di to first cluster

\b  SET_DSSI_DPT           set ds:si to DPT address

\b  PUSH_DPT               push DPT address and DPT entry address

\b  DATASTART_HIDDEN       add hidden sectors to datastart var

\b  SET_AXBX_DATASTART     set ax:bx to datastart var

\b  SET_DSBP_BPB           set ds:bp to BPB address

\b  LBA_SET_TYPE           set LBA partition type in BPB

\b  MESSAGE_TABLE          provide message table pointed to at 1EEh

\b  SET_AXBX_ROOT_HIDDEN   set ax:bx to root start with hidden sectors

\b  NO_BPB                 do not load BPB

\b  SET_DSSI_PARTINFO      load part table to 600h, point ds:si + ds:bp to it


\H{helpbuild} ?BUILD - lDebug build (only revisions)

\c lDebug (YYYY-MM-DD)
\c Source Control Revision ID: hg xxxxxxxxxxxx
\c Uses yyyyyyyy: Revision ID hg zzzzzzzzzzzz
\c [etc]


\H{helpb} ?B - lDebug build (with options)

\c lDebug (YYYY-MM-DD)
\c Source Control Revision ID: hg xxxxxxxxxxxx
\c Uses yyyyyyyy: Revision ID hg zzzzzzzzzzzz
\c [etc]
\c
\c DI command
\c DM command
\c D string commands
\c S match dumps line of following data
\c RN command
\c Access SDA current PSP field
\c Load NTVDM VDD for sector access
\c X commands for EMS access
\c RM command and reading MMX registers as variables
\c Expression evaluator
\c  Indirection in expressions
\c Variables with user-defined purpose
\c Debugger option and status variables
\c PSP variables
\c Conditional jump notice in register dump
\c TSR mode (Process detachment)
\c Boot loader
\c Permanent breakpoints
\c Intercepted interrupts: 00, 01, 03, 06, 18, 19
\c Extended built-in help pages


\H{helpx} ?X - EMS commands

\c Expanded memory (EMS) commands:
\c   Allocate      XA count
\c   Deallocate    XD handle
\c   Map memory    XM logical-page physical-page handle
\c   Reallocate    XR handle count
\c   Show status   XS


\H{helpsource} ?SOURCE - lDebug source reference

The original lDebug releases can be obtained from the repo located at
\W{https://hg.pushbx.org/ecm/ldebug}{https://hg.pushbx.org/ecm/ldebug}
(E. C. Masloch's repo)

The most recent manual is hosted at
\W{https://pushbx.org/ecm/doc/}{https://pushbx.org/ecm/doc/}
in the
files
\W{https://pushbx.org/ecm/doc/ldebug.htm}{ldebug.htm},
\W{https://pushbx.org/ecm/doc/ldebug.txt}{ldebug.txt}, and
\W{https://pushbx.org/ecm/doc/ldebug.pdf}{ldebug.pdf}


\H{helpl} ?L - lDebug license

lDebug - libre 86-DOS debugger

\b Copyright (C) 1995-2003 Paul Vojta

\b Copyright (C) 2008-2021 C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.


All contributions by Paul Vojta or C. Masloch to the debugger are available
under a choice of three different licenses. These are the Fair License, the
Simplified 2-Clause BSD License, or the MIT License.

This is the license and copyright information that applies to lDebug; but note
that there have been substantial contributions to the code base that are not
copyrighted (public domain).
