User Tools

Site Tools


blog:pushbx:2023:1115_porting_the_amitsrs_tool_to_an_eld

Porting the amitsrs tool to an ELD

An early use case I had for Extensions for lDebug was to run a tool like amitsrs. (This originates in Ralf Brown's AMIS libraries, for working with the Alternate Multiplex Interrupt Specification.) It is more detailed and heavyweight than I wanted to add as a command that lives internally in the debugger. I did consider possibly being able to compile the original C program's source to an ELD with bespoke libraries and output, but ultimately did not pursue this path further. (The differences are mainly that I/O must be done using the debugger links, and segmentation is very different and by default involves a linker that makes the offsets of the ELD data block and ELD code instance position-independent within their respective segments.)

Bugs in original

Despite abandoning the C compiler, I did port amitsrs to become an ELD. This, then, simply involved porting the entire program to 8086 NASM assembly language. During testing this port, I found some bugs in the original program:

  • When a multiplexer lists more than one hotkey in the AMIS hotkey list, the tool would repeatedly display the first hotkey rather than advancing through the list. (Incidentally, the only example of the AMIS libraries to serve a hotkey list, NOTE, only has one hotkey.)
  • The specified hotkey scancode could overflow the array of known scancodes, including if the flag 80h is set (according to the AMIS, "hotkey triggers on release if bit 7 set")
  • Unknown scancodes within the array bounds would display as "nokey" as well even though the canonical "nokey" is only scancode zero

These bugs are fixed at least in a basic way by two changesets to my repo of amitsrs: 1 and 2. When adding support for displaying the hotkey list to amitsrs.eld, I based my work upon the fixed sources.

The process

eldstrict for ldmem.eld

The zeroth order was to enable eldstrict mode in the ldmem.eld what was used as a basis.

Skeleton

The first order was to create a basic skeleton that has a no-op run function.

The beginning

Next, the simple nonverbose output was implemented. This already required nontrivial string concatenation based on the "length" of the strings, which is folded into a simple printf in the C sources. The work was made only slightly more difficult by juggling the segment/selector that points to the multiplexer's signatures. (To work in a bimodal way (Protected Mode or 86 Mode), the debugger's setes2dx is used with the 86 Mode segment to obtain a usable seg/sel.) Unlike the C program, we do not need a near buffer to copy the signatures into. Also unlike the C program, we do use the line_out buffer to build the output eventually sent to puts, which is obscured by simply using printf in the original. Like all subsequent porting steps, the C sources were copied into the assembly source file as comments. I left these in as comments behind the respective parts of the ported sources eventually.

Multiplex number, version, private entrypoint

The second line of the verbose display was fairly straightforward. I did have to use the debugger's dec_dword_minwidth code link to replace the two-digit-minimum display of the minor version number.

Interrupt list

Next up was the interrupt list display. This required more juggling of the Extra Segment register to access the multiplexer's interrupt list interleaved with using the debugger's code links. The offset into the interrupt list was kept in BX. The line-buffering again diverges from the original sources, in that up to three entries are buffered in line_out until they are flushed to puts. Using printf is definitely easier to work with.

Hotkey list

A small step in preparation for the next changeset was to make the next label nonlocal, and put away the interrupts display into its own nonlocal label.

The final step in porting was to add the hotkey display. As mentioned, this was eventually based on the bugfixed revision of the original program. Some definitions from amis.h were copied into the assembly language sources, and properly NASMified. (Use percent sign for %define, do not double the backslash, comments with semicolons.) Again the 86 Mode segment, helpfully returned by the 86 Mode AMIS interface in a non-segment register, is fed to setes2dx to address the multiplexer's hotkey list. The function to set up the Extra Segment was renamed to get_saved_es, to indicate it is not used only for the interrupt list.

Two shift tables are used to loop through the various flags that can be set in the "required shift states" word. A last minute change was to split both tables into smaller sub-tables, as I found that some of the if trees matching these flags actually involved else if conditionals.

Other than that, there were some mmacros defined to convert the tables and if ladders into readable assembly sources. shiftentry accepts a numeric word as well as a message. scancodeentry accepts only a message. dumpmessages is used to write the messages saved by the two prior mmacros' calls, including their mmacro-local labels that these two mmacros use to refer to the messages.

Admin

The penultimate change was to add the credit for the original program to the assembly source file of the ELD.

Trim trailing blanks

Finally, the output of the ELD was changed to use trimputs in two places. This actually changes the behaviour from the original C program, but is considered a feature rather than a bug. Both the "INT 09h " and "INT 15h " messages have trailing blanks in the ELD. Only one of those ("INT 09h ") has the trailing blanks in the C program, but if only this message is displayed then the trailing blanks won't be removed by the printf powered output.

Further, if the description in the multiplexer's signatures is empty, the original program would display a trailing blank. This is also trimmed by the ELD.

The final trailing blank change is in the entry point display, which had a trailing blank for whatever reason. In the original program, all the way back to Ralf Brown's original release, there is an unconditional linebreak after this message has been written.

The result

The amitsrs ELD at this point is fully compatible to the original (minus the trailing blanks). Moreover, it allows operation as an ELD installed residently, so it can even run while InDOS is set. Here's how the sizes of the XLD and ELD compare to the original's latest revision as compiled by gcc-ia16:

test$ ls -lgG
total 48
-rwxr-xr-x 1 29034 Nov 14 23:40 amitsrs.com
-rw-r--r-- 1  4720 Nov 14 23:49 amitsrs.eld
-rw-r--r-- 1  4336 Nov 14 23:49 amitsrs.xld

The original is more than 5 times as large as the ELD! And that's with the ELD linker and resident installer and uninstaller contained in the ELD. Passing -O3 to the gcc-ia16 compiler helps a little, but not very much:

$ ./mak.sh -O3
$ ls -lgG amitsrs.com 
-rwxr-xr-x 1 27408 Nov 15 18:53 amitsrs.com

Further developments

After reaching the fully compatible port, I changed the parsing for verbose mode to require an explicit "VERBOSE" keyword rather than just any non-empty parameter. At the same time, it now accepts the keywords "MPX", "HOTKEYS", or "INT" to select just one of the verbose outputs.

Next, the keywords moved into a table, except for "VERBOSE" which sets several flags. This simplified adding some alias keywords, "VERSION", "ENTRY", "KEYS", "INTLIST", "INTERRUPTS".

The ELD will probably also soon learn how to query and display only a specified range of multiplex numbers.

You could leave a comment if you were logged in.
blog/pushbx/2023/1115_porting_the_amitsrs_tool_to_an_eld.txt · Last modified: 2023-11-15 19:31:02 +0100 Nov Wed by ecm