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 2020-09-14.
Building lDebug is not supported on conventional DOS-like systems. (DJGPP environments may suffice but are not tested.)
The following components are required to build with the provided scripts:
%deftok
’ is not supported
%deftok
’ is implemented wrongly
%assign %$foo%[bar] quux
’ doesn't function right
hg pull
’ to update the repo
hg up default
’ or the symbolic branch with ‘hg up symbolic
’ or any other available commit you want to build
hg fetch
’ or the sequence of ‘hg pull
’ then ‘hg up
’ to update the repos. (Usually the additional source repos do not have multiple branches.)
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 ldebug.com
result. This favours LZMA-lzip (lzd) and Exomizer 3 (exodecr) compression as they result in the best ratios. The uncompressed ldebugu.com
file will always be generated, you can rename or copy or symlink it to use it as ldebug.com
if you want.
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.
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 ‘hg id
’. The resulting revision IDs are embedded into the executable and will be shown for the ?B (long) and ?BUILD (short) commands.
$NASM
specifies the nasm executable to use, with path if needed.
./makec
’ (or use whatever C compiler to build mktables) then ‘./mktables
’ next.
./mak.sh
’ from the ldebug/source directory. You may pass environment variables to it, such as ‘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 ‘./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 ‘./mak.sh
’ from that directory. The same is true of the make* scripts.
The make* scripts work as follows:
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, debug.com
will be a nonbootable executable (even if the _BOOTLDR
option is enabled). This executable can safely be compressed using EXE packers such as the UPX. If the _BOOTLDR
option is enabled, ldebug.com
will be a compressed bootable executable (if any compression method is selected), whereas 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 ‘last page size’ MZ EXE header field holds an invalid value.
The bootable executables can be used as MS-DOS 6 protocol IO.SYS
, MS-DOS 7/8 IO.SYS
, PC-DOS 6/7 IBMBIO.COM
, FreeDOS KERNEL.SYS
, RxDOS.3 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.
~
’.
(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.)
-
’ to a hash sign ‘#
’. (lDDebugX prepends its tilde to that resulting in ‘~#
’.)
ldebugu.com
and 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 section 5.10.
Plain numbers are evaluated as expressions. Expressions consist of any number of the following:
Plain number parsing for an expression continues for as long as a valid expression is continued. For example, in the command ‘D 100 + 20 L 10
’ the starting address (its offset to be specific) is calculated as ‘100 + 20’. Then the expression evaluator encounters the ‘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 ‘count’ or ‘value’.
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.
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 ‘L
’ or ‘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 ‘BYTES
’, ‘WORDS
’, or ‘DWORDS
’. For the latter two, the plain number will be multiplied by 2 or 4. The ‘BYTES
’ keyword is only provided for symmetry; currently all commands taking ranges default to byte size for the ‘LENGTH
’ number.
For example, the command ‘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 ‘DW
’ and ‘DD
’ commands (refer to section 3.8), but they can be used for any command that accepts a range.
Range parameters are used by a lot of commands.
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 section 3.12, section 3.13, and section 3.31.
A list or range can be specified for this parameter. The range is identified by a leading ‘RANGE
’ keyword. Otherwise, a list is parsed. A list or range parameter is as yet used by the S command, refer to section 3.31.
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.
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 section 3.5.
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 section 3.10 and section 5.10.
Each breakpoint is a single address, which defaults to the code segment. The address may instead be specified starting with an AT sign ‘@
’, 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 section 3.5 and section 3.14.
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 section 3.15 and section 3.39.
A port is a plain number for parsing purposes. The port parameter type is used by the I and O commands, refer to section 3.17 and section 3.24.
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 section 3.20 and section 3.37. The N and Y commands (section 3.23 and section 3.39) also accept drive parameters, but only as part of their filenames. These must be in the drive letter followed by colon format.
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 section 3.20 and section 3.37. Some BOOT commands also use sector numbers, refer to section 5.10.
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 ‘WHILE
’ keyword. Refer to section 3.18, section 3.25, and section 3.32.
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 section 3.27.
Command is a special parameter type that is used only by the RE.APPEND and RE.REPLACE commands (section 3.27.2). 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.
Entering an empty command at an interactive prompt results in autorepeat. Interactive prompts for this purpose include:
int 21h
)
int 16h
/int 10h
)
Input that does not count as an interactive prompt includes:
int 21h
)
int 21h
)
int 13h
)
Autorepeat is not supported by all commands. The following commands support autorepeat:
CS:(E)IP
at the start of the command's execution, it is skipped once.
Online help ?
The question mark command (?) lists the main online help screen.
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:
Registers ?R
Flags ?F
Conditionals ?C
Expressions ?E
Variables ?V
R Extended ?RE
Run keywords ?RUN
Options ?O
Boot loading ?BOOT
lDebug build ?BUILD
lDebug build ?B
lDebug license ?L
The full help pages are listed in section 5.
A leading colon indicates a destination label for GOTO, see section 3.15.
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.
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. After that message a register dump occurs, same as for default breaking for the Run commands.
The exceptions are as follows:
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:
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. After that message, a register dump occurs. Then execution is continued in accordance with the command that is running debuggee code.
set breakpoint B[P] index|AT|NEW address [number]
BP (or B) 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 are usable.
The optional number, which defaults to 8000h, sets the breakpoint counter to that number.
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.
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.
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.
enable BE index|AT address|ALL
Like BD, but enables breakpoints.
toggle BT index|AT address|ALL
Like BE and BD, but toggles breakpoints: A disabled breakpoint is enabled, while an enabled breakpoint is disabled.
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, two breakpoints are displayed per line, and only lines with used breakpoints are displayed.
The output format for unused breakpoints is as follows:
The output format for used breakpoints is as follows:
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:
-bu
Already in topmost instance. (This is no debugging build of lDebug.)
-
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.
dump D [range]
dump bytes DB [range]
dump words DW [range]
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.
dump interrupts DI 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.
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.
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.
enter E address [list]
fill F range list
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 LIST command lists the breakpoints given to the last (successfully parsed) G command.
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 "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.
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:
hex add/sub H value1 value2
input I[W|D] port
if IF (cond) THEN cmd
The IF command allows specifying a conditionally executed command. The condition is a numeric expression. If it evaluates to non-zero then the conditional command is executed. This is especially useful for creating conditional control flow branches with the GOTO command (see section 3.15).
load program L [address]
load sectors L address drive sector count
move M range address
80x86/x87 mode M [0..6|C|NC|C2|?]
set name N [[drive:][path]progname.ext [parameters]]
output O[W|D] port value
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.
quit Q
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/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:
-r ax .
AX 0000
-r ax
AX 0000 :1
-r ax
AX 0001 :.
-r ax += 4
-r ax
AX 0005 :
-r word [cs:0]
WORD [1867:0000] 20CD :
-r dif .
DIF 0100B00B
-
R extended RE
The RE command runs the RE buffer commands. Refer to section 5.7.
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 (section 5.7).
MMX register RM
FPU register RN
toggle 386 regs RX
search S range list
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.
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.
trace mode TM [0|1]
enter TSR mode TSR
unassemble U [range]
write program W [address]
write sectors W address drive sector count
expanded mem XA/XD/XM/XR/XS, X? for help
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.
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 ‘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.
All debuggee registers can be accessed numerically:
al
, cl
, dl
, bl
, ah
, ch
, dh
, bh
ax
, cx
, dx
, bx
, sp
, bp
, si
, di
eax
, ecx
, edx
, ebx
, esp
, ebp
, esi
, edi
es
, cs
, ss
, ds
, fs
, gs
fl
, efl
, ip
, eip
Each 16-bit register can be used in a register pair, such as:
dxax
bxcx
(used by L
load program and W
write program commands)
sidi
csip
0 while in Real or Virtual 8086 Mode, debugger process selector otherwise. (The process selector addresses DebugX's PSP and DATA ENTRY section.)
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 section 3.1. If one of these is set to zero then it is an error to not specify a count explicitly for the corresponding command.
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.
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.
Word. This holds the most recent command's return code. If the most recent command succeeded, then this is zero.
Word. This holds the most recent non-zero return code.
AAS: word, AAO: doubleword. Default address for the assembler. Updated to point after each assembled instruction.
Default address for memory dumping. Updated to point after each dumped memory content.
Default address for the disassembler.
Default address for memory entry.
Default address for DZ command, ASCIZ strings. Terminated by zero byte.
Default address for D$ command, CP/M strings. Terminated by dollar sign ‘$
’.
Default address for D# command, Pascal strings. Prefixed by length count byte.
Default address for DW# command. Prefixed by length count word.
Default address for DX command. (Only included in DebugX.)
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.
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.
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 https://github.com/stsp/dosemu2/issues/748.
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:
The default values for all counters and addresses is zero.
If a fault is injected into readmem, it returns the value given in TRV.
If a fault is injected into writemem, it returns failure (CY).
If a fault is injected into getlinear, it returns failure (CY).
If a fault is injected into getsegmented, it returns failure (CY).
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.
Doubleword. Default 0. Mask AA55_AA55h.
Doubleword. Default 0011_0022h. Mask 00FF_00FFh.
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.
Word.
Doubleword. Default zero. V0 to VF or V00 to VFF each specify one variable.
lDebug (2020-03-25) help screen
assemble A [address]
set breakpoint B[P] index|NEW address [number]
set number BN index|ALL number
clear BC index|ALL
disable BD index|ALL
enable BE index|ALL
toggle BT index|ALL
list BL [index|ALL]
compare C range address
dump D [range]
dump interrupts DI interrupt [count]
dump MCB chain DM [segment]
display strings DZ/D$/D[W]# [address]
enter E address [list]
fill F range list
go G [=address] [breakpts]
goto GOTO :label
hex add/sub H value1 value2
input I[W|D] port
if IF (cond) THEN cmd
load program L [address]
load sectors L address drive sector count
move M range address
80x86/x87 mode M [0..6|C|NC|C2|?]
set name N [[drive:][path]progname.ext [parameters]]
output O[W|D] port value
proceed P [=address] [count [WHILE cond] [SILENT [count]]]
quit Q
register R [register [value]]
R extended RE
RE commands RE.LIST|APPEND|REPLACE [commands]
MMX register RM
FPU register RN
toggle 386 regs RX
search S range list
trace T [=address] [count [WHILE cond] [SILENT [count]]]
trace (exc str) TP [=address] [count [WHILE cond] [SILENT [count]]]
trace mode TM [0|1]
enter TSR mode TSR
unassemble U [range]
write program W [address]
write sectors W address drive sector count
expanded mem XA/XD/XM/XR/XS, X? for help
run script Y [partition/][scriptfile] [:label]
Additional help topics:
Registers ?R
Flags ?F
Conditionals ?C
Expressions ?E
Variables ?V
R Extended ?RE
Run keywords ?RUN
Options ?O
Boot loading ?BOOT
lDebug build ?BUILD
lDebug build ?B
lDebug sources ?SOURCE
lDebug license ?L
Available 16-bit registers: Available 32-bit registers: (386+)
AX Accumulator EAX
BX Base register EBX
CX Counter ECX
DX Data register EDX
SP Stack pointer ESP
BP Base pointer EBP
SI Source index ESI
DI Destination index EDI
DS Data segment
ES Extra segment
SS Stack segment
CS Code segment
FS Extra segment 2 (386+)
GS Extra segment 3 (386+)
IP Instruction pointer EIP
FL Flags EFL
Available 64-bit Matrix Math Extension (MMX) registers: (if supported)
MMx MM(x) MMX register x, where x is 0 to 7
Enter ?F to display the recognized flags.
Recognized flags:
Value Name Set Clear
0800 OF Overflow Flag OV Overflow NV No overflow
0400 DF Direction Flag DN Down UP Up
0200 IF Interrupt Flag EI Enable interrupts DI Disable interrupts
0080 SF Sign Flag NG Negative PL Plus
0040 ZF Zero Flag ZR Zero NZ Not zero
0010 AF Auxiliary Flag AC Auxiliary carry NA No auxiliary carry
0004 PF Parity Flag PE Parity even PO Parity odd
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.
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)
jo jno OF
jc jb jnae jnc jnb jae CF
jz je jnz jne ZF
jbe jna jnbe ja ZF||CF
js jns SF
jp jpe jnp jpo PF
jl jnge jnl jge OF^^SF
jle jng jnle jg OF^^SF || ZF
j(e)cxz (e)cx==0
loop (e)cx!=1
loopz loope (e)cx!=1 && ZF
loopnz loopne (e)cx!=1 && !ZF
Enter ?F to display a description of the flag names.
Recognized operators in expressions:
| bitwise OR || boolean OR
^ bitwise XOR ^^ boolean XOR
& bitwise AND && boolean AND
>> bit-shift right > test if above
>>> signed bit-shift right < test if below
<< bit-shift left >= test if above-or-equal
>< bit-mirror <= test if below-or-equal
+ addition == test if equal
- subtraction != test if not equal
* multiplication => same as >=
/ division =< same as <=
% modulo (A-(A/B*B)) <> same as !=
** power
Implicit operater precedence is handled in the listed order, with increasing precedence: (Brackets specify explicit precedence of an expression.)
boolean operators OR, XOR, AND (each has a different precedence)
comparison operators
bitwise operators OR, XOR, AND (each has a different precedence)
shift and bit-mirror operators
addition and subtraction operators
multiplication, division and modulo operators
power operator
Recognized unary operators: (modifying the next number)
+ positive (does nothing)
- negative
~ bitwise NOT
! boolean NOT
? absolute value
!! 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:
32-bit immediates
8-bit registers
16-bit registers including segment registers (except FS, GS)
32-bit compound registers made of two 16-bit registers (eg DXAX)
32-bit registers and FS, GS only if running on a 386+
64-bit MMX registers only if running on a CPU with MMX (r/o for now)
MM0L, MM(0)L accesses the low 32 bits of the register
MM0H, MM(0)H accesses the high 32 bits of the register
MM0Z, MM(0)Z reads the low 32 bits; writes the full register (zero-extend)
MM0S, MM(0)S reads the low 32 bits; writes the full register (sign-extend)
MM0, MM(0) is an alias for the MM0Z syntax
32-bit variables V0..VF
32-bit special variables DCO, DCS, DAO, DAS, DIF, DPI, PPI
16-bit special variables DPR, DPP, PSP, PPR
byte/word/dword memory content (eg byte [seg:ofs], where both the 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.
Available lDebug variables:
The following variables cannot be written:
Enter ?O to display the options and internal flags.
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.
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.
Available options: (read/write DCO, read DCS)
Internal flags: (read DIF)
Available assembler/disassembler options: (read/write DAO, read DAS)
Boot loading commands:
Available protocols: (default filenames, load segment, then entrypoint)
Available options:
Boolean options: [opt=bool]
lDebug (YYYY-MM-DD)
Source Control Revision ID: hg xxxxxxxxxxxx
Uses yyyyyyyy: Revision ID hg zzzzzzzzzzzz
[etc]
lDebug (YYYY-MM-DD)
Source Control Revision ID: hg xxxxxxxxxxxx
Uses yyyyyyyy: Revision ID hg zzzzzzzzzzzz
[etc]
DI command
DM command
D string commands
S match dumps line of following data
RN command
Access SDA current PSP field
Load NTVDM VDD for sector access
X commands for EMS access
RM command and reading MMX registers as variables
Expression evaluator
Indirection in expressions
Variables with user-defined purpose
Debugger option and status variables
PSP variables
Conditional jump notice in register dump
TSR mode (Process detachment)
Boot loader
Permanent breakpoints
Intercepted interrupts: 00, 01, 03, 06, 18, 19
Extended built-in help pages
The original lDebug releases can be obtained from the repo located at https://hg.ulukai.org/ecm/ldebug (E. C. Masloch's repo)
The most recent manual is hosted at https://ulukai.org/ecm/doc/ in the files ldebug.htm, ldebug.txt, and ldebug.pdf
lDebug - libre 86-DOS debugger
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 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).
The program executables can be compressed with a choice of different compressors. The files then contain a decompression stub. Some of these stubs have their own usage conditions. The following stub usage conditions apply, if one of these stubs is used.
BriefLZ - small fast Lempel-Ziv
8086 Assembly lDOS iniload payload BriefLZ depacker
Based on: BriefLZ C safe depacker
Copyright (c) 2002-2016 Joergen Ibsen
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
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.
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.
Copyright (c) 2005-2017 Magnus Lind.
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
MIT License
Copyright (c) 2020 David Barina
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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 program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
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.
hg 3a05abfb3dac, from commit on at 2020-09-14 23:06:52 +0200
If this is in ecm's repository, you can find it at https://hg.ulukai.org/ecm/ldebug/rev/3a05abfb3dac