This shows you the differences between two versions of the page.
— |
blog:pushbx:2023:0707_the_amis_review [2023-07-07 13:34:03 +0200 Jul Fri] (current) ecm created |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== The AMIS review ====== | ||
+ | |||
+ | This article reviews various implementations of the Alternate Multiplex Interrupt Specification (AMIS) that I found. All of them are source-available if not free software. | ||
+ | |||
+ | I started notes for this review in 2022 December and wanted to finish it by 2023 June, but the SSD failure of the Linux box interfered with that. So now here it is a little late. | ||
+ | |||
+ | All files are either mirrored at https:// | ||
+ | |||
+ | |||
+ | ===== Ralf Brown (AMISLIB, various) ===== | ||
+ | |||
+ | * https:// | ||
+ | * Public Domain | ||
+ | * 1995-09-24 | ||
+ | * MASM | ||
+ | * uses '' | ||
+ | * bug: '' | ||
+ | * '' | ||
+ | * int 2Dh handler shares common tail code (eg '' | ||
+ | * int 2Dh handler can use a resident remover function? but uses a near call to call it then an '' | ||
+ | * switchar.asm uses it to return al == 4 and disable itself | ||
+ | * note.asm uses it to request a popup (amipopup.mac) with a flag set for shutdown, and if that succeeds it frees its file handle, returning al == 4 | ||
+ | * can support functions 0 (installation check), 1 (private entrypoint), | ||
+ | * extensive popup and hotkey support code | ||
+ | * int 2Dh uninstall function (if no remover function defined) sets bx using '' | ||
+ | * can go resident with 21.31 or 21.4C | ||
+ | * The program called " | ||
+ | * The program called " | ||
+ | * checks for resident instance and free multiplex number by counting from multiplex number 0 to 255 in a single loop | ||
+ | * can allocate an XMS UMB for installing resident | ||
+ | * can allocate a DOS UMB for installing resident, will patch MCB owner to itself and MCB name from process MCB | ||
+ | * can allocate a DOS LMB using last fit strategy, patched just like a DOS UMB | ||
+ | * if none of the above then 21.31 is used to terminate, environment segment is freed explicitly then. file handles not closed | ||
+ | * overwrites tail of PSP (first 64 (= 40h) bytes preserved) | ||
+ | * The program called " | ||
+ | * interrupt handler walker checks for word at '' | ||
+ | * uninstaller assumes that segment of memory block (as returned by AMIS uninstall function) is a UMB if >= 0B000h. if not an UMB or DOS UMBs are available it tries to deallocate the block using 21.49, else it attempts to use the XMS UMB deallocate function | ||
+ | * '' | ||
+ | |||
+ | |||
+ | ===== ecm (RxANSI, TSR example, seekext, lClock, KEEPHOOK, lDebug (partial), FDAPM (partial), IDLEDPMS, FreeDOS SHARE (partial)) ===== | ||
+ | |||
+ | * https:// | ||
+ | * various: Fair License, Public Domain, GNU GPL v2+ for FDAPM and FD SHARE | ||
+ | * 2023 May (still in development), | ||
+ | * NASM, mixed with gcc-ia16 component for FreeDOS SHARE | ||
+ | * '' | ||
+ | * uses several loops of AMIS installation check: | ||
+ | * before 2023 May: | ||
+ | * '' | ||
+ | * '' | ||
+ | * after 2023 May: | ||
+ | * '' | ||
+ | * '' | ||
+ | * additionally, | ||
+ | * if '' | ||
+ | * shares common tails of int 2Dh functions | ||
+ | * frees environment block | ||
+ | * relocates process to top of LMA during installation, | ||
+ | * allocates a DOS memory block for resident program in the UMA (not if /JU switch specified) or LMA, without a PSP | ||
+ | * hacks MCB owner to the memory block itself, MCB name to a hardcoded string | ||
+ | * does not close file handles but termination using 21.4C will always take care of those | ||
+ | * detects whether allocated resident block is in the UMA or LMA, but only for an informational message choice | ||
+ | * provides /X= option to try a specific multiplex number first (for '' | ||
+ | * checks TSR version for compatible values | ||
+ | * provide private functions to retrieve control variables, allowing to modify some behaviour | ||
+ | * advanced deinstallation method, searching for the downlink matching our handler in other AMIS multiplexers' | ||
+ | * checks for valid interrupt handlers to chain to while hooking | ||
+ | * simulates hooking and unhooking interrupt handlers before actually starting, allowing to generally notice error conditions without ending up with a halfway (un)installed resident instance | ||
+ | * includes uninstaller in every program, though can also be uninstalled using generic remove tools | ||
+ | * interrupt handler walker checks for: | ||
+ | * offset is not too high, to avoid accessing a word at offset FFFFh | ||
+ | * " | ||
+ | * byte '' | ||
+ | * byte '' | ||
+ | |||
+ | |||
+ | ===== ecm (TESTALOC) ===== | ||
+ | |||
+ | * https:// | ||
+ | * Fair License | ||
+ | * 2022-02-22 | ||
+ | * NASM | ||
+ | * like other ecm TSR example based programs, but allows to include a fully resident uninstaller (2023 May updates not included) | ||
+ | * builds a trampoline on the caller' | ||
+ | |||
+ | |||
+ | ===== Pino Navato (KEYBIT Lite, AltMenu) ===== | ||
+ | |||
+ | * https:// | ||
+ | * CARDWARE | ||
+ | * 1999-09-13 | ||
+ | * MASM | ||
+ | * based on AMISLIB: Version 0.91.K6 (custom version by Pino Navato for KEYBIT Lite v6+) | ||
+ | |||
+ | |||
+ | ===== Donald Bindner (IDLEHALT, DVORAK96) ===== | ||
+ | |||
+ | * https:// | ||
+ | * GNU GPL v2+ | ||
+ | * 1999-02-17 | ||
+ | * NASM + A86 (DVORAK96), A86 (IDLEHALT) | ||
+ | * does not use SMC '' | ||
+ | * after '' | ||
+ | * uses '' | ||
+ | * needs an 186 ('' | ||
+ | * uses '' | ||
+ | * may use 21.31 to install resident | ||
+ | * may allocate PSP-alike block in DOS UMBs if the cs is <= B800h, copies name from PSP MCB and sets owner to the UMB itself, then terminates with 21.4C | ||
+ | * frees environment block | ||
+ | * does not free file handles | ||
+ | * searches for free multiplex number and a resident instance from multiplex number 255 to 0 | ||
+ | * hardware reset function uses a '' | ||
+ | * '' | ||
+ | * no removal handler nor unhooking handling included | ||
+ | * dvorak: docs suggest using Ralf Brown' | ||
+ | * idlehalt: function 2 is supported and disables program, docs suggest it cannot be uninstalled | ||
+ | * "I would appreciate comments or bug reports sent to Don Bindner < | ||
+ | * allows to disable and enable by using the program; expects to find the byte to XOR with 1 at a hardcoded offset within the segment of the AMIS signature | ||
+ | |||
+ | |||
+ | ===== Davide Bresolin (EATUMBS) ===== | ||
+ | |||
+ | * https:// | ||
+ | * MIT License | ||
+ | * 2022-11-21 | ||
+ | * two-component: | ||
+ | * '' | ||
+ | * does do '' | ||
+ | * does not use '' | ||
+ | * unneeded '' | ||
+ | * uses multiple '' | ||
+ | * uses '' | ||
+ | * '' | ||
+ | * searches from multiplex number 0 to 255 | ||
+ | * IISP header walker: | ||
+ | * entrypoint == EBh byte, " | ||
+ | * creates '' | ||
+ | * does not use interrupt list from AMIS function 4, assumes only the int 2Dh handler is hooked | ||
+ | * does short jumps to '' | ||
+ | |||
+ | |||
+ | ===== George A. Theall or GAT (EATMEM, RECALL) ===== | ||
+ | |||
+ | * https:// | ||
+ | * Public Domain | ||
+ | * 1995-03-26 | ||
+ | * MASM | ||
+ | * uses data behind PSP and entrypoint jump: AMIS signature (16 bytes + ASCIZ string), AMIS TSR version number (word), Multiplex number (byte), interrupt list (AMIS style) | ||
+ | * RECALL: switches stack to its own during 21.0A call | ||
+ | * uses multiplex number in a separate variable, not ecm RENUMBER compatible | ||
+ | * int 2Dh handler starts with '' | ||
+ | * int 2Dh handler does not run a '' | ||
+ | * int 2Dh handler could share zeroing of al and '' | ||
+ | * int 2Dh handler uses '' | ||
+ | * int 2Dh installation check handler loads the version number in cx from the structure behind the PSP instead of hardcoding it with a '' | ||
+ | * int 2D handler only implements the installation check (no uninstall function support, no interrupt list function support) | ||
+ | * leaves resident a modified/ | ||
+ | * uses 21.31 to stay resident | ||
+ | * does not free file handles | ||
+ | * RECALL: uses '' | ||
+ | * interrupt handler walker checks for byte at '' | ||
+ | * checks for int 2Dh handler starting with 0CFh ('' | ||
+ | * checks from multiplex number 0 to 255 both for finding a resident instance and for determining free multiplex number | ||
+ | * uses offset of interrupt table hardcoded into transient program (segment of AMIS signature) | ||
+ | * in uninstall frees environment block found from PSP, if address is still nonzero (assumes that segment of AMIS signature is also PSP segment). so if the AMIS uninstall function was supported then the environment segment should be handled in some way, too. | ||
+ | * bug: accesses the interrupt list using bp as a base register, so it actually accesses the interrupt list of the transient instance because addresses with bp use the stack segment by default. but if the contents of the transient and resident interrupt list match then the right thing happens anyway, so this is equivalent to hardcoding the offset of the interrupt entrypoints and their IISP headers. | ||
+ | * includes INTPROTO.TXT (Chris Dunford text about the IISP) | ||
+ | * confusingly named '' | ||
+ | * function '' | ||
+ | |||
+ | |||
+ | ===== Jim Leonard (SOFTHDDI) ===== | ||
+ | |||
+ | * https:// | ||
+ | * MIT License | ||
+ | * 2022-12-05 | ||
+ | * MASM | ||
+ | * based on AMISLIB version 0.92 | ||
+ | |||
+ | |||
+ | ===== Marcus Better (iHPFS) ===== | ||
+ | |||
+ | * https:// | ||
+ | * GNU GPL v2+ | ||
+ | * 2000-07-29 | ||
+ | * TASM ideal mode | ||
+ | * 386+ | ||
+ | * "You are welcome to send me any ideas, comments and suggestions for iHPFS. | ||
+ | * '' | ||
+ | * int 2Dh handler behind IISP header starts with a '' | ||
+ | * uses multiple '' | ||
+ | * frees environment segment | ||
+ | * counts from 0 to 255 to find a free multiplex number | ||
+ | * likewise to find resident instance | ||
+ | * segment size additions and shifting at run time | ||
+ | * allocates XMS and sets up CDS entries, but AMIS function 2 does not free those | ||
+ | * sets current PSP to resident copy to uninstall so that 21.4A will set the resident block as owner, not the transient copy's | ||
+ | * does not walk IISP header chain, only checks for IVT entries pointing directly at the resident instance | ||
+ | * does not call AMIS function 4 to get the interrupt list, hardcodes the interrupt handler offsets | ||
+ | * resizes the memory block before patching the entrypoints so that a call could occur while block is already truncated | ||
+ | * if not both handlers (2Fh and 2Dh) as topmost handlers will instead resize block and patch both IISP headers to hold 90h, EAh ('' | ||
+ | |||
+ | |||
+ | ===== Douglas Boling at PC Magazine / CyberRax (CALC 1.1) ===== | ||
+ | |||
+ | * https:// | ||
+ | * unclear usage conditions (released with sources in PC Magazine) | ||
+ | * 2001-12-09 | ||
+ | * TASM | ||
+ | * 286+ | ||
+ | * standard IISP, '' | ||
+ | * interrupt handler entrypoints both happen to be on odd offsets | ||
+ | * does not issue a '' | ||
+ | * not ecm RENUMBER compatible: int 2Dh handler starts with '' | ||
+ | * int 09h handler has the EOI flag set | ||
+ | * runs its pop up on the int 09h call's stack | ||
+ | * has an AMIS hotkey list | ||
+ | * reverses the bit counting in "type of AMIS hotkey checking" | ||
+ | * "AMIS shift states" | ||
+ | * function 02h (uninstall) returns a non-standard return code 4 (now disabled, no resident uninstaller) with a return value in dx indicating " | ||
+ | * can allocate an XMS memory block for screen swapping. AMIS private function 20h gets the XMS handle in bx, al = 0FFh. XMS handle needs to be freed by the remover, so Ralf Brown' | ||
+ | * AMIS private function 30h returns status in bl, al = 0FFh. AMIS private function 31h sets status from bl, returns al = 0FFh (status is expected as 0 or 1). | ||
+ | * int 2Dh handler ends in '' | ||
+ | * does one loop from multiplex number 0 to 255, checking for already resident copy and noting the first found free number | ||
+ | * uses '' | ||
+ | * can set a variable named '' | ||
+ | * if found resident, checks private function 30h support (" | ||
+ | * ignores blanks, tabs, slashes, and hyphens in command line, parses known switches as just the letters | ||
+ | * E = Enable | ||
+ | * D = Disable | ||
+ | * I = Install (does not automatically install) | ||
+ | * U = Uninstall | ||
+ | * X = Do not use XMS | ||
+ | * P = Pop up a resident instance | ||
+ | * H = Help | ||
+ | * ? = Help | ||
+ | * all others: ignored silently! | ||
+ | * uses its xms_handle variable as a flag, handle number 0 is assumed to be invalid (used to indicate no handle allocated). this is not good. | ||
+ | * frees environment segment but does not clear the PSP field | ||
+ | * does not free file handles | ||
+ | * goes resident with interrupt 21h service 31h | ||
+ | * relocates resident portion (and installer) from the default load address CS:100h to CS:40h and subtracts 0Ch from segregs to address the relocated program at offset 100h. this is the cause of the ill-advised non-standard function 2 (uninstall) return value | ||
+ | * (NB this assumes DOS can terminate the process with only the first 64 bytes of the PSP preserved, much like Ralf Brown' | ||
+ | * interrupt 21h service 31h return size is calculated properly at build time (delta of the initialize function and code segment start, + 15 for rounding up, - 0C0h for relocation, '' | ||
+ | * uninstaller: | ||
+ | * calls function 2 and checks for return 5, but does not check for another return value (assumes all non-5 return values are return value 4) | ||
+ | * checks that int 9 and int 2Dh vectors in the IVT point to "code segment" | ||
+ | * checks that offsets of int 9 and int 2Dh vectors match the hardcoded offsets of the transient uninstaller' | ||
+ | * checks that function 20h is supported with al returning 0FFh and tries to free the XMS handle if it is returned as nonzero | ||
+ | * gets address of XMM without properly detecting that an XMM is present | ||
+ | * can display status (enabled/ | ||
+ | * never calls AMIS function 4 (determine chained interrupts) | ||
+ | * uninstalling and installing take precedence over disabling or enabling or popping up | ||
+ | * popping up takes precedence over disabling or enabling | ||
+ | * popping up with P switch is possible even while disabled | ||
+ | * if both disable and enable or both uninstall and install are specified then an error is issued | ||
+ | |||
+ | |||
+ | {{tag> | ||
+ | |||
+ | |||
+ | ~~DISCUSSION~~ | ||