
WarpLink updates (as of r19 2026 March)
 by E. C. Masloch, 2023 to 2026

The main WarpLink executable (wl.exe) now completely builds with
NASM and itself. The repo history contains part of the fixmem.pl
script's history, which was used to port the source from TASM to
NASM.

The display bug of the "EXE load image size" line was fixed.

NASM's encodings for DWORD and 4KIB section alignment values
are now supported.

The map file now lists the date as ISO 8601 plus a day of the
week and the time in 24-hour format. The map file also lists
the executable header size, initialised image size (progbits),
and total image size (including nobits).

With the /XE switch, the wlemitalign feature is activated.
This feature is used by naming a section starting with the
"wlemitalign" prefix. If this section is nobits, the padding
to align it within the executable is still written like it is
progbits. This is useful to align the executable size despite
the last progbits middle section being aligned less.

Disk full condition checks are improved.

The /WSN switch hides the "no stack segment was found" warning.
The /WS0 switch avoids returning a nonzero error level (return
code) if this warning would be displayed.

Using the /XC switch, wlcalc is enabled. This is a facility to
perform post-link calculations that are generally applied to
variables within the final linked executable image. A wlcalc
request must be a global label that consists of the following:

  * Keyword "wlcalc_"
  * Size keyword, must be "byte", "word", "3byte", or "dword"
  * Optional "pass" keyword followed by a decimal number
  * Optional WRT clause (EXT-related operations only):
    * "wrt" keyword
    * Optional "@" text followed by a quote delimiter (any one
       byte to use as the delimiter of the segment name), if not
       present then underscore "_" is used as delimiter.
    * Segment or group name
    * Delimiter that ends the segment or group name
  * Operation keyword
  * Depending on the operation: a constant number (hex, decimal,
     or binary), a segment or group name, or an extern label name
  * After a constant number, an optional "repeat" keyword
     followed by a repetition number (also hex, dec, or binary).
  * After a constant number or "repeat" number, another optional
     "pass" keyword followed by a number (hex, dec, binary)
  * Optional distinguishing string with a leading question mark

The supported operation keywords:

DIV, MUL, SHR, SHL, XOR, OR, AND, CLR (AND with NOT of constant),
ADD, SUB, SUBR (SUB with operands reversed), SEG (writes an MZ
executable relocation and applies relative segment value), SEGREL
(only applies relative segment value), MINUSSEGREL (subtracts the
relative segment value), EXT (adds the offset value of the named
extern label), MINUSEXT (subtracts offset value of label), EXTPARA
(rounds up and divides label's offset to a paragraph value and
adds that), MINUSEXTPARA (subtracts paragraph value), OPEXT, and
finally ITOA.

The WRT clause (With Reference To) is only valid if the subsequent
operation keyword is EXT, MINUSEXT, EXTPARA, MINUSEXTPARA, or
OPEXT. The segment or group name given after the "wrt" keyword
indicates the base segment against which to evaluate the given
extern label. If the WRT clause is not present, then the PUBDEF's
default group or segment is used as a base instead. The PUBDEF
found for the extern label name must not be an absolute number
if a WRT clause is given, this will be rejected with an error.

The OPEXT operation must specify a subsequent operation after the
"OPEXT" keyword. This subsequent operation must not be one of the
SEG or EXT related operations. After the second operation keyword,
a label to use follows. It will use this label's offset as the
second operand for the subsequent operation. OPEXT_ADD_ is the
same as EXT_, and OPEXT_SUB_ is the same as MINUSEXT_.

SEG operations are only supported on WORD sized variables. All the
other operations support any of the four variable sizes. Overflow
is not generally detected, except that a divisor of zero and a
shift count >= 64 Ki are rejected. Constant numbers and repetition
count numbers are 32-bit unsigned numbers, pass numbers are 16-bit
unsigned numbers.

ITOA reads a number from the file with the specified variable size.
It formats the number as text into the buffer. The constant passed
to ITOA determines the following:

  * Low byte: Base, must be between 2 and 36 inclusive
  * Second lowest byte: If nonzero, modifies the buffer size to
     write to. Must not be higher than 10, an overflow error is
     generated if it is higher. An error is also generated if the
     buffer size used does not suffice to hold the number's text.
  * High word: Flags and group width:
    * Flag 1: Append padding rather than prepending it.
    * Flag 2: Padding is '0' (digit zero) instead of ' ' blank.
    * Flag 4 and 8: Select separator text to use:
      * 00b: Underscore (NASM style)
      * 01b: Dot (german)
      * 10b: Comma (english)
      * 11b: Apostrophe (C23 style)
    * Higher nybble (mask 0F0h): Grouping width, 0 if no grouping.
    * Unknown flags that are set nonzero generate an error.

There are some new /C switches to generate flat-format files. These
are only effective if /C is specified itself:

  * /CZ - Use an entrypoint of 0:0 and do not cut out a prefix of
     the executable image
  * /CS - Ignore existing stack
  * /CB - Allow file larger than 64 KiB
  * /CL= - Specify location segment number, to allow MZ executable
     segment relocations and relocate to this location

TMP= and TEMP= variables are both searched for now.

With the /XL switch, the wllist feature is enabled. To use it:

  * Emit labels starting with the "wllist_" or "..@wllist_" prefix
  * A wllist label with an "N" after the prefix indicates a new
     list to start. There must be an "S" followed by a segment
     name, ended by an underscore "_", then an "L" followed by the
     list name, ended by a question mark "?" or the end of label.
    The named list will be emitted into the named segment.
  * A label with a "G" after the prefix indicates a group. It must
     be followed by another "G", then the group name ended by an
     underscore "_", then one or more segment names indicated by
     the "S" key letter.
  * All other wllist labels must end with an "L" key letter that's
     followed by the list name. Before the "L" there may be the
     "R" letter followed by a repetition count, and after an "R"
     there may be a "W" letter followed by a repetition step width.

The generated lists are emitted into the named segments and groups.
The segment gets word alignment. The following global labels are
emitted per list name:

  * name - The start of the list
  * name.END - Past the last entry of the list
  * name.AMOUNT - Number of words (items) in the list

The /TL= and /TO= switches allow to specify filenames to use for
the temporary list file and temporary object file created by the
wllist facility. If not specified, temporary filenames in the
temporary directory are used. If /XS is specified, then these two
files will not be deleted upon the linker program's exit.

The /XLD switch increases the wllist debugging output levels.
Currently the most output is displayed if there are two or more
of the /XLD switches.

There's a new switch called /TZ. This forces use of a temporary
file to hold the executable image during pass 2, rather than
allowing the entire image to remain in DOS memory if it fits.

A bug that occurs when using the /TZ and /C switches is fixed.
It could occur under very specific conditions with the original
WarpLink revision as well, if setup_exe_image finds >= 20 KiB
but < the image size (which was limited to 64 KiB) of free DOS
memory available. If the bug occurs, then the 256-byte prefix
of the .COM file isn't skipped in the way it should be, and
instead the last 256 bytes of the image are truncated.

There is a new warning. If using the /C switch without the /CZ
switch, the linker discards (cuts) the first 256 bytes of the
executable image. The warning indicates that these bytes were
neither all-zeroes nor all NOP instructions (90h).

The /XCW switch, if enabled, treats many wlcalc-related errors
as warnings instead. This is useful to enumerate multiple
faulty wlcalc requests at once instead of needing to fix them
one by one and having to rerun the linker each time.
