浏览代码

runtime: MBF formatting and parsing (fmtreal/ascreal)

Two new entries, transcribed from TPSRC3:

  * real_fmt (entry 28, fmtreal).  [BP+4] real, [BP+6] destination;
    CX = (decimals << 8) | width.  Writes a length-prefixed, left-padded
    field and returns its length.  DEC >= 25 selects the reference's
    scientific mode and derives the decimals from the width.  The helpers
    (realdec, decround, fdig*, m10, rrange, the fltdec table) are the
    reference's.  Ten exact-output cases.

  * real_val (entry 29, ascreal).  [BP+4] ASCIIZ source, [BP+6] real
    destination; AX = the first unparsed offset, FFFFh on a hard error
    (destination untouched).  Thirty cases, checking both the offset and
    the packed value (including untouched EEEE poison on error).

Four transcription traps, all caught by the exact cases:

  * LdBxDiOff/LdDxDiOff were 8B 5F/57 = [BX+off], not [DI+off].
  * StDataImm is a WORD store; zeroing the one-byte exponent counter also
    zeroed the first fltdec byte (1e0), so negative-exponent parses divided
    by zero.  Added StDataByte.
  * rd_core is the post-testexp add core; its caller must set resign.  The
    parser's digit add inherited the previous result's sign, corrupting
    every digit after the first.  It now sets resign = 0.
  * the DEC >= 25 path used SUB DL,AL (28 C2) for SUB AL,DL (2A C2).

The runtime this needs (3381 bytes) pushed the string fixtures past the
old 8 KiB boot-sector read, so item 14 is done too: bootcom.s reads 72
sectors one at a time into 1000:0000 (state saved around INT 13h, which
may clobber every register), copies 0x7000 bytes to 0100h, and puts the
input descriptor at 0x7000.  The image may reach 0x6F00 (28,416 bytes),
enough for CALC's 27,901, while the boot sector at 0x7C00 is never
overwritten.  t51/t52 run again; t64_arrays is compile-only only because
it has no .out.

rt_exec 256/256; run_com_exec 72/72; check_runtime and the audit pass;
non-vacuity 115/115 (LdBxDiOff -> [BX+off] and the parser's resign=8000h
must each turn their real case red); run_all ALL PASS.
Eric Streit 1 天之前
父节点
当前提交
3c758774e9

+ 55 - 25
CALC-COMPILE.md

@@ -484,9 +484,9 @@ Exec86):
   declarations half)** — multi-range array types with row-major sizing stored
   in an `ArrRec` (`Sheet` = 11760), globals of array type, and
   `XPOS : array[…] of Integer = (…)` emitted code-resident like a set.
-  Fixture `t64_arrays` (compile-only: its ~16 KB image is past the exec
-  harness's 8 KB boot-sector read). `t14` re-baselined: the array DECLARES now;
-  the refusal moved to element access.
+  Fixture `t64_arrays` (compile-only because it has no `.out`; its ~16 KB
+  image now fits the raised 0x7000-byte read). `t14` re-baselined: the array
+  DECLARES now; the refusal moved to element access.
 - **File TYPES are landed (Stage 13, first half).** `text` and `file of T`; a
   file variable is our control block (`FileVarSize` = 4). Fixture `t66_files`.
   This is the step that carried the compiler **inside `CALC.INC`**: the whole
@@ -550,13 +550,14 @@ Exec86):
   been green and only `t40_readln` (and later CALC) would have noticed.
 - **Verified baseline, run on the code HEAD above:** `./tests/run_all.sh` →
   **OVERALL: ALL PASS**, compile matrix **83/83**, CALC ladder **1/1** at
-  `ERR 102 18267`, terminal config **4/4**, 64 `.COM` linked and **72 executed
-  under both qemu and Exec86** (`t64_arrays` is compile-only: its image is past
-  the 8 KB boot-sector read).  `tests/nonvacuity.sh`: **113 ok, 0 failed**.
-  The runtime is 2059 bytes (wrintw, real_from_int, real_add, real_sub,
-  real_mul, real_div, real_cmp, real_int; the golden was re-blessed) and
-  `tests/rt_exec.py` passes **191/191**, including 16 add/sub, ten multiply,
-  fourteen division, thirty comparison and eighteen Int exact-byte cases.
+  `ERR 102 18267`, terminal config **4/4**, 74 `.COM` linked and **72 executed
+  under both qemu and Exec86** (`t64_arrays` remains compile-only because it
+  has no `.out`; its ~16 KB image now fits the raised read).  `tests/nonvacuity.sh`:
+  **115 ok, 0 failed**.  The runtime is 3381 bytes (wrintw, real_from_int,
+  real_add, real_sub, real_mul, real_div, real_cmp, real_int, real_fmt,
+  real_val; the golden was re-blessed) and `tests/rt_exec.py` passes
+  **256/256**, including 16 add/sub, ten multiply, fourteen division, thirty
+  comparison, eighteen Int, ten format and thirty parse cases.
   `check_realconst.py` pins the measured 6-byte Real operand bytes.
 - **`tests/nonvacuity.sh`:** re-run after this commit's cases (the set
   membership bit among them); see the commit message for the count. It is not in
@@ -721,20 +722,48 @@ Then the two that are *outside* the ladder and gate the goal as stated:
         Exponents >= 0A8h (2^39) are already integral and return unchanged;
         <= 80h give zero.  Eighteen rt_exec cases, including 12345.75 -> 12345
         and 2^40 unchanged.
-      * **NEXT:** `fmtreal`/`ascreal` for `Write(Value:FW:DEC)`, `Str` and
-        `Val`.  Each is a direct transcription with rt_exec cases.
-      * **HEADROOM:** the runtime is 2059 bytes and the probe's scaffold now
-        starts at HDR=0x0A00 with RT_BASE=0x0190, so the ceiling is 2160
-        bytes - about 100 bytes left.  The next real rung will need another
-        shift of rtdrv.s/rt_exec.py, or a larger probe image.
+      * **DONE: `real_fmt`** (`v-TP3-MBF-CONV`, entry 28) and **`real_val`**
+        (entry 29).  TPSRC3's `fmtreal` and `ascreal`, with their helpers
+        (`realdec`, `decround`, `fdig*`, `m10`, `rrange`, the fltdec table)
+        transcribed.  `real_fmt`: [BP+4] real, [BP+6] destination, CX =
+        (decimals << 8) | width; writes a length-prefixed, left-padded field
+        and returns its length.  DEC >= 25 selects the reference's scientific
+        mode and derives the decimals from the width.  `real_val`: [BP+4]
+        ASCIIZ source, [BP+6] destination; returns AX = the first unparsed
+        offset, or FFFFh on a hard error (destination untouched).  Ten format
+        and thirty parse exact-byte cases.
+        Traps:
+          - `LdBxDiOff`/`LdDxDiOff` were `8B 5F/57`, i.e. **[BX+off]**, not
+            [DI+off]; only the exact output showed it.
+          - `StDataImm` is a WORD store.  Zeroing the one-byte exponent
+            counter also zeroed the first fltdec byte (1e0), so every
+            negative-exponent parse divided by zero.  Added `StDataByte`.
+          - `rd_core` is the post-testexp add core: its caller must set
+            `resign`.  The parser's digit add left the previous result's sign
+            there, corrupting every digit after the first.
+          - `rc_fmt`'s DEC>=25 path used `SUB DL,AL` (28 C2) instead of
+            `SUB AL,DL` (2A C2).
+      * **NEXT:** wire `Write(Value:FW:DEC)` and `Str`/`Val` in the compiler.
+        The runtime entries are ready; the compiler still refuses a real
+        width/decimals and has no real-expression model.
+      * **HEADROOM:** the runtime is 3381 bytes and the probe's scaffold starts
+        at HDR=0x0F00 with RT_BASE=0x0190, so the ceiling is 3440 bytes - about
+        59 bytes left.  The boot read now allows a .COM up to 0x6F00, so the
+        next runtime addition should move HDR up (e.g. 0x2000) and shift the
+        blocks with it; there is room below the input at 0x7000.
       * **THEN** the compiler side: real expressions need a value model
         (pointers to 6-byte temporaries), real comparisons, and real function
         results (currently refused because the result is wider than a word).
 
-14. **Raise the execution harness's read.**  `tests/exec/bootcom.s` reads 16
-    sectors (8192 bytes); `t64_arrays` is already compile-only for that reason,
-    and CALC's measured `.COM` is **27,901 bytes**.  Without this, "executable
-    tested" cannot be demonstrated for CALC even once it compiles.
+14. **Raise the execution harness's read — DONE (`v-TP3-MBF-CONV`).**
+    `tests/exec/bootcom.s` now reads **72 sectors (36,864 bytes)** into
+    `1000:0000`, one sector per INT 13h call with the loop state pushed around
+    the call (the BIOS may clobber every register; POP does not touch CF), and
+    copies `COPY_BYTES = 0x7000` down to `0100`.  The input descriptor moved to
+    `0x7000`, so the image may reach `0x6F00` (**28,416 bytes**) while staying
+    below the boot sector at `0x7C00`.  CALC's measured `.COM` is **27,901
+    bytes**, which now fits.  `t64_arrays` remains compile-only only because it
+    has no `.out`, not because of the read.
 
 **Two things settled this session, not to re-litigate:**
 
@@ -947,11 +976,12 @@ today, and `with`.  Both wait on the same scaled-addressing work.
   constants are now listed in `CODE_RESIDENT_CONST` and clause F is skipped for
   them; the runtime sweep (the backbone) and the execution oracles still cover
   the emitted instructions.
-- **The execution harness reads 8192 bytes.**  `tests/exec/bootcom.s` reads 16
-  sectors, and `t64_arrays`'s image is already ~16 KB - so it is compile-only,
-  and **CALC's measured `.COM` is 27,901 bytes**.  Running CALC therefore needs
-  the boot sector's read raised as well as the layout change; both are on the
-  execution path.
+- **The execution harness's read is raised.**  `tests/exec/bootcom.s` reads 72
+  sectors and copies 0x7000 bytes; the input is at 0x7000, the image may reach
+  0x6F00, and the boot sector at 0x7C00 is never overwritten.  CALC's 27,901
+  bytes fit; `t64_arrays` is compile-only because it has no `.out`, not for
+  size.  The remaining CALC execution gate is the layout change (§3), not the
+  loader.
 
 **Stage 9 — pointers and the heap.** `^T` (4 bytes, offset then segment),
 `New`/`Dispose`, `Buffer^[i]` read/write, `Buffer^[0] := st` (assignment to a

+ 2 - 0
shell/Runtime.def

@@ -60,6 +60,8 @@ CONST
    E_RealDiv = 25 ;         (* ...and division: a / b *)
    E_RealCmp = 26 ;         (* real comparison: AX = -1/0/+1 for a<b, a=b, a>b *)
    E_RealInt = 27 ;         (* Int(real): truncate the mantissa in place *)
+   E_RealFmt = 28 ;         (* fmtreal: a padded length-prefixed field *)
+   E_RealVal = 29 ;         (* ascreal: parse an ASCIIZ string into a real *)
 
    (* Where a .COM's first byte ends up.  DOS loads a .COM at CS:0100 (the
       100 bytes below are the PSP), and CS = DS, so an image offset K is at

+ 703 - 15
shell/Runtime.mod

@@ -47,7 +47,7 @@ CONST
       that case; the fill checks below make any future overflow a HALT instead
       of wrong code.  tests/check_runtime.py's branch-boundary check is what
       caught this one. *)
-   MaxLbl = 160 ;       (* the MBF core's labels took the count past 96 *)
+   MaxLbl = 320 ;       (* fmtreal/ascreal added ~70 labels to the MBF core's 160 *)
    MaxFix = 768 ;
    MaxNm  = 15 ;
 
@@ -82,7 +82,17 @@ CONST
    D_RMUL21 = 41 ;    (* b's saved CX (low byte is the exponent, skipped) *)
    D_RMUL22 = 43 ;    (* b's saved SI *)
    D_RMUL23 = 45 ;    (* b's saved DI *)
-   D_END   = 47 ;     (* the block is padded to here *)
+   D_CVOUT  = 47 ;    (* 12 bytes: realdec's decimal digits *)
+   D_CVDECEXP = 59 ;  (* realrang's decimal exponent, sign in bit 7 *)
+   D_CVEXPCNT = 60 ;  (* ascreal's decimal-point counter *)
+   D_FLTDEC = 61 ;    (* 10 x 6 bytes: 1e0, 1e4, ... 1e36 (TPSRC3) *)
+   D_FMTBUF = 121 ;   (* 64 bytes: fmtreal's unpadded output *)
+   D_FMTLEN = 185 ;   (* 2 bytes: its length *)
+   D_FMTW   = 187 ;   (* 2 bytes: the requested field width *)
+   D_FMTPAD = 189 ;   (* 2 bytes: left padding *)
+   D_FMTTOT = 191 ;   (* 2 bytes: pad + length *)
+   D_ASCSRC = 193 ;   (* 2 bytes: ascreal's source pointer *)
+   D_END   = 195 ;    (* the block is padded to here *)
 
    (* THE LOAD BIAS.  Everything above is an offset into the image as this
       compiler numbers it: the entry JMP is at image 0.  But a DOS .COM is
@@ -139,7 +149,7 @@ VAR
    dataAt : CARDINAL ;
    rtBase : CARDINAL ;
    built  : BOOLEAN ;
-   entNm  : ARRAY [0..27] OF ARRAY [0..MaxNm] OF CHAR ;
+   entNm  : ARRAY [0..29] OF ARRAY [0..MaxNm] OF CHAR ;
 
 (* ---------------------------------------------------------------- *)
 (*  name helpers                                                     *)
@@ -697,6 +707,104 @@ PROCEDURE CmpAhData (delta : CARDINAL) ;
 BEGIN B (3AH) ; B (26H) ; Dd (delta) END CmpAhData ;
 PROCEDURE SubAhData (delta : CARDINAL) ;
 BEGIN B (2AH) ; B (26H) ; Dd (delta) END SubAhData ;  (* SUB.B AH,remul21a: ignores the carry *)
+
+(* --- the real formatter/parser's instruction set (fmtreal/ascreal) ------ *)
+PROCEDURE Jl8  (nm : ARRAY OF CHAR ) ; BEGIN Jcc (7CH, nm) END Jl8 ;
+PROCEDURE Jg8  (nm : ARRAY OF CHAR ) ; BEGIN Jcc (7FH, nm) END Jg8 ;
+PROCEDURE MovAxBx ; BEGIN B (89H) ; B (0D8H) END MovAxBx ;       (* AX:=BX *)
+PROCEDURE MovAxSi ; BEGIN B (89H) ; B (0F0H) END MovAxSi ;       (* AX:=SI *)
+PROCEDURE MovSiDi ; BEGIN B (89H) ; B (0FEH) END MovSiDi ;       (* SI:=DI *)
+PROCEDURE MovBlCl ; BEGIN B (88H) ; B (0CBH) END MovBlCl ;       (* BL:=CL *)
+PROCEDURE MovChDh ; BEGIN B (88H) ; B (0F5H) END MovChDh ;       (* CH:=DH *)
+PROCEDURE MovChCl ; BEGIN B (88H) ; B (0CDH) END MovChCl ;       (* CH:=CL *)
+PROCEDURE MovDlCh ; BEGIN B (88H) ; B (0EAH) END MovDlCh ;       (* DL:=CH *)
+PROCEDURE MovDhAl ; BEGIN B (88H) ; B (0C6H) END MovDhAl ;       (* DH:=AL *)
+PROCEDURE MovClAh ; BEGIN B (88H) ; B (0E1H) END MovClAh ;       (* CL:=AH *)
+PROCEDURE MovClAl ; BEGIN B (88H) ; B (0C1H) END MovClAl ;       (* CL:=AL *)
+PROCEDURE MovAhAl ; BEGIN B (88H) ; B (0C4H) END MovAhAl ;       (* AH:=AL *)
+PROCEDURE MovAlCl ; BEGIN B (88H) ; B (0C8H) END MovAlCl ;       (* AL:=CL *)
+PROCEDURE MovChImm (v : CARDINAL) ;
+BEGIN B (0B5H) ; B (v MOD 256) END MovChImm ;                    (* MOV CH,imm8 *)
+PROCEDURE CmpDxImm (v : CARDINAL) ;
+BEGIN B (81H) ; B (0FAH) ; W (v) END CmpDxImm ;                  (* CMP DX,imm16 *)
+PROCEDURE CmpAxImm (v : CARDINAL) ;
+BEGIN B (3DH) ; W (v) END CmpAxImm ;                             (* CMP AX,imm16 *)
+PROCEDURE CmpDl0 ; BEGIN B (80H) ; B (0FAH) ; B (0) END CmpDl0 ;
+PROCEDURE TestChImm (v : CARDINAL) ;
+BEGIN B (0F6H) ; B (0C5H) ; B (v MOD 256) END TestChImm ;        (* TEST CH,imm8 *)
+PROCEDURE TestDiOffImm (off, v : CARDINAL) ;
+BEGIN B (0F6H) ; B (45H) ; B (off MOD 256) ; B (v MOD 256) END TestDiOffImm ;
+PROCEDURE AndClImm (v : CARDINAL) ;
+BEGIN B (80H) ; B (0E1H) ; B (v MOD 256) END AndClImm ;          (* AND CL,imm8 *)
+PROCEDURE AndBlImm (v : CARDINAL) ;
+BEGIN B (80H) ; B (0E3H) ; B (v MOD 256) END AndBlImm ;          (* AND BL,imm8 *)
+PROCEDURE OrChImm (v : CARDINAL) ;
+BEGIN B (80H) ; B (0CDH) ; B (v MOD 256) END OrChImm ;           (* OR CH,imm8 *)
+PROCEDURE AddChImm (v : CARDINAL) ;
+BEGIN B (80H) ; B (0C5H) ; B (v MOD 256) END AddChImm ;          (* ADD CH,imm8 *)
+PROCEDURE AddClImm (v : CARDINAL) ;
+BEGIN B (80H) ; B (0C1H) ; B (v MOD 256) END AddClImm ;          (* ADD CL,imm8 *)
+PROCEDURE ShrChCl ; BEGIN B (0D2H) ; B (0EDH) END ShrChCl ;      (* SHR CH,CL *)
+PROCEDURE ShrBl1 ; BEGIN B (0D0H) ; B (0EBH) END ShrBl1 ;        (* SHR BL,1 *)
+PROCEDURE ShlAx1 ; BEGIN B (0D1H) ; B (0E0H) END ShlAx1 ;        (* SHL AX,1 *)
+PROCEDURE ShlAl1 ; BEGIN B (0D0H) ; B (0E0H) END ShlAl1 ;        (* SHL AL,1 *)
+PROCEDURE AddBlBh ; BEGIN B (00H) ; B (0FBH) END AddBlBh ;       (* BL:=BL+BH *)
+PROCEDURE XorBhBh ; BEGIN B (30H) ; B (0FFH) END XorBhBh ;       (* BH:=0 *)
+PROCEDURE AddAlAh ; BEGIN B (00H) ; B (0E0H) END AddAlAh ;       (* AL:=AL+AH *)
+PROCEDURE AddAxCx ; BEGIN B (03H) ; B (0C1H) END AddAxCx ;       (* AX:=AX+CX *)
+PROCEDURE AdcBxCx ; BEGIN B (13H) ; B (0D9H) END AdcBxCx ;       (* BX:=BX+CX+CF *)
+PROCEDURE AdcDxCx ; BEGIN B (13H) ; B (0D1H) END AdcDxCx ;       (* DX:=DX+CX+CF *)
+PROCEDURE AddAxDx ; BEGIN B (03H) ; B (0C2H) END AddAxDx ;       (* AX:=AX+DX *)
+PROCEDURE AddBxAx ; BEGIN B (03H) ; B (0D8H) END AddBxAx ;       (* BX:=BX+AX *)
+PROCEDURE SubAxDx ; BEGIN B (2BH) ; B (0C2H) END SubAxDx ;       (* AX:=AX-DX *)
+PROCEDURE AddAxImm (v : CARDINAL) ;
+BEGIN B (05H) ; W (v) END AddAxImm ;                             (* ADD AX,imm16 *)
+PROCEDURE DecBx ; BEGIN B (4BH) END DecBx ;                      (* DEC BX *)
+PROCEDURE DecCh ; BEGIN B (0FEH) ; B (0CDH) END DecCh ;          (* DEC CH *)
+PROCEDURE DecDl ; BEGIN B (0FEH) ; B (0CAH) END DecDl ;          (* DEC DL *)
+PROCEDURE NegCl ; BEGIN B (0F6H) ; B (0D9H) END NegCl ;          (* NEG CL *)
+PROCEDURE Cbw ; BEGIN B (98H) END Cbw ;                          (* AL -> AX *)
+PROCEDURE ImulDx ; BEGIN B (0F7H) ; B (0EAH) END ImulDx ;        (* IMUL DX *)
+PROCEDURE StSiImm (v : CARDINAL) ;
+BEGIN B (0C7H) ; B (04H) ; W (v) END StSiImm ;                   (* [SI]:=imm16 *)
+PROCEDURE StSiAl ; BEGIN B (88H) ; B (04H) END StSiAl ;          (* [SI]:=AL *)
+PROCEDURE StSiCh ; BEGIN B (88H) ; B (2CH) END StSiCh ;          (* [SI]:=CH *)
+PROCEDURE StBxAl ; BEGIN B (88H) ; B (07H) END StBxAl ;          (* [BX]:=AL *)
+PROCEDURE LdAlSi ; BEGIN B (8AH) ; B (04H) END LdAlSi ;          (* AL:=[SI] *)
+PROCEDURE LdClBx ; BEGIN B (8AH) ; B (0FH) END LdClBx ;          (* CL:=[BX] *)
+PROCEDURE LdAlDi ; BEGIN B (8AH) ; B (05H) END LdAlDi ;          (* AL:=[DI] *)
+PROCEDURE XorDiOffImm (off, v : CARDINAL) ;
+BEGIN B (80H) ; B (75H) ; B (off MOD 256) ; B (v MOD 256) END XorDiOffImm ;
+PROCEDURE LdClSi ; BEGIN B (8AH) ; B (0CH) END LdClSi ;          (* CL:=[SI] *)
+PROCEDURE LdAxDi ; BEGIN B (8BH) ; B (05H) END LdAxDi ;          (* AX:=[DI] *)
+PROCEDURE LdBxDiOff (off : CARDINAL) ;
+BEGIN B (8BH) ; B (5DH) ; B (off MOD 256) END LdBxDiOff ;   (* [DI+off] *)
+PROCEDURE LdDxDiOff (off : CARDINAL) ;
+BEGIN B (8BH) ; B (55H) ; B (off MOD 256) END LdDxDiOff ;   (* [DI+off] *)
+PROCEDURE LeaDiBxData (delta : CARDINAL) ;
+BEGIN B (8DH) ; B (0BFH) ; Dd (delta) END LeaDiBxData ;          (* LEA DI,[BX+data] *)
+PROCEDURE MovSiData (delta : CARDINAL) ;
+BEGIN B (0BEH) ; Dd (delta) END MovSiData ;
+PROCEDURE MovBxDataAddr (delta : CARDINAL) ;
+BEGIN B (0BBH) ; Dd (delta) END MovBxDataAddr ;
+PROCEDURE CmpSiData (delta : CARDINAL) ;
+BEGIN B (81H) ; B (0FEH) ; Dd (delta) END CmpSiData ;
+PROCEDURE MovAxData (delta : CARDINAL) ;
+BEGIN B (8BH) ; B (06H) ; Dd (delta) END MovAxData ;
+PROCEDURE LdClData (delta : CARDINAL) ;
+BEGIN B (8AH) ; B (0EH) ; Dd (delta) END LdClData ;
+PROCEDURE DecData (delta : CARDINAL) ;
+BEGIN B (0FEH) ; B (0EH) ; Dd (delta) END DecData ;
+PROCEDURE CmpBxByte (v : CARDINAL) ;
+BEGIN B (80H) ; B (3FH) ; B (v MOD 256) END CmpBxByte ;          (* CMP [BX],imm8 *)
+PROCEDURE MovBxByte (v : CARDINAL) ;
+BEGIN B (0C6H) ; B (07H) ; B (v MOD 256) END MovBxByte ;         (* [BX]:=imm8 *)
+PROCEDURE MovBxOff1Byte (v : CARDINAL) ;
+BEGIN B (0C6H) ; B (47H) ; B (1) ; B (v MOD 256) END MovBxOff1Byte ;
+PROCEDURE IncBxByte ; BEGIN B (0FEH) ; B (07H) END IncBxByte ;    (* INC [BX] *)
+PROCEDURE MovDiBp6 ; BEGIN B (8BH) ; B (7EH) ; B (6) END MovDiBp6 ;
+PROCEDURE MovDxBp6 ; BEGIN B (8BH) ; B (56H) ; B (6) END MovDxBp6 ;
+PROCEDURE PushBp6 ; BEGIN B (0FFH) ; B (76H) ; B (6) END PushBp6 ;
 PROCEDURE SbbBxData (delta : CARDINAL) ;
 BEGIN B (1BH) ; B (1EH) ; Dd (delta) END SbbBxData ;
 PROCEDURE SbbDxData (delta : CARDINAL) ;
@@ -707,6 +815,9 @@ PROCEDURE Clc ; BEGIN B (0F8H) END Clc ;
 PROCEDURE IncCl ; BEGIN B (0FEH) ; B (0C1H) END IncCl ;
 PROCEDURE DecDi ; BEGIN B (4FH) END DecDi ;
 PROCEDURE SubAhCh ; BEGIN B (28H) ; B (0ECH) END SubAhCh ;  (* AH:=AH-CH *)
+PROCEDURE SubAlDl ; BEGIN B (2AH) ; B (0C2H) END SubAlDl ;  (* AL:=AL-DL *)
+PROCEDURE IncCh ; BEGIN B (0FEH) ; B (0C5H) END IncCh ;      (* INC CH *)
+PROCEDURE IncDl ; BEGIN B (0FEH) ; B (0C2H) END IncDl ;      (* INC DL *)
 PROCEDURE MovClImm (v : CARDINAL) ;
 BEGIN B (0B1H) ; B (v MOD 256) END MovClImm ;
 PROCEDURE CmpClImm (v : CARDINAL) ;
@@ -734,14 +845,14 @@ PROCEDURE TestDhImm (v : CARDINAL) ;
 BEGIN B (0F6H) ; B (0C6H) ; B (v MOD 256) END TestDhImm ;
 PROCEDURE StDataImm (delta, v : CARDINAL) ;
 BEGIN B (0C7H) ; B (06H) ; Dd (delta) ; W (v) END StDataImm ;
+PROCEDURE StDataByte (delta, v : CARDINAL) ;
+BEGIN B (0C6H) ; B (06H) ; Dd (delta) ; B (v MOD 256) END StDataByte ;
 PROCEDURE StDataCl (delta : CARDINAL) ;
 BEGIN B (88H) ; B (0EH) ; Dd (delta) END StDataCl ;
 PROCEDURE StDataDi (delta : CARDINAL) ;
 BEGIN B (89H) ; B (3EH) ; Dd (delta) END StDataDi ;
 PROCEDURE LdAlData (delta : CARDINAL) ;
 BEGIN B (0A0H) ; Dd (delta) END LdAlData ;
-PROCEDURE LdClData (delta : CARDINAL) ;
-BEGIN B (8AH) ; B (0EH) ; Dd (delta) END LdClData ;
 PROCEDURE XorDiData (delta : CARDINAL) ;
 BEGIN B (33H) ; B (3EH) ; Dd (delta) END XorDiData ;          (* XOR DI,[Vx] *)
 PROCEDURE XorDataDh (delta : CARDINAL) ;
@@ -1650,11 +1761,21 @@ BEGIN
    PushBx ; PushDx ; PushSi ; PushDi ;
    MovSiBp6 ;                       (* SI := source word *)
    LdAxSi ;                         (* AX := the integer *)
+   Call ("rf_core") ;
+   M ("rf_store") ;
+   MovDiBp4 ;                       (* DI := the destination *)
+   StDiAx ;                         (* bytes 0..1 *)
+   StDiOffBx (2) ;                  (* bytes 2..3 *)
+   StDiOffDx (4) ;                  (* bytes 4..5, sign in DH bit 7 *)
+   PopDi ; PopSi ; PopDx ; PopBx ;
+   MovSpBp ; PopBp ; RetR ;
+   (* ---- the callable integer -> real core: AX in, AX/BX/DX out ---- *)
+   M ("rf_core") ;
    CmpAx0 ;
    Jne8 ("rf_nz") ;
    XorBxBx ;
    XorDxDx ;
-   Jmp8 ("rf_store") ;
+   Jmp8 ("rf_core_ret") ;
    M ("rf_nz") ;
    MovBhAh ;                        (* BH := the integer's sign byte *)
    MovDxAx ;
@@ -1680,13 +1801,8 @@ BEGIN
    AndDhImm (7FH) ;                 (* positive: bit 7 of DH is not a sign *)
    M ("rf_pos2") ;
    XorBxBx ;                        (* only DX's 16 bits carry the value now *)
-   M ("rf_store") ;
-   MovDiBp4 ;                       (* DI := the destination *)
-   StDiAx ;                         (* bytes 0..1 *)
-   StDiOffBx (2) ;                  (* bytes 2..3 *)
-   StDiOffDx (4) ;                  (* bytes 4..5, sign in DH bit 7 *)
-   PopDi ; PopSi ; PopDx ; PopBx ;
-   MovSpBp ; PopBp ; RetR
+   M ("rf_core_ret") ;
+   RetR
 END EmitRealFromInt ;
 
 PROCEDURE EmitRealAddSub ;
@@ -2112,6 +2228,515 @@ BEGIN
    Jmp8 ("ri_store")
 END EmitRealInt ;
 
+PROCEDURE EmitRealConv ;
+(* fmtreal / ascreal: the decimal<->binary conversions, TPSRC3 880-1250.
+
+   The cores are transcribed with their reference register conventions:
+   m10 multiplies AX/BX/DX by ten in place; rrange multiplies by 10**CL
+   through the fltdec table and the remult/rediv cores; rdec turns a packed
+   real into twelve decimal digits in D_CVOUT and returns the sign in CH and
+   the decimal exponent in CL; round and fdig* are the reference's helpers.
+   They all use CALL/RET internally, so a caller's flags survive where the
+   reference relies on that (the digit loop's CH flags are pushed explicitly
+   because rd_core uses CX for its second operand).
+
+   Two entries:
+     real_fmt  (28): [BP+4] real ptr, [BP+6] destination; CX = width in CL
+                     and decimals in CH.  Writes a length-prefixed string
+                     (dest[0] = length) padded on the LEFT to width, and
+                     returns the length in AX.  DEC >= 25 selects the
+                     reference's scientific mode and derives the number of
+                     fraction digits from the width.
+     real_val  (29): [BP+4] ASCIIZ source, [BP+6] destination real.  Returns
+                     AX = the offset of the first character not consumed, or
+                     FFFFh on a hard error (in which case the destination is
+                     untouched).  A trailing non-digit is NOT an error; the
+                     offset tells Val where to report it, as TPSRC's ascreal
+                     returns BX = end. *)
+BEGIN
+   (* ---------------------------------------------------------- real_fmt *)
+   M ("real_fmt") ;
+   PushBp ; MovBpSp ;
+   PushBx ; PushDx ; PushSi ; PushDi ;
+   MovDiBp4 ;                       (* DI := the real *)
+   MovDlCh ;                        (* DL := decimals *)
+   MovChImm (0) ;                   (* CX := width *)
+   MovDhImm (0) ;
+   PushCx ;                         (* keep the width across rdec *)
+   MovBxDataAddr (D_FMTBUF) ;
+   Call ("rc_fmt") ;
+   PopCx ;
+   MovAxBx ;                        (* AX := end of the formatted text *)
+   MovBxDataAddr (D_FMTBUF) ;
+   SubAxBx ;                        (* AX := its length *)
+   StDataAx (D_FMTLEN) ;
+   StDataCx (D_FMTW) ;
+   (* pad := max (width - length, 0) *)
+   MovAxData (D_FMTW) ;
+   MovDxData (D_FMTLEN) ;
+   SubAxDx ;
+   CmpAx0 ;
+   Jge8 ("rc_fpadok") ;
+   XorAxAx ;
+   M ("rc_fpadok") ;
+   StDataAx (D_FMTPAD) ;
+   MovDxData (D_FMTLEN) ;
+   AddAxDx ;                        (* AX := pad + length *)
+   CmpAxImm (0FFH) ;                (* a Pascal string's length is one byte *)
+   JccNear (76H, "rc_ftotok") ;
+   MovAxImm (0FFH) ;
+   M ("rc_ftotok") ;
+   StDataAx (D_FMTTOT) ;
+   (* dest[0] := length; then pad spaces, then the number *)
+   MovDxBp6 ; MovDiDx ;
+   StDiAl ;
+   IncDi ;
+   MovCxData (D_FMTPAD) ;
+   Jcxz8 ("rc_fpad_done") ;
+   M ("rc_fpad_loop") ;
+   MovAlD (20H) ; StDiAl ; IncDi ; Loop8 ("rc_fpad_loop") ;
+   M ("rc_fpad_done") ;
+   MovSiData (D_FMTBUF) ;
+   MovCxData (D_FMTLEN) ;
+   Jcxz8 ("rc_fcopy_done") ;
+   M ("rc_fcopy_loop") ;
+   LdAlSi ; StDiAl ; IncSi ; IncDi ; Loop8 ("rc_fcopy_loop") ;
+   M ("rc_fcopy_done") ;
+   MovAxData (D_FMTTOT) ;
+   PopDi ; PopSi ; PopDx ; PopBx ;
+   MovSpBp ; PopBp ; RetR ;
+
+   (* ---------------------------------------------------------- real_val *)
+   M ("real_val") ;
+   PushBp ; MovBpSp ;
+   PushBx ; PushDx ; PushSi ; PushDi ;
+   MovBxBp4 ;
+   MovDiBp6 ;
+   StDataBx (D_ASCSRC) ;
+   Call ("rc_asc") ;
+   JccNear (72H, "rc_averr") ;
+   MovAxBx ;                        (* AX := end pointer *)
+   MovDxData (D_ASCSRC) ;
+   SubAxDx ;                        (* AX := consumed length *)
+   JmpNear ("rc_avdone") ;
+   M ("rc_averr") ;
+   MovAxImm (0FFFFH) ;
+   M ("rc_avdone") ;
+   PopDi ; PopSi ; PopDx ; PopBx ;
+   MovSpBp ; PopBp ; RetR ;
+
+   (* ---------------------------------------------------------- m10 *)
+   (* AX/BX/DX := value * 10; CF = overflow; CX is preserved.  The reference
+      multiplies by 1.25 (add the /4 value) and then by 8 via the exponent. *)
+   M ("rc_m10") ;
+   CmpAl0 ;
+   JccNear (75H, "rc_m10nz") ;
+   RetR ;
+   M ("rc_m10nz") ;
+   OrDhImm (80H) ;
+   PushCx ; PushDx ; PushBx ; PushAx ;
+   ShrDx1 ; RcrBx1 ; RcrAh1 ;
+   ShrDx1 ; RcrBx1 ; RcrAh1 ;
+   PopCx ; AddAhCh ;
+   PopCx ; AdcBxCx ;
+   PopCx ; AdcDxCx ;
+   PopCx ;
+   JccNear (73H, "rc_m10nrm") ;
+   RcrDx1 ; RcrBx1 ; RcrAh1 ;
+   IncAl ;
+   JccNear (75H, "rc_m10nrm") ;
+   Stc ; RetR ;
+   M ("rc_m10nrm") ;
+   AndDhImm (7FH) ;
+   AddAlImm (3) ;
+   RetR ;
+
+   (* -------------------------------------------------------- rrange *)
+   (* AX/BX/DX := value * 10**CL, signed CL, via the fltdec table. *)
+   M ("rc_range") ;
+   PushDx ; PushBx ; PushAx ;
+   StDataCl (D_CVDECEXP) ;
+   CmpCl0 ;
+   JccNear (79H, "rc_rpos") ;
+   NegCl ;
+   M ("rc_rpos") ;
+   MovBlCl ;
+   AndBlImm (0FCH) ;
+   MovBhBl ;
+   ShrBl1 ;
+   AddBlBh ;
+   XorBhBh ;
+   LeaDiBxData (D_FLTDEC) ;
+   LdAxDi ; LdBxDiOff (2) ; LdDxDiOff (4) ;
+   AndClImm (3) ;
+   JccNear (74H, "rc_rdone") ;
+   M ("rc_rmul") ;
+   Call ("rc_m10") ;
+   DecCl ;
+   JccNear (75H, "rc_rmul") ;
+   M ("rc_rdone") ;
+   MovCxAx ; MovSiBx ; MovDiDx ;
+   PopAx ; PopBx ; PopDx ;
+   TestDataImm (D_CVDECEXP, 80H) ;
+   JccNear (75H, "rc_rdiv") ;
+   JmpNear ("rm_core") ;
+   M ("rc_rdiv") ;
+   JmpNear ("rv_core") ;
+
+   (* ------------------------------------------------------- rangem *)
+   (* the signed range check around rrange: |CL| <= 38 *)
+   M ("rc_rangem") ;
+   CmpClImm (0DAH) ; JccNear (7CH, "rc_rerr") ;
+   CmpClImm (26H) ; JccNear (7FH, "rc_rerr") ;
+   PushCx ; PushSi ; PushDi ;
+   Call ("rc_range") ;
+   PopDi ; PopSi ; PopCx ;
+   RetR ;
+   M ("rc_rerr") ;
+   Stc ; RetR ;
+
+   (* ---------------------------------------------------------- rdec *)
+   (* DI -> real.  D_CVOUT gets twelve digits; CH = sign, CL = decimal
+      exponent.  The estimate is 77/256 * (exponent - 128), TPSRC's
+      log10(2) approximation. *)
+   M ("rc_rdec") ;
+   LdAxDi ; LdBxDiOff (2) ; LdDxDiOff (4) ;
+   CmpAl0 ;
+   JccNear (75H, "rc_rdno0") ;
+   MovSiData (D_CVOUT) ;
+   M ("rc_rdfill") ;
+   StSiImm (3030H) ;
+   IncSi ; IncSi ;
+   CmpSiData (D_CVOUT + 12) ;
+   JccNear (75H, "rc_rdfill") ;
+   MovCxImm (0) ;
+   RetR ;
+   M ("rc_rdno0") ;
+   MovChDh ;
+   AndDhImm (7FH) ;
+   PushAx ; PushDx ;
+   SubAl (80H) ; Cbw ; MovDxImm (004DH) ; ImulDx ; AddAxImm (5) ;
+   MovClAh ;
+   PopDx ; PopAx ;
+   CmpClImm (0D9H) ;
+   JccNear (75H, "rc_rdnocomp") ;
+   IncCl ;
+   M ("rc_rdnocomp") ;
+   PushCx ;
+   NegCl ;
+   Call ("rc_range") ;
+   PopCx ;
+   CmpAl (81H) ;
+   JccNear (73H, "rc_rdnoadj") ;
+   Call ("rc_m10") ;
+   DecCl ;
+   M ("rc_rdnoadj") ;
+   PushCx ;
+   OrDhImm (80H) ;
+   MovClImm (84H) ;
+   SubClAl ;
+   MovAlD (0) ;
+   CmpCl0 ;
+   JccNear (74H, "rc_rdnosh") ;
+   M ("rc_rdshift") ;
+   ShrDx1 ; RcrBx1 ; RcrAh1 ;
+   DecCl ;
+   JccNear (75H, "rc_rdshift") ;
+   M ("rc_rdnosh") ;
+   MovSiData (D_CVOUT) ;
+   M ("rc_rdconv") ;
+   MovChDh ; MovClImm (4) ; ShrChCl ; AddChImm (30H) ;
+   StSiCh ;
+   AndDhImm (0FH) ;
+   PushDx ; PushBx ; PushAx ;
+   ShlAx1 ; RclBx1 ; RclDx1 ;
+   ShlAx1 ; RclBx1 ; RclDx1 ;
+   PopCx ; AddAxCx ;
+   PopCx ; AdcBxCx ;
+   PopCx ; AdcDxCx ;
+   ShlAx1 ; RclBx1 ; RclDx1 ;
+   IncSi ;
+   CmpSiData (D_CVOUT + 12) ;
+   JccNear (75H, "rc_rdconv") ;
+   PopCx ;
+   RetR ;
+
+   (* --------------------------------------------------------- round *)
+   (* round the digits at index AL: look at the next digit, and carry if it is
+      5 or more.  CL is the decimal exponent and is incremented on carry-out. *)
+   M ("rc_round") ;
+   XorAhAh ;
+   MovBxDataAddr (D_CVOUT) ;
+   AddBxAx ;
+   CmpBxByte (35H) ;
+   MovBxByte (0) ;
+   JccNear (72H, "rc_rounddone") ;
+   M ("rc_roundloop") ;
+   DecAl ;
+   JccNear (78H, "rc_roundexp") ;
+   DecBx ;
+   IncBxByte ;
+   CmpBxByte (3AH) ;
+   JccNear (72H, "rc_rounddone") ;
+   MovBxByte (0) ;
+   JmpNear ("rc_roundloop") ;
+   M ("rc_roundexp") ;
+   MovBxByte (31H) ;
+   MovBxOff1Byte (0) ;
+   IncCl ;
+   M ("rc_rounddone") ;
+   RetR ;
+
+   (* ------------------------------------------------------------ fdig *)
+   M ("rc_fdig") ;
+   LdAlSi ;
+   CmpAl0 ;
+   JccNear (74H, "rc_fdig0") ;
+   IncSi ;
+   JmpNear ("rc_fdigsto") ;
+   M ("rc_fdig0") ;
+   MovAlD (30H) ;
+   M ("rc_fdigsto") ;
+   StBxAl ;
+   IncBx ;
+   RetR ;
+
+   (* ---------------------------------------------------------- fcore *)
+   (* DI = real, BX = destination, CX = width, DX = decimals.  Writes raw
+      characters (no padding) and leaves BX one past the end. *)
+   M ("rc_fmt") ;
+   PushBx ;
+   CmpDxImm (19H) ;
+   JccNear (72H, "rc_fnlim2") ;
+   MovAxCx ;
+   CmpCh0 ;
+   JccNear (74H, "rc_flimok") ;
+   TestChImm (80H) ;
+   JccNear (74H, "rc_flimpos") ;
+   XorAxAx ;
+   JmpNear ("rc_flimok") ;
+   M ("rc_flimpos") ;
+   MovAxImm (0FFH) ;
+   M ("rc_flimok") ;
+   MovDl (7) ;
+   TestDiOffImm (5, 80H) ;
+   JccNear (74H, "rc_frpos") ;
+   IncDl ;
+   M ("rc_frpos") ;
+   SubAlDl ;
+   JccNear (73H, "rc_frnound") ;
+   MovAlD (0) ;
+   M ("rc_frnound") ;
+   CmpAl (9) ;
+   JccNear (72H, "rc_frnolim") ;
+   MovAlD (9) ;
+   M ("rc_frnolim") ;
+   IncAl ;
+   MovDlAl ;
+   MovDhAl ;
+   M ("rc_fnlim2") ;
+   PushDx ;
+   Call ("rc_rdec") ;
+   PopDx ;
+   MovAlDl ;
+   IncAl ;
+   CmpDh0 ;
+   JccNear (75H, "rc_frround") ;
+   AddAlCl ;
+   JccNear (79H, "rc_frlimprc") ;
+   StDataByte (D_CVOUT, 0) ;
+   JmpNear ("rc_frfmtit") ;
+   M ("rc_frlimprc") ;
+   CmpAl (0CH) ;
+   JccNear (72H, "rc_frround") ;
+   MovAlD (0BH) ;
+   M ("rc_frround") ;
+   Call ("rc_round") ;
+   M ("rc_frfmtit") ;
+   PopBx ;
+   MovSiData (D_CVOUT) ;
+   TestChImm (80H) ;
+   JccNear (74H, "rc_frpos2") ;
+   MovAlD (2DH) ;
+   Call ("rc_fdigsto") ;
+   M ("rc_frpos2") ;
+   MovChCl ;
+   CmpDh0 ;
+   JccNear (74H, "rc_frzer") ;
+   MovChImm (0) ;
+   M ("rc_frzer") ;
+   CmpCh0 ;
+   JccNear (79H, "rc_frint") ;
+   Call ("rc_fdig0") ;
+   JmpNear ("rc_frfrac0") ;
+   M ("rc_frint") ;
+   Call ("rc_fdig") ;
+   DecCh ;
+   JccNear (79H, "rc_frint") ;
+   M ("rc_frfrac0") ;
+   CmpDl0 ;
+   JccNear (74H, "rc_frexp") ;
+   MovAlD (2EH) ;
+   Call ("rc_fdigsto") ;
+   M ("rc_frfill0") ;
+   IncCh ;
+   JccNear (74H, "rc_frfrac") ;
+   Call ("rc_fdig0") ;
+   DecDl ;
+   JccNear (75H, "rc_frfill0") ;
+   M ("rc_frfrac") ;
+   DecDl ;
+   JccNear (78H, "rc_frexp") ;
+   Call ("rc_fdig") ;
+   JmpNear ("rc_frfrac") ;
+   M ("rc_frexp") ;
+   CmpDh0 ;
+   JccNear (75H, "rc_frputexp") ;
+   RetR ;
+   M ("rc_frputexp") ;
+   MovAlD (45H) ;
+   Call ("rc_fdigsto") ;
+   MovAlD (2BH) ;
+   CmpCl0 ;
+   JccNear (79H, "rc_frposexp") ;
+   NegCl ;
+   MovAlD (2DH) ;
+   M ("rc_frposexp") ;
+   Call ("rc_fdigsto") ;
+   MovAlD (2FH) ;
+   M ("rc_frexpsub") ;
+   IncAl ;
+   SubClImm (0AH) ;
+   JccNear (73H, "rc_frexpsub") ;
+   Call ("rc_fdigsto") ;
+   AddClImm (3AH) ;
+   MovAlCl ;
+   JmpNear ("rc_fdigsto") ;
+
+   (* ------------------------------------------------------------ asc *)
+   (* BX = ASCIIZ source, DI = destination real.  Returns BX = end, CF = 1 on
+      a hard error.  The digit add keeps the reference's stack dance: the
+      digit's real goes in a and the accumulated value in b (addition is
+      commutative), while the pointers and the CH flags are saved around the
+      call because rd_core uses CX/SI/DI. *)
+   M ("rc_asc") ;
+   LdClBx ;
+   CmpClImm (2DH) ;
+   JccNear (75H, "rc_asign") ;
+   IncBx ;
+   M ("rc_asign") ;
+   PushCx ;
+   Call ("rc_asc2") ;
+   PopCx ;
+   JccNear (72H, "rc_aouterr") ;
+   CmpClImm (2DH) ;
+   JccNear (75H, "rc_aok") ;
+   LdAlDi ;
+   CmpAl0 ;
+   JccNear (74H, "rc_aok") ;
+   XorDiOffImm (5, 80H) ;
+   M ("rc_aok") ;
+   Clc ;
+   RetR ;
+   M ("rc_aouterr") ;
+   Stc ;
+   RetR ;
+   M ("rc_asc2") ;
+   MovSiBx ;
+   XorAxAx ; XorBxBx ; XorDxDx ; XorCxCx ;
+   StDataByte (D_CVEXPCNT, 0) ;
+   M ("rc_aloop") ;
+   LdClSi ;
+   CmpClImm (61H) ; JccNear (72H, "rc_aup") ;
+   CmpClImm (7AH) ; Ja8 ("rc_aup") ;
+   SubClImm (20H) ;
+   M ("rc_aup") ;
+   Call ("rc_adigit2") ;
+   JccNear (72H, "rc_anodig") ;
+   Call ("rc_m10") ;
+   JccNear (72H, "rc_aerr") ;
+   PushDi ; PushSi ; PushCx ;
+   PushDx ; PushBx ; PushAx ;
+   MovAlCl ;
+   XorAhAh ;
+   Call ("rf_core") ;
+   MovCxAx ; MovSiBx ; MovDiDx ;
+   PopAx ; PopBx ; PopDx ;
+   StDataImm (D_RSIGN, 0) ;          (* readd, not resub: resign := 0 *)
+   Call ("rd_core") ;
+   PopCx ; PopSi ; PopDi ;
+   TestChImm (40H) ;
+   JccNear (74H, "rc_anext") ;
+   DecData (D_CVEXPCNT) ;
+   M ("rc_anext") ;
+   IncSi ;
+   JmpNear ("rc_aloop") ;
+   M ("rc_anodig") ;
+   CmpClImm (2EH) ;
+   JccNear (75H, "rc_aexp") ;
+   TestChImm (40H) ;
+   JccNear (75H, "rc_aerr") ;
+   OrChImm (40H) ;
+   JmpNear ("rc_anext") ;
+   M ("rc_aexp") ;
+   CmpClImm (45H) ;
+   LdClData (D_CVEXPCNT) ;
+   JccNear (75H, "rc_aexp3") ;
+   Call ("rc_rangem") ;
+   JccNear (72H, "rc_aerr") ;
+   IncSi ;
+   LdClSi ;
+   CmpClImm (2BH) ;
+   JccNear (74H, "rc_aposexp") ;
+   CmpClImm (2DH) ;
+   JccNear (75H, "rc_aexp2") ;
+   OrChImm (20H) ;
+   M ("rc_aposexp") ;
+   IncSi ;
+   M ("rc_aexp2") ;
+   Call ("rc_adigit") ;
+   JccNear (72H, "rc_aerr") ;
+   PushAx ;
+   MovAlCl ;
+   IncSi ;
+   Call ("rc_adigit") ;
+   JccNear (72H, "rc_aonedig") ;
+   MovAhAl ;
+   ShlAl1 ; ShlAl1 ; AddAlAh ; ShlAl1 ; AddAlCl ;
+   IncSi ;
+   M ("rc_aonedig") ;
+   MovClAl ;
+   PopAx ;
+   TestChImm (20H) ;
+   JccNear (74H, "rc_aexp3") ;
+   NegCl ;
+   M ("rc_aexp3") ;
+   Call ("rc_rangem") ;
+   JccNear (72H, "rc_aerr") ;
+   StDiAx ; StDiOffBx (2) ; StDiOffDx (4) ;
+   Clc ;
+   JmpNear ("rc_aret") ;
+   M ("rc_aerr") ;
+   Stc ;
+   M ("rc_aret") ;
+   MovBxSi ;
+   RetR ;
+
+   (* -------------------------------------------------------- adigit *)
+   M ("rc_adigit") ;
+   LdClSi ;
+   M ("rc_adigit2") ;
+   CmpClImm (30H) ;
+   JccNear (72H, "rc_adret") ;
+   CmpClImm (3AH) ;
+   Cmc ;
+   JccNear (72H, "rc_adret") ;
+   SubClImm (30H) ;
+   M ("rc_adret") ;
+   RetR
+END EmitRealConv ;
+
+
 PROCEDURE EmitData ;
 (* The runtime's data block.  The D_ constants name the offsets in it and are
    ASSERTED against what is emitted here, three ways: the starting offset of
@@ -2184,6 +2809,67 @@ BEGIN
       HALT
    END ;
    B (0) ; B (0) ;
+   IF dataAt + D_CVOUT # rpos THEN
+      HALT
+   END ;
+   (* twelve decimal digit slots; rdconv fills all of them *)
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   IF dataAt + D_CVDECEXP # rpos THEN
+      HALT
+   END ;
+   B (0) ;
+   IF dataAt + D_CVEXPCNT # rpos THEN
+      HALT
+   END ;
+   B (0) ;
+   IF dataAt + D_FLTDEC # rpos THEN
+      HALT
+   END ;
+   (* 1e0, 1e4, ... 1e36 as the reference's AX:BX:DX triples, low byte first *)
+   B (081H) ; B (000H) ; B (000H) ; B (000H) ; B (000H) ; B (000H) ;
+   B (08EH) ; B (000H) ; B (000H) ; B (000H) ; B (040H) ; B (01CH) ;
+   B (09BH) ; B (000H) ; B (000H) ; B (020H) ; B (0BCH) ; B (03EH) ;
+   B (0A8H) ; B (000H) ; B (010H) ; B (0A5H) ; B (0D4H) ; B (068H) ;
+   B (0B6H) ; B (004H) ; B (0BFH) ; B (0C9H) ; B (01BH) ; B (00EH) ;
+   B (0C3H) ; B (0ACH) ; B (0C5H) ; B (0EBH) ; B (078H) ; B (02DH) ;
+   B (0D0H) ; B (0CDH) ; B (0CEH) ; B (01BH) ; B (0C2H) ; B (053H) ;
+   B (0DEH) ; B (0F9H) ; B (078H) ; B (039H) ; B (03FH) ; B (001H) ;
+   B (0EBH) ; B (02BH) ; B (0A8H) ; B (0ADH) ; B (0C5H) ; B (01DH) ;
+   B (0F8H) ; B (0C9H) ; B (07BH) ; B (0CEH) ; B (097H) ; B (040H) ;
+   IF dataAt + D_FMTBUF # rpos THEN
+      HALT
+   END ;
+   (* 64 bytes of formatted output; a fixed-format 1e38 with 10 decimals is
+      about 50 characters, so this has room *)
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ; B (0) ;
+   IF dataAt + D_FMTLEN # rpos THEN
+      HALT
+   END ;
+   B (0) ; B (0) ;
+   IF dataAt + D_FMTW # rpos THEN
+      HALT
+   END ;
+   B (0) ; B (0) ;
+   IF dataAt + D_FMTPAD # rpos THEN
+      HALT
+   END ;
+   B (0) ; B (0) ;
+   IF dataAt + D_FMTTOT # rpos THEN
+      HALT
+   END ;
+   B (0) ; B (0) ;
+   IF dataAt + D_ASCSRC # rpos THEN
+      HALT
+   END ;
+   B (0) ; B (0) ;
    WHILE rpos < dataAt + D_END DO
       B (0)
    END ;
@@ -2253,7 +2939,7 @@ BEGIN
    EmitGetCh ; EmitUnGetCh ;
    EmitRdStr ; EmitStrStore ; EmitCmpStr ; EmitStrCat ;
    EmitRealFromInt ; EmitRealAddSub ; EmitRealMul ;
-   EmitRealCmp ; EmitRealInt ;
+   EmitRealCmp ; EmitRealInt ; EmitRealConv ;
    EmitData ;
    FixUp ;
    SetStr (entNm [0], "initmem") ;
@@ -2284,6 +2970,8 @@ BEGIN
    SetStr (entNm [25], "real_div") ;
    SetStr (entNm [26], "real_cmp") ;
    SetStr (entNm [27], "real_int") ;
+   SetStr (entNm [28], "real_fmt") ;
+   SetStr (entNm [29], "real_val") ;
    built := TRUE
 END RT_Build ;
 
@@ -2311,7 +2999,7 @@ BEGIN
    IF NOT built THEN
       RT_Build (0)
    END ;
-   IF i > 27 THEN
+   IF i > 29 THEN
       RETURN 0
    END ;
    RETURN rtBase + LblOff (entNm [i])

+ 5 - 3
shell/tests/RtProbe.mod

@@ -108,7 +108,7 @@ END PENT ;
 
 PROCEDURE Main ;
 VAR i, n, base : CARDINAL ;
-    names : ARRAY [0..27] OF ARRAY [0..15] OF CHAR ;
+    names : ARRAY [0..29] OF ARRAY [0..15] OF CHAR ;
 BEGIN
    base := GetBase () ;
    RT_Build (base) ;
@@ -121,7 +121,7 @@ BEGIN
    PCARD (RT_Size ()) ; PS (" bytes") ; NL ;
    PS ("code ends at ") ; PCARD (RT_CodeEnd ()) ; NL ;
    i := 0 ;
-   WHILE i <= 27 DO
+   WHILE i <= 29 DO
       names [i] := "" ;
       INC (i)
    END ;
@@ -140,8 +140,10 @@ BEGIN
    names [25] := "real_div" ;
    names [26] := "real_cmp" ;
    names [27] := "real_int" ;
+   names [28] := "real_fmt" ;
+   names [29] := "real_val" ;
    i := 0 ;
-   WHILE i <= 27 DO
+   WHILE i <= 29 DO
       PENT (i, names [i]) ;
       INC (i)
    END ;

+ 19 - 3
shell/tests/audit_helpers.py

@@ -134,7 +134,19 @@ NON_ONE_LINE = {
         "SubAhData": COMP, "StDataAl": COMP,
         "MovBxImm": PARAM, "MovCxImm": PARAM, "MovDxImm": PARAM,
         "MovDl": PARAM, "MovAlD": PARAM, "MovAh": PARAM,
-        "MovDhImm": PARAM,
+        "MovDhImm": PARAM, "MovChImm": PARAM, "OrChImm": PARAM,
+        "TestChImm": PARAM, "StSiImm": PARAM,
+        # the fmtreal/ascreal data-offset and parameterised stores.  Each is a
+        # fixed sequence with a parameter/address, so there is no single set of
+        # literal bytes to disassemble; rt_exec's exact-output cases pin them.
+        "MovBxDataAddr": COMP, "MovSiData": COMP, "StDataByte": COMP,
+        "MovBxByte": COMP, "MovBxOff1Byte": COMP, "TestDiOffImm": COMP,
+        "XorDiOffImm": COMP, "LdBxDiOff": COMP, "LdDxDiOff": COMP,
+        "LeaDiBxData": COMP, "MovAxData": COMP,
+        "AddAxImm": COMP, "AddChImm": COMP, "AddClImm": COMP,
+        "AndBlImm": COMP, "AndClImm": COMP, "CmpAxImm": COMP,
+        "CmpBxByte": COMP, "CmpDxImm": COMP, "CmpSiData": COMP,
+        "DecData": COMP,
         "SubAl": PARAM, "CmpAl": PARAM, "AddDl": PARAM, "J8": COMP,
         "Jcc": COMP, "CmpCxV": PARAM,
         "B": DATA, "C8": DATA,
@@ -417,12 +429,16 @@ PATTERNS = [
     (re.compile(r"^Lahf$"), "lahf", [], {0x9F}),
     (re.compile(r"^Sahf$"), "sahf", [], {0x9E}),
     (re.compile(r"^LdChDiOff$"), "mov", ["r:Ch", "m:Di"], {0x8A}),
-    (re.compile(r"^PushBp4$"), "push", ["m:Bp+4"], {0xFF}),
+    (re.compile(r"^PushBp(4|6)$"), "push", ["m:Bp+%(1)s"], {0xFF}),
+    (re.compile(r"^IncBxByte$"), "inc", ["m:Bx"], {0xFE}),
     (re.compile(r"^Adc(%s)(%s)$" % (_ALT16, _ALT16)),
      "adc", ["r:%(1)s", "r:%(2)s"], {0x11, 0x13}),
     (re.compile(r"^Sbb(%s)(%s)$" % (_ALT16, _ALT16)),
      "sbb", ["r:%(1)s", "r:%(2)s"], {0x18, 0x19, 0x1A, 0x1B}),
-    (re.compile(r"^ShlDlCl$"),  "shl", ["r:Dl", "r:Cl"],     {0xD2}),
+    (re.compile(r"^(Shl|Shr|Rcl|Rcr)(Al|Cl|Dl|Bl|Ah|Ch|Dh|Bh)Cl$"),
+     None, ["r:%(2)s", "r:Cl"], {0xD2}),
+    (re.compile(r"^Cbw$"), "cbw", [], {0x98}),
+    (re.compile(r"^Imul(%s)$" % _ALT), "imul", ["r:%(1)s"], {0xF7}),
     # --- CMP reg,0 as a flag test (the 8086 has no OR reg,reg FCML can
     #     decode here; CMP sets the same ZF/SF/CF for a non-negative reg) ---
     (re.compile(r"^CmpAl0$"), "cmp", ["r:Al", "i:0"], {0x3C}),

+ 2 - 0
shell/tests/check_runtime.py

@@ -139,6 +139,8 @@ GOLDEN = {
     "real_div": "55 8B EC 53 52 56 57",
     "real_cmp": "55 8B EC 53 52 56 57",
     "real_int": "55 8B EC 53 52 56 57",
+    "real_fmt": "55 8B EC 53 52 56 57",
+    "real_val": "55 8B EC 53 52 56 57",
     # wrchar: AL, not DL.  DOS INT 21h AH=02h takes the character in AL, and
     # DL is the *other* 8086 convention (BIOS teletype).  This read DL, so
     # every write of a character printed whatever the *last* character read

+ 79 - 29
shell/tests/exec/bootcom.s

@@ -37,8 +37,9 @@
 #
 #   * The program is loaded at 0000:0100, so segment 0 holds the IVT at
 #     0000:0000-00FF and the program from 0100 up.  The input descriptor at
-#     2000h sits past the end of any fixture and is simply part of the disk
-#     image the harness writes, so the addresses here are assembly constants.
+#     7000h sits above the largest image that may reach 6F00h and below the
+#     boot sector at 7C00h, and is simply part of the disk image the harness
+#     writes, so the addresses here are assembly constants.
 #
 #     The handler owns no scratch inside the loaded region.  It used to keep
 #     the AH=09h cursor in memory at 0702h -- image offset 602h, inside every
@@ -99,23 +100,64 @@ _start:
 	# run wrong inside an otherwise byte-perfect 512-byte sector, which no
 	# partial-read or sector-count bug can produce.
 	#
-	# 8000h is clear of the IVT (0-3FFh), the BDA (400-4FFh), SeaBIOS's stack
-	# at 700h and the option-ROM window at C000h.  REP MOVSW is executed code,
-	# so the copy is the LAST thing that touches 0100h-20FFh and no BIOS call
-	# follows it.  The copy is what the program then runs out of, unchanged.
-	movw	$3, %cx
+	# 1000:0000 (linear 10000h) is clear of the IVT (0-3FFh), the BDA
+	# (400-4FFh), SeaBIOS's stack at 700h and the option-ROM window at C000h.
+	# REP MOVSW is executed code, so the copy is the LAST thing that touches
+	# 0100h-7100h, and it stops below the boot sector at 7C00h.  The copy is
+	# what the program then runs out of, unchanged.
+	# The image is read one track at a time.  A single INT 13h call cannot
+	# cross a track reliably, and a per-sector loop has to keep CHS and the
+	# destination across a BIOS call that may clobber any register.  Five
+	# fixed calls are simpler: track 0 starts at sector 2 (sector 1 is this
+	# boot sector), every later track starts at sector 1, and the last read
+	# takes the one sector that is left of the 72.
+	.set	READS, 5
+	# Read the image one sector at a time.  The loop state lives in registers,
+	# and every register is pushed around INT 13h: the BIOS is allowed to
+	# clobber all of them, and POP does not touch the carry, so the error flag
+	# survives the restore.  One sector per call also cannot cross a track.
+	movw	$SECTORS, %si		# sectors still to read
+	movw	$SCRATCH_SEG, %ax
+	movw	%ax, %es
+	xorw	%bx, %bx		# destination offset in ES
+	xorw	%cx, %cx		# CH=cylinder 0, CL=sector 0
+	xorw	%dx, %dx		# DH=head 0, DL=drive A
+	movb	$2, %cl			# sector 2 -- the .COM, 1-based
+.Lread:
+	movw	$3, %bp
 .Lretry:
-	movw	$SCRATCH, %bx		# ES:BX = 0000:8000
-	movb	$0x02, %ah		# read sectors
-	movb	$16, %al		# 16 * 512 = 8192 bytes, far more than any fixture
-	movb	$0x00, %ch		# cylinder 0
-	movb	$0x02, %cl		# sector 2 -- the .COM, 1-based
-	movb	$0x00, %dh		# head 0
-	movb	$0x00, %dl		# drive A
+	movb	$0x02, %ah
+	movb	$1, %al
+	pushw	%es
+	pushw	%bp
+	pushw	%si
+	pushw	%bx
+	pushw	%cx
+	pushw	%dx
 	int	$0x13
-	jnc	.Lcopy
-	decw	%cx
+	popw	%dx
+	popw	%cx
+	popw	%bx
+	popw	%si
+	popw	%bp
+	popw	%es
+	jnc	.Lreadok
+	decw	%bp
 	jnz	.Lretry
+	jmp	.Lbootfail
+.Lreadok:
+	addw	$512, %bx
+	incb	%cl
+	cmpb	$19, %cl
+	jb	.Lreadnext
+	movb	$1, %cl
+	xorb	$1, %dh
+	jnz	.Lreadnext
+	incb	%ch
+.Lreadnext:
+	decw	%si
+	jnz	.Lread
+	jmp	.Lcopy
 .Lbootfail:
 	movb	$0x7f, %al
 	movw	$0x0501, %dx		# isa-debug-exit
@@ -123,11 +165,17 @@ _start:
 	cli
 	hlt
 .Lcopy:
-	movw	$0x0100, %di
-	movw	$SCRATCH, %si
-	movw	$4096, %cx		# 8192 bytes = 16 sectors
+	movw	$SCRATCH_SEG, %ax
+	movw	%ax, %ds
+	xorw	%si, %si		# source 1000:0000
+	xorw	%ax, %ax
+	movw	%ax, %es
+	movw	$0x0100, %di		# destination 0000:0100
+	movw	$(COPY_BYTES / 2), %cx	# bytes / 2
 	cld
 	rep	movsw
+	xorw	%ax, %ax
+	movw	%ax, %ds		# the .COM expects DS=0
 	.byte	0xEA, 0x00, 0x01, 0x00, 0x00	# jmp 0000:0100
 
 # ---------------------------------------------------------------- INT 21h
@@ -285,10 +333,10 @@ ser_put:
 	ret
 
 # --------------------------------------------------------------- layout
-# The input descriptor lives at 2000h, which the read + copy above covers
-# (0100h + 2000h = 2100h) and which is well past the end of any fixture (the
-# largest is 4493 bytes, so the image stops at 1285h).  So the descriptor is
-# simply part of the disk image the harness writes, not something it has to
+# The input descriptor lives at 7000h.  The image may reach 6F00h, the copy
+# ends at 7100h, and the boot sector at 7C00h is never touched; the read covers
+# enough sectors to bring the descriptor down with the image.  So it is simply
+# part of the disk image the harness writes, not something it has to
 # patch into this boot sector afterwards -- which means the addresses here are
 # assembly constants and the harness only has to know where they land in the
 # file.  See run_com_exec.py, FLAT_OFF.
@@ -296,12 +344,14 @@ ser_put:
 # SCRATCH is where the sector read parks the bytes before the copy moves them
 # to 0100h.  Nothing may ever be placed there: the region is not reserved by
 # this file, it is merely unused, and a future change that put a table at
-# 8000h would be overwritten by the read and would not notice.
-	.set	SCRATCH, 0x8000		# see the note above: not 0100h
-	.set	INLEN, 0x2000		# word: number of input bytes
-	.set	INCUR, 0x2002		# word: cursor, starts at INBUF
-	.set	INBUF, 0x2004		# the bytes themselves
-	.set	INMAX, 0x00fc		# 2100h - 2004h, the most that fits
+# 10000h would be overwritten by the read and would not notice.
+	.set	SECTORS, 72		# 36,864 bytes read; only COPY_BYTES is moved down
+	.set	COPY_BYTES, 0x7000	# up to the input, below the boot sector at 7C00h
+	.set	SCRATCH_SEG, 0x1000	# read buffer at 1000:0000, outside the 64K
+	.set	INLEN, 0x7000		# word: number of input bytes
+	.set	INCUR, 0x7002		# word: cursor, starts at INBUF
+	.set	INBUF, 0x7004		# the bytes themselves
+	.set	INMAX, 0x00fc		# 7100h - 7004h, the most that fits
 
 	.org	510
 	.byte	0x55, 0xAA

+ 102 - 52
shell/tests/exec/rtdrv.s

@@ -65,9 +65,9 @@
 # RT_SZ that run_com_tests.sh used to carry: the descriptor has to be where the
 # shim looks, and the only way to be sure is to have written both down and
 # checked.)
-	.set	INLEN, 0x2000		# word: how many input bytes follow
-	.set	INCUR, 0x2002		# word: index into INBUF, NOT an address
-	.set	INBUF, 0x2004		# the bytes themselves
+	.set	INLEN, 0x7000		# word: how many input bytes follow
+	.set	INCUR, 0x7002		# word: index into INBUF, NOT an address
+	.set	INBUF, 0x7004		# the bytes themselves
 
 # The case record, as rt_exec.py writes it.  These offsets are the contract; the
 # two places that read them (this file, and case_bytes() over there) are
@@ -92,58 +92,65 @@
 # silently run into the test scaffolding.  rt_exec.py asserts
 # RT_BASE + blob size <= HDR, so the bound is a checked one.
 	.set	RT_BASE, 0x0190
-	.set	HDR, 0x0A00
-	.set	DATA, 0x0A10
+	.set	HDR, 0x0F00
+	.set	FMTDEST, 0x1230	# 64-byte destination for real_fmt
+	.set	ASCSRC, 0x1270	# ASCIIZ sources for real_val
+	.set	DATA, 0x0F10
 	.set	DLEN, 32			# bytes of data area for initmem to clear
-	.set	STORE, 0x0A40		# where a read entry's result is stored
-	.set	WSTR, 0x0A50		# a string for the wrstr case: length + chars
-	.set	WSTR_EMPTY, 0x0A58	# the same, with a length of 0
-	.set	CASE, 0x0A60		# the case record
-	.set	D_DUMPLEN, 0x0AA0	# the driver's own three words
-	.set	D_DUMPADR, 0x0AA2
-	.set	D_CNT, 0x0AA4
-	.set	D_AX, 0x0AA6		# last call's AX, for the comparison cases
-	.set	RDSTR_DST, 0x0AB0	# destination for the rdstr cases
-	.set	SST_HELLO, 0x0AC0	# a short source string for strstore
-	.set	SST_LONG, 0x0AD0	# a source longer than a small max
-	.set	SST_EMPTY, 0x0AE0	# an empty source string
-	.set	SST_DST, 0x0AF0		# destination for the strstore cases
-	.set	SST_CAT, 0x0B00		# destination for the strcat cases, with a
+	.set	STORE, 0x0F40		# where a read entry's result is stored
+	.set	WSTR, 0x0F50		# a string for the wrstr case: length + chars
+	.set	WSTR_EMPTY, 0x0F58	# the same, with a length of 0
+	.set	CASE, 0x0F60		# the case record
+	.set	D_DUMPLEN, 0x0FA0	# the driver's own three words
+	.set	D_DUMPADR, 0x0FA2
+	.set	D_CNT, 0x0FA4
+	.set	D_AX, 0x0FA6		# last call's AX, for the comparison cases
+	.set	RDSTR_DST, 0x0FB0	# destination for the rdstr cases
+	.set	SST_HELLO, 0x0FC0	# a short source string for strstore
+	.set	SST_LONG, 0x0FD0	# a source longer than a small max
+	.set	SST_EMPTY, 0x0FE0	# an empty source string
+	.set	SST_DST, 0x0FF0		# destination for the strstore cases
+	.set	SST_CAT, 0x1000		# destination for the strcat cases, with a
 					# length to append to -- unlike SST_DST,
 					# which strstore overwrites
-	.set	SST_CAT0, 0x0B10	# ...and one that starts empty
-	.set	SST_WORLD, 0x0B20	# a source distinct from SST_HELLO
-	.set	R_BLK1, 0x0B30
-	.set	R_BLK2, 0x0B40
-	.set	R_BLK3, 0x0B50
-	.set	R_BLK4, 0x0B60
-	.set	R_BLK5, 0x0B70
-	.set	R_BLK6, 0x0B80
-	.set	R_BLK7, 0x0B90
-	.set	R_BLK8, 0x0BA0
-	.set	R_BLK9, 0x0BB0
-	.set	R_BLK10, 0x0BC0
-	.set	R_BLK11, 0x0BD0
-	.set	R_BLK12, 0x0BE0
-	.set	R_BLK13, 0x0BF0
-	.set	R_BLK14, 0x0C00
-	.set	R_BLK15, 0x0C10
-	.set	R_BLK16, 0x0C20
-	.set	R_BLK17, 0x0C30
-	.set	R_BLK18, 0x0C40
-	.set	R_BLK19, 0x0C50
-	.set	R_BLK20, 0x0C60
-	.set	R_BLK21, 0x0C70
-	.set	R_BLK22, 0x0C80
-	.set	R_BLK23, 0x0C90
-	.set	R_BLK24, 0x0CA0
-	.set	R_BLK25, 0x0CB0
-	.set	R_BLK26, 0x0CC0
-	.set	R_BLK27, 0x0CD0
-	.set	R_BLK28, 0x0CE0
-	.set	R_BLK29, 0x0CF0
-	.set	R_BLK30, 0x0D00
-	.set	R_BLK31, 0x0D10
+	.set	SST_CAT0, 0x1010	# ...and one that starts empty
+	.set	SST_WORLD, 0x1020	# a source distinct from SST_HELLO
+	.set	R_BLK1, 0x1030
+	.set	R_BLK2, 0x1040
+	.set	R_BLK3, 0x1050
+	.set	R_BLK4, 0x1060
+	.set	R_BLK5, 0x1070
+	.set	R_BLK6, 0x1080
+	.set	R_BLK7, 0x1090
+	.set	R_BLK8, 0x10A0
+	.set	R_BLK9, 0x10B0
+	.set	R_BLK10, 0x10C0
+	.set	R_BLK11, 0x10D0
+	.set	R_BLK12, 0x10E0
+	.set	R_BLK13, 0x10F0
+	.set	R_BLK14, 0x1100
+	.set	R_BLK15, 0x1110
+	.set	R_BLK16, 0x1120
+	.set	R_BLK17, 0x1130
+	.set	R_BLK18, 0x1140
+	.set	R_BLK19, 0x1150
+	.set	R_BLK20, 0x1160
+	.set	R_BLK21, 0x1170
+	.set	R_BLK22, 0x1180
+	.set	R_BLK23, 0x1190
+	.set	R_BLK24, 0x11A0
+	.set	R_BLK25, 0x11B0
+	.set	R_BLK26, 0x11C0
+	.set	R_BLK27, 0x11D0
+	.set	R_BLK28, 0x11E0
+	.set	R_BLK29, 0x11F0
+	.set	R_BLK30, 0x1200
+	.set	R_BLK31, 0x1210
+	.set	R_BLK32, 0x1300
+	.set	R_BLK33, 0x1310
+	.set	R_BLK34, 0x1320
+	.set	R_BLK35, 0x1330
+	.set	R_BLK36, 0x1340
 
 	.code16
 	.text
@@ -514,3 +521,46 @@ HDR:
 # 2^40: above reint's 0A8h early return, so it must come back unchanged.
 	.org	R_BLK31
 	.byte	0xA9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+# ASCIIZ sources for real_val.
+	.org	ASCSRC
+	.ascii	"3.5\x00"
+	.ascii	"-2.25\x00"
+	.ascii	"1E3\x00"
+	.ascii	"0.5\x00"
+	.ascii	"12345.75\x00"
+	.ascii	"3.5x\x00"
+	.ascii	"1E\x00"
+	.ascii	"1E40\x00"
+	.ascii	"\x00"
+	.ascii	".5\x00"
+	.ascii	"1.2.3\x00"
+	.ascii	"35\x00"
+	.ascii	"5E-1\x00"
+	.ascii	"5.\x00"
+	.ascii	"5.0\x00"
+	.ascii	"12345\x00"
+	.ascii	"1234575\x00"
+	.ascii	"1234.5\x00"
+	.ascii	"1000\x00"
+	.ascii	"123\x00"
+	.ascii	"1234\x00"
+	.ascii	"12340\x00"
+	.ascii	"12341\x00"
+	.ascii	"12341E0\x00"
+	.ascii	"12345E0\x00"
+
+# add-core probes
+	.org	R_BLK32
+	.byte	0x8E, 0x00, 0x00, 0x00, 0xD0, 0x40, 0x83, 0x00, 0x00, 0x00, 0x00, 0x20
+	.org	R_BLK33
+	.byte	0x8E, 0x00, 0x00, 0x00, 0xD0, 0x40, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00
+
+# multiplication-by-one probes
+	.org	R_BLK34
+	.byte	0x8E, 0x00, 0x00, 0x00, 0xD4, 0x40, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00
+	.org	R_BLK35
+	.byte	0x8E, 0x00, 0x00, 0x00, 0xE4, 0x40, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00
+
+	.org	R_BLK36
+	.byte	0x8E, 0x00, 0x00, 0x00, 0xD0, 0x40, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00

+ 45 - 0
shell/tests/nonvacuity.sh

@@ -1474,6 +1474,51 @@ fi
 cp "$SAVED" Runtime.mod
 "$GM2" -fiso -c Runtime.mod >/dev/null 2>&1
 
+# --- fmtreal reads the real through DI, not BX ---------------------------
+# LdBxDiOff is `8B 5D off' = MOV BX,[DI+off].  8B 5F is [BX+off], and the
+# formatter would then read its own card scratch as the real's mantissa.  The
+# exact-output real_fmt cases catch it.
+if mutate Runtime.mod 's|BEGIN B (8BH) ; B (5DH) ; B (off MOD 256) END LdBxDiOff|BEGIN B (8BH) ; B (5FH) ; B (off MOD 256) END LdBxDiOff|'; then
+    if "$GM2" -fiso -c Runtime.mod >/dev/null 2>&1; then
+        expect_red "real_fmt red when the real is loaded through BX, not DI" \
+            "real_fmt" python3 tests/rt_exec.py
+    else
+        echo "  FAIL: the runtime would not rebuild with the LdBxDiOff mutation"
+        fail=$((fail + 1))
+    fi
+fi
+cp "$SAVED" Runtime.mod
+"$GM2" -fiso -c Runtime.mod >/dev/null 2>&1
+
+# --- ascreal's digit add is an ADD, not a SUB ----------------------------
+# rd_core is the post-testexp core; its caller must set resign.  The parser
+# adds each digit, so resign must be 0.  8000h makes it a subtraction with the
+# sign XORed into the second operand: 12341 comes out 12339-ish, while the
+# offset tests (which do not look at the value) still pass.
+if python3 - <<'PYX'
+p = 'Runtime.mod'
+s = open(p).read()
+old = """   PopAx ; PopBx ; PopDx ;
+   StDataImm (D_RSIGN, 0) ;          (* readd, not resub: resign := 0 *)"""
+assert s.count(old) == 1, 'the parser resign found %d times' % s.count(old)
+open(p, 'w').write(s.replace(old, """   PopAx ; PopBx ; PopDx ;
+   StDataImm (D_RSIGN, 8000H) ;"""))
+PYX
+then
+    if "$GM2" -fiso -c Runtime.mod >/dev/null 2>&1; then
+        expect_red "real_val value red when the digit add uses resign=8000h" \
+            "real_val" python3 tests/rt_exec.py
+    else
+        echo "  FAIL: the runtime would not rebuild with the parser resign mutation"
+        fail=$((fail + 1))
+    fi
+else
+    echo "  BROKEN CASE: the parser resign mutation did not apply"
+    fail=$((fail + 1))
+fi
+cp "$SAVED" Runtime.mod
+"$GM2" -fiso -c Runtime.mod >/dev/null 2>&1
+
 # --- the compiler's arms --------------------------------------------------
 # The limit both entries read is MOV CX,imm16.  MOV AX,imm16 is one opcode away,
 # the same length, and the audit's MovCxi row is COMP - "no single sequence to

+ 112 - 28
shell/tests/rt_exec.py

@@ -63,23 +63,26 @@ SHELL = os.path.dirname(HERE)
 # two are written down and then CHECKED against each other (see build_image).
 # A restated constant that is never compared is a constant waiting to lie.
 RT_BASE = 0x0190
-HDR = 0x0A00
+HDR = 0x0F00
 DLEN = 32
-DATA = 0x0A10
-STORE = 0x0A40
-WSTR = 0x0A50
-WSTR_EMPTY = 0x0A58
-CASE = 0x0A60
+DATA = 0x0F10
+STORE = 0x0F40
+WSTR = 0x0F50
+WSTR_EMPTY = 0x0F58
+CASE = 0x0F60
 CASE_SZ = 64
-RDSTR_DST = 0x0AB0
-SST_HELLO = 0x0AC0
-SST_LONG = 0x0AD0
-SST_EMPTY = 0x0AE0
-SST_DST = 0x0AF0
-SST_CAT = 0x0B00
-SST_CAT0 = 0x0B10
-SST_WORLD = 0x0B20
-AXOUT = 0x0AA6          # the driver stores the last call's AX here
+RDSTR_DST = 0x0FB0
+SST_HELLO = 0x0FC0
+SST_LONG = 0x0FD0
+SST_EMPTY = 0x0FE0
+SST_DST = 0x0FF0
+SST_CAT = 0x1000
+SST_CAT0 = 0x1010
+SST_WORLD = 0x1020
+AXOUT = 0x0FA6          # the driver stores the last call's AX here
+FMTDEST = 0x1230        # a 64-byte string for the real_fmt cases
+ASCSRC = 0x1270          # the ASCIIZ strings for real_val
+REALDST = 0x0FA8
 
 # A .COM is loaded at CS:0100, and every address in the image is an image
 # offset.  The load bias is therefore the difference between the two, and
@@ -106,7 +109,7 @@ ENTS = ["initmem", "progend", "stackchk", "wrint", "wrchar", "wrbool",
         "wrreal", "wrln", "rdint", "rdchar", "rdbool", "rdln", "halt",
         "wrtinl", "rdbyte", "wrstr", "rdstr", "strstore", "cmpstr", "strcat",
         "wrintw", "real_from_int", "real_add", "real_sub", "real_mul",
-        "real_div", "real_cmp", "real_int"]
+        "real_div", "real_cmp", "real_int", "real_fmt", "real_val"]
 
 # A call slot's flags, as rtdrv.s reads them.
 F_STACK = 1     # the argument goes on the stack, popped by the caller
@@ -488,6 +491,23 @@ def build_cases():
             b[5] |= 0x80
         return bytes(b)
 
+    def mbf_float(x):
+        """The measured 6-byte MBF nearest to a fractional value."""
+        if x == 0:
+            return bytes(6)
+        neg = x < 0
+        a = abs(x)
+        k = math.floor(math.log2(a))
+        e = 129 + k
+        n = int(round((a / (2.0 ** k) - 1.0) * (1 << 39)))
+        if n >= (1 << 39):
+            n = 0
+            e += 1
+        b = bytearray([e]) + bytearray((n >> (8 * i)) & 0xFF for i in range(5))
+        if neg:
+            b[5] |= 0x80
+        return bytes(b)
+
     SRC = CASE + 5 + LOAD_BIAS
     for v in (0, 1, 2, 3, 5, 7, 42, 1000, 32767, -1, -2, -42, -32768):
         add("real_from_int(%d)" % v,
@@ -504,7 +524,7 @@ def build_cases():
               (6, 2), (10, 2), (15, 3), (1000, 2), (-6, 2), (6, -2),
               (-6, -2), (0, 5), (5, 2), (42, 6)]
     for bi, (a, b) in enumerate(BLOCKS):
-        blk = 0x0B30 + 16 * bi
+        blk = 0x1030 + 16 * bi
         add("real_add(%d,%d)" % (a, b),
             [s("real_add", blk + LOAD_BIAS)],
             dump=6, dumpbytes=mbf(a + b), dumpadr=blk,
@@ -537,11 +557,11 @@ def build_cases():
         if (a, b) in seen:
             continue
         seen.add((a, b))
-        blk = 0x0B30 + 16 * bi
+        blk = 0x1030 + 16 * bi
         want = (a > b) - (a < b)
         add("real_cmp(%d,%d)" % (a, b),
             [s("real_cmp", blk + LOAD_BIAS)],
-            dump=2, dumpbytes=struct.pack("<h", want), dumpadr=AXOUT,
+            dump=2, dumpbytes=struct.pack("<H", want & 0xFFFF), dumpadr=AXOUT,
             note="the reference's recmp, returned as AX = -1/0/+1")
 
     # Fractional blocks, compared through the exponent/mantissa path.
@@ -549,14 +569,14 @@ def build_cases():
             (-0.5, 0.5), (12345.75, 12345.5), (2.5, 0.0), (-2.5, 0.0),
             (0.99, 0.0), (1.9, 0.0)]
     for fi, (a, b) in enumerate(FRAC):
-        blk = 0x0C70 + 16 * fi
+        blk = 0x1170 + 16 * fi
         want = (a > b) - (a < b)
         add("real_cmp(%g,%g)" % (a, b),
             [s("real_cmp", blk + LOAD_BIAS)],
-            dump=2, dumpbytes=struct.pack("<h", want), dumpadr=AXOUT,
+            dump=2, dumpbytes=struct.pack("<H", want & 0xFFFF), dumpadr=AXOUT,
             note="fractional magnitudes: the mantissa decides")
     add("real_cmp(2^40,0)",
-        [s("real_cmp", 0x0D10 + LOAD_BIAS)],
+        [s("real_cmp", 0x1210 + LOAD_BIAS)],
         dump=2, dumpbytes=struct.pack("<h", 1), dumpadr=AXOUT,
         note="the exponent alone decides")
 
@@ -566,22 +586,86 @@ def build_cases():
     # (TPSRC's xint pushes the six-byte result back).
     for bi, (a, b) in enumerate(BLOCKS):
         if a in (0, 1, -3, 32767):
-            blk = 0x0B30 + 16 * bi
+            blk = 0x1030 + 16 * bi
             add("real_int(%d)" % a,
                 [s("real_int", blk + LOAD_BIAS)],
                 dump=6, dumpbytes=mbf(math.trunc(a)), dumpadr=blk,
                 note="the integer part as a real, the reference's reint")
     for fi, (a, b) in enumerate(FRAC):
-        blk = 0x0C70 + 16 * fi
+        blk = 0x1170 + 16 * fi
         add("real_int(%g)" % a,
             [s("real_int", blk + LOAD_BIAS)],
             dump=6, dumpbytes=mbf(math.trunc(a)), dumpadr=blk,
             note="the fraction is masked away; the sign and exponent stay")
     add("real_int(2^40)",
-        [s("real_int", 0x0D10 + LOAD_BIAS)],
-        dump=6, dumpbytes=bytes.fromhex("A90000000000"), dumpadr=0x0D10,
+        [s("real_int", 0x1210 + LOAD_BIAS)],
+        dump=6, dumpbytes=bytes.fromhex("A90000000000"), dumpadr=0x1210,
         note="exponent >= 0A8h is already integral and returns unchanged")
 
+    # --- fmtreal: real_fmt writes a length-prefixed, left-padded field -----
+    # CX = (decimals << 8) | width, [BP+4] = real, [BP+6] = destination.
+    def fmt(name, blk, width, dec, text):
+        add(name,
+            [s2cx("real_fmt", blk + LOAD_BIAS, FMTDEST + LOAD_BIAS,
+                  (dec << 8) | width)],
+            dump=1 + len(text), dumpbytes=bytes([len(text)]) + text,
+            dumpadr=FMTDEST,
+            note="the reference's fmtreal; dest[0] is the field length")
+    add("real_fmt(from int 1)",
+        [s2("real_from_int", STORE + LOAD_BIAS, SRC),
+         s2cx("real_fmt", STORE + LOAD_BIAS, FMTDEST + LOAD_BIAS, 0)],
+        stdin=struct.pack("<h", 1), dump=2, dumpbytes=bytes([1]) + b"1",
+        dumpadr=FMTDEST, note="a known-good 1.0 from real_from_int")
+    fmt("real_fmt(1:0:0)", 0x1030, 0, 0, b"1")
+    fmt("real_fmt(0:0:0)", 0x10B0, 0, 0, b"0")
+    fmt("real_fmt(3.7:0:2)", 0x1170, 0, 2, b"3.70")
+    fmt("real_fmt(12345.75:12:2)", 0x11C0, 12, 2, b"    12345.75")
+    fmt("real_fmt(0.5:6:3)", 0x11A0, 6, 3, b" 0.500")
+    fmt("real_fmt(-3.7:0:1)", 0x1190, 0, 1, b"-3.7")
+    fmt("real_fmt(0:5:2)", 0x10B0, 5, 2, b" 0.00")
+    fmt("real_fmt(2.5:0:0)", 0x11D0, 0, 0, b"3")
+    fmt("real_fmt(3.7:10:25)", 0x1170, 10, 25, b"3.7000E+00")
+
+    # --- ascreal: real_val parses an ASCIIZ string ------------------------
+    # A dump of AXOUT shows the returned offset, or FFFFh on a hard error.
+    ASC_STRINGS = [b"3.5\0", b"-2.25\0", b"1E3\0", b"0.5\0",
+                   b"12345.75\0", b"3.5x\0", b"1E\0", b"1E40\0",
+                   b"\0", b".5\0", b"1.2.3\0", b"35\0", b"5E-1\0", b"5.\0", b"5.0\0", b"12345\0", b"1234575\0", b"1234.5\0", b"1000\0", b"123\0", b"1234\0", b"12340\0", b"12341\0", b"12341E0\0", b"12345E0\0"]
+    WANT_OFF = [3, 5, 3, 3, 8, 3, 0xFFFF, 0xFFFF, 0, 2, 0xFFFF, 2, 4, 2, 3, 5, 7, 6, 4, 3, 4, 5, 5, 7, 7]
+    off = 0
+    for txt, want in zip(ASC_STRINGS, WANT_OFF):
+        add("real_val(%r) offset" % txt[:-1],
+            [s2("real_val", ASCSRC + off + LOAD_BIAS, STORE + LOAD_BIAS)],
+            dump=2, dumpbytes=struct.pack("<H", want & 0xFFFF), dumpadr=AXOUT,
+            note="AX = the first unparsed character, FFFFh on error")
+        off += len(txt)
+    # The parsed VALUE.  On a hard error nothing is stored, and STORE is
+    # poisoned with EEEE (its first two bytes are all the driver writes), so
+    # those cases also prove the destination was left alone.
+    VAL = [3.5, -2.25, 1000.0, 0.5, 12345.75, 3.5, None, None, 0.0, 0.5,
+           None, 35.0, 0.5, 5.0, 5.0, 12345.0, 1234575.0, 1234.5,
+           1000.0, 123.0, 1234.0, 12340.0, 12341.0, 12341.0, 12345.0]
+    off = 0
+    for txt, v in zip(ASC_STRINGS, VAL):
+        wantv = (b"\xEE\xEE" + bytes(4)) if v is None else mbf_float(v)
+        add("real_val(%r) value" % txt[:-1],
+            [s2("real_val", ASCSRC + off + LOAD_BIAS, STORE + LOAD_BIAS)],
+            dump=6, dumpbytes=wantv, dumpadr=STORE,
+            note="the packed MBF, or the untouched EEEE poison on error")
+        off += len(txt)
+
+    for bi, (a, b) in [(0, (12340, 5)), (1, (12340, 1))]:
+        blk = 0x1300 + 16 * bi
+        add("real_add(%d,%d)" % (a, b), [s("real_add", blk + LOAD_BIAS)],
+            dump=6, dumpbytes=mbf(a + b), dumpadr=blk,
+            note="a large value plus a small digit: the add core's alignment")
+
+    for bi, a in [(2, 12341), (3, 12345), (4, 12340)]:
+        blk = 0x1300 + 16 * bi
+        add("real_mul(%d,1)" % a, [s("real_mul", blk + LOAD_BIAS)],
+            dump=6, dumpbytes=mbf(a), dumpadr=blk,
+            note="multiplying by 1.0 must be exact")
+
     add("wrchar('A')", [s("wrchar", ord("A"))], out=b"A")
     add("wrchar('!')", [s("wrchar", ord("!"))], out=b"!")
 
@@ -605,7 +689,7 @@ def build_cases():
                        (b"0", 0), (b"  007", 7), (b"1234", 1234)]:
         add("rdint(%r) then rdln" % text,
             [s("rdint", V), n("rdln")], out=b"", stdin=text, dump=2,
-            dumpbytes=struct.pack("<h", want),
+            dumpbytes=struct.pack("<H", want & 0xFFFF),
             note="the delimiter must be left for rdln, which prints nothing")
 
     for c in "Q7":
@@ -627,7 +711,7 @@ def build_cases():
 
     for c, want in [("T", 1), ("y", 1), ("1", 1), ("F", 0), ("n", 0), ("0", 0)]:
         add("rdbool(%r)" % c, [s("rdbool", V)], out=b"", stdin=c.encode(),
-            dump=2, dumpbytes=struct.pack("<H", want))
+            dump=2, dumpbytes=struct.pack("<H", want & 0xFFFF))
 
     add("rdint at end of input leaves the variable alone",
         [s("rdint", V), n("rdln")], out=b"", stdin=b"", dump=2,

+ 9 - 9
shell/tests/run_com_exec.py

@@ -60,13 +60,13 @@ TIMEOUT = 15
 LOAD_SEG = 0x0000        # the .COM's load segment
 LOAD_OFF = 0x0100        # ...and offset; DOS puts a .COM at CS:0100
 FLAT_LOAD = LOAD_SEG * 16 + LOAD_OFF
-INLEN_OFF = 0x2000       # word: how many input bytes follow
-INBUF_OFF = 0x2004       # the input bytes
-INBUF_MAX = 0x00FC       # 2100h - 2004h
-SECTORS = 16             # what bootcom.s reads off the disk
+INLEN_OFF = 0x7000       # word: how many input bytes follow
+INBUF_OFF = 0x7004       # the input bytes
+INBUF_MAX = 0x00FC       # 7100h - 7004h
+SECTORS = 72             # what bootcom.s reads off the disk
 FLOPPY_SECTORS = 2880    # 1.44M, 18 sectors per track
 FLOPPY_BYTES = FLOPPY_SECTORS * 512
-COM_MAX = SECTORS * 512  # a .COM the boot sector could not load in full
+COM_MAX = INLEN_OFF - LOAD_OFF  # the image must end before the input
 
 # The descriptor has to be inside the region the boot sector reads, or the
 # boot sector reads whatever the BIOS left there.  This is a check on the two
@@ -77,10 +77,10 @@ if INBUF_OFF + INBUF_MAX > READ_END:
              "%d sectors bootcom.s reads (which end at %04X)"
              % (INBUF_OFF, INBUF_OFF + INBUF_MAX, SECTORS, READ_END))
 # ...and past the end of any .COM, or it would land inside the program.
-if INBUF_OFF < COM_MAX:
-    sys.exit("run_com_exec.py: the input descriptor at %04X is inside the %d "
-             "bytes the boot sector reads, so it could overlap a .COM"
-             % (INBUF_OFF, COM_MAX))
+if FLAT_LOAD + COM_MAX > INBUF_OFF:
+    sys.exit("run_com_exec.py: COM_MAX ends at %04X, past the input "
+             "descriptor at %04X"
+             % (FLAT_LOAD + COM_MAX, INBUF_OFF))
 
 # isa-debug-exit at port 0501h.  qemu exits with (value<<1)|1, so a program
 # that exits 0 gives rc=1 and a program that exits n gives (n<<1)|1.  Both

+ 1067 - 536
shell/tests/runtime.golden

@@ -41,7 +41,7 @@
 0036  58          pop ax
 0037  F7 D8       neg ax
 0039  B9 0A 00    mov cx,0ah
-003C  BB E4 08    mov bx,8e4h
+003C  BB 7A 0D    mov bx,0d7ah
 003F  89 DE       mov si,bx
 0041  31 D2       xor dx,dx
 0043  F7 F1       div ax,cx
@@ -93,7 +93,7 @@
 00A2  58          pop ax
 00A3  F7 D8       neg ax
 00A5  B9 0A 00    mov cx,0ah
-00A8  BB E4 08    mov bx,8e4h
+00A8  BB 7A 0D    mov bx,0d7ah
 00AB  89 DE       mov si,bx
 00AD  31 D2       xor dx,dx
 00AF  F7 F1       div ax,cx
@@ -125,18 +125,18 @@
 00DE  83 7E 04 00 cmp word ptr [bp+4h],0h
 00E2  89 EC       mov sp,bp
 00E4  75 05       jne 0ebh
-00E6  BA E9 08    mov dx,8e9h
+00E6  BA 7F 0D    mov dx,0d7fh
 00E9  EB 03       jmp 0eeh
-00EB  BA E4 08    mov dx,8e4h
+00EB  BA 7A 0D    mov dx,0d7ah
 00EE  B4 09       mov ah,9h
 00F0  CD 21       int 21h
 00F2  5D          pop bp
 00F3  C3          ret
-00F4  BA F2 08    mov dx,8f2h
+00F4  BA 88 0D    mov dx,0d88h
 00F7  B4 09       mov ah,9h
 00F9  CD 21       int 21h
 00FB  C3          ret
-00FC  BA EF 08    mov dx,8efh
+00FC  BA 85 0D    mov dx,0d85h
 00FF  B4 09       mov ah,9h
 0101  CD 21       int 21h
 0103  C3          ret
@@ -303,12 +303,12 @@
 0217  EB EF       jmp 208h
 0219  58          pop ax
 021A  C3          ret
-021B  8B 1E F8 08 mov bx,word ptr [8f8h]
+021B  8B 1E 8E 0D mov bx,word ptr [0d8eh]
 021F  83 FB 00    cmp bx,0h
 0222  74 09       je 22dh
 0224  8A C3       mov al,bl
 0226  31 DB       xor bx,bx
-0228  89 1E F8 08 mov word ptr [8f8h],bx
+0228  89 1E 8E 0D mov word ptr [0d8eh],bx
 022C  C3          ret
 022D  B4 08       mov ah,8h
 022F  CD 21       int 21h
@@ -316,7 +316,7 @@
 0232  88 C2       mov dl,al
 0234  BB 01 00    mov bx,1h
 0237  8A DA       mov bl,dl
-0239  89 1E F8 08 mov word ptr [8f8h],bx
+0239  89 1E 8E 0D mov word ptr [0d8eh],bx
 023D  C3          ret
 023E  55          push bp
 023F  8B EC       mov bp,sp
@@ -490,530 +490,1061 @@
 0355  57          push di
 0356  8B 76 06    mov si,word ptr [bp+6h]
 0359  8B 04       mov ax,word ptr [si]
-035B  83 F8 00    cmp ax,0h
-035E  75 06       jne 366h
-0360  31 DB       xor bx,bx
-0362  31 D2       xor dx,dx
-0364  EB 2C       jmp 392h
-0366  88 E7       mov bh,ah
-0368  89 C2       mov dx,ax
-036A  83 FA 00    cmp dx,0h
-036D  79 02       jns 371h
-036F  F7 DA       neg dx
-0371  B8 90 00    mov ax,90h
-0374  80 FE 00    cmp dh,0h
-0377  75 04       jne 37dh
-0379  B0 88       mov al,88h
-037B  86 D6       xchg dh,dl
-037D  83 FA 00    cmp dx,0h
-0380  78 06       js 388h
-0382  FE C8       dec al
-0384  D1 E2       shl dx,1h
-0386  79 FA       jns 382h
-0388  80 FF 00    cmp bh,0h
-038B  78 03       js 390h
-038D  80 E6 7F    and dh,7fh
-0390  31 DB       xor bx,bx
-0392  8B 7E 04    mov di,word ptr [bp+4h]
-0395  89 05       mov word ptr [di],ax
-0397  89 5D 02    mov word ptr [di+2h],bx
-039A  89 55 04    mov word ptr [di+4h],dx
-039D  5F          pop di
-039E  5E          pop si
-039F  5A          pop dx
-03A0  5B          pop bx
-03A1  89 EC       mov sp,bp
-03A3  5D          pop bp
-03A4  C3          ret
-03A5  55          push bp
-03A6  8B EC       mov bp,sp
-03A8  53          push bx
-03A9  52          push dx
-03AA  56          push si
-03AB  57          push di
-03AC  FF 76 04    push word ptr [bp+4h]
-03AF  8B 76 04    mov si,word ptr [bp+4h]
-03B2  8B 04       mov ax,word ptr [si]
-03B4  8B 4C 02    mov cx,word ptr [si+2h]
-03B7  8B 54 04    mov dx,word ptr [si+4h]
-03BA  89 CB       mov bx,cx
-03BC  8B FE       mov di,si
-03BE  8B 4D 06    mov cx,word ptr [di+6h]
-03C1  8B 75 08    mov si,word ptr [di+8h]
-03C4  8B 7D 0A    mov di,word ptr [di+0ah]
-03C7  C7 06 FA 08 00 00 mov word ptr [8fah],0h
-03CD  E8 4D 00    call 41dh
-03D0  5F          pop di
-03D1  89 05       mov word ptr [di],ax
-03D3  89 5D 02    mov word ptr [di+2h],bx
-03D6  89 55 04    mov word ptr [di+4h],dx
-03D9  5F          pop di
-03DA  5E          pop si
-03DB  5A          pop dx
-03DC  5B          pop bx
-03DD  89 EC       mov sp,bp
-03DF  5D          pop bp
-03E0  C3          ret
-03E1  55          push bp
-03E2  8B EC       mov bp,sp
-03E4  53          push bx
-03E5  52          push dx
-03E6  56          push si
-03E7  57          push di
-03E8  FF 76 04    push word ptr [bp+4h]
-03EB  8B 76 04    mov si,word ptr [bp+4h]
-03EE  8B 04       mov ax,word ptr [si]
-03F0  8B 4C 02    mov cx,word ptr [si+2h]
-03F3  8B 54 04    mov dx,word ptr [si+4h]
-03F6  89 CB       mov bx,cx
-03F8  8B FE       mov di,si
-03FA  8B 4D 06    mov cx,word ptr [di+6h]
-03FD  8B 75 08    mov si,word ptr [di+8h]
-0400  8B 7D 0A    mov di,word ptr [di+0ah]
-0403  C7 06 FA 08 00 80 mov word ptr [8fah],8000h
-0409  E8 11 00    call 41dh
-040C  5F          pop di
-040D  89 05       mov word ptr [di],ax
-040F  89 5D 02    mov word ptr [di+2h],bx
-0412  89 55 04    mov word ptr [di+4h],dx
-0415  5F          pop di
-0416  5E          pop si
-0417  5A          pop dx
-0418  5B          pop bx
-0419  89 EC       mov sp,bp
-041B  5D          pop bp
-041C  C3          ret
-041D  80 F9 00    cmp cl,0h
-0420  74 0E       je 430h
-0422  33 3E FA 08 xor di,word ptr [8fah]
-0426  3C 00       cmp al,0h
-0428  75 07       jne 431h
-042A  89 C8       mov ax,cx
-042C  89 F3       mov bx,si
-042E  89 FA       mov dx,di
-0430  C3          ret
-0431  38 C8       cmp al,cl
-0433  76 05       jbe 43ah
-0435  91          xchg ax,cx
-0436  87 F3       xchg bx,si
-0438  87 FA       xchg dx,di
-043A  88 0E FE 08 mov byte ptr [8feh],cl
-043E  28 C1       sub cl,al
-0440  80 F9 28    cmp cl,28h
-0443  72 06       jb 44bh
-0445  8A 0E FE 08 mov cl,byte ptr [8feh]
-0449  EB DF       jmp 42ah
-044B  89 3E FA 08 mov word ptr [8fah],di
-044F  80 26 FB 08 80 and byte ptr [8fbh],80h
-0454  89 3E FC 08 mov word ptr [8fch],di
-0458  30 36 FD 08 xor byte ptr [8fdh],dh
-045C  81 CF 00 80 or di,8000h
-0460  80 CE 80    or dh,80h
-0463  80 F9 10    cmp cl,10h
-0466  72 0B       jb 473h
-0468  88 FC       mov ah,bh
-046A  89 D3       mov bx,dx
-046C  31 D2       xor dx,dx
-046E  80 E9 10    sub cl,10h
-0471  EB F0       jmp 463h
-0473  80 F9 08    cmp cl,8h
-0476  72 0D       jb 485h
-0478  88 DC       mov ah,bl
-047A  88 FB       mov bl,bh
-047C  88 D7       mov bh,dl
-047E  88 F2       mov dl,dh
-0480  30 F6       xor dh,dh
-0482  80 E9 08    sub cl,8h
-0485  80 F9 00    cmp cl,0h
-0488  74 0A       je 494h
-048A  D1 EA       shr dx,1h
-048C  D1 DB       rcr bx,1h
-048E  D0 DC       rcr ah,1h
-0490  FE C9       dec cl
-0492  75 F6       jne 48ah
-0494  A0 FE 08    mov al,byte ptr [8feh]
-0497  F6 06 FD 08 80 test byte ptr [8fdh],80h
-049C  75 14       jne 4b2h
-049E  00 EC       add ah,ch
-04A0  11 F3       adc bx,si
-04A2  11 FA       adc dx,di
-04A4  73 5F       jnb 505h
-04A6  D1 DA       rcr dx,1h
-04A8  D1 DB       rcr bx,1h
-04AA  D0 DC       rcr ah,1h
-04AC  FE C0       inc al
-04AE  75 55       jne 505h
-04B0  F9          stc
-04B1  C3          ret
-04B2  86 EC       xchg ah,ch
-04B4  87 F3       xchg bx,si
-04B6  87 FA       xchg dx,di
-04B8  28 EC       sub ah,ch
-04BA  19 F3       sbb bx,si
-04BC  19 FA       sbb dx,di
-04BE  73 14       jnb 4d4h
-04C0  80 36 FB 08 80 xor byte ptr [8fbh],80h
-04C5  F6 D4       not ah
-04C7  F7 D3       not bx
-04C9  F7 D2       not dx
-04CB  80 C4 01    add ah,1h
-04CE  83 D3 00    adc bx,0h
-04D1  83 D2 00    adc dx,0h
-04D4  B1 05       mov cl,5h
-04D6  80 FE 00    cmp dh,0h
-04D9  75 14       jne 4efh
-04DB  88 D6       mov dh,dl
-04DD  88 FA       mov dl,bh
-04DF  88 DF       mov bh,bl
-04E1  88 E3       mov bl,ah
-04E3  30 E4       xor ah,ah
-04E5  2C 08       sub al,8h
-04E7  72 15       jb 4feh
-04E9  FE C9       dec cl
-04EB  75 E9       jne 4d6h
-04ED  EB 0F       jmp 4feh
-04EF  F6 C6 80    test dh,80h
-04F2  75 11       jne 505h
-04F4  D0 E4       shl ah,1h
-04F6  D1 D3       rcl bx,1h
-04F8  D1 D2       rcl dx,1h
-04FA  FE C8       dec al
-04FC  75 F1       jne 4efh
-04FE  31 C0       xor ax,ax
-0500  31 DB       xor bx,bx
-0502  31 D2       xor dx,dx
-0504  C3          ret
-0505  80 E6 7F    and dh,7fh
-0508  32 36 FB 08 xor dh,byte ptr [8fbh]
-050C  C3          ret
-050D  55          push bp
-050E  8B EC       mov bp,sp
-0510  53          push bx
-0511  52          push dx
-0512  56          push si
-0513  57          push di
-0514  FF 76 04    push word ptr [bp+4h]
-0517  8B 76 04    mov si,word ptr [bp+4h]
-051A  8B 04       mov ax,word ptr [si]
-051C  8B 4C 02    mov cx,word ptr [si+2h]
-051F  8B 54 04    mov dx,word ptr [si+4h]
-0522  89 CB       mov bx,cx
-0524  8B FE       mov di,si
-0526  8B 4D 06    mov cx,word ptr [di+6h]
-0529  8B 75 08    mov si,word ptr [di+8h]
-052C  8B 7D 0A    mov di,word ptr [di+0ah]
-052F  E8 11 00    call 543h
-0532  5F          pop di
-0533  89 05       mov word ptr [di],ax
-0535  89 5D 02    mov word ptr [di+2h],bx
-0538  89 55 04    mov word ptr [di+4h],dx
-053B  5F          pop di
-053C  5E          pop si
-053D  5A          pop dx
-053E  5B          pop bx
-053F  89 EC       mov sp,bp
-0541  5D          pop bp
-0542  C3          ret
-0543  80 F9 00    cmp cl,0h
-0546  75 03       jne 54bh
-0548  E9 A4 00    jmp 5efh
-054B  3C 00       cmp al,0h
-054D  75 03       jne 552h
-054F  E9 A3 00    jmp 5f5h
-0552  00 C8       add al,cl
-0554  72 07       jb 55dh
-0556  04 80       add al,80h
-0558  72 0D       jb 567h
-055A  E9 92 00    jmp 5efh
-055D  04 80       add al,80h
-055F  73 06       jnb 567h
-0561  B0 01       mov al,1h
-0563  B4 4C       mov ah,4ch
-0565  CD 21       int 21h
-0567  89 0E 05 09 mov word ptr [905h],cx
-056B  8B CA       mov cx,dx
-056D  31 F9       xor cx,di
-056F  F6 D5       not ch
-0571  80 E5 80    and ch,80h
-0574  88 2E FB 08 mov byte ptr [8fbh],ch
-0578  80 CE 80    or dh,80h
-057B  81 CF 00 80 or di,8000h
-057F  89 36 07 09 mov word ptr [907h],si
-0583  89 3E 09 09 mov word ptr [909h],di
-0587  A3 FF 08    mov word ptr [8ffh],ax
-058A  89 1E 01 09 mov word ptr [901h],bx
-058E  89 16 03 09 mov word ptr [903h],dx
-0592  30 E4       xor ah,ah
-0594  31 DB       xor bx,bx
-0596  31 D2       xor dx,dx
-0598  BF 05 09    mov di,905h
-059B  B1 05       mov cl,5h
-059D  47          inc di
-059E  8A 2D       mov ch,byte ptr [di]
-05A0  80 FD 00    cmp ch,0h
-05A3  75 0C       jne 5b1h
-05A5  88 DC       mov ah,bl
-05A7  88 FB       mov bl,bh
-05A9  88 D7       mov bh,dl
-05AB  88 F2       mov dl,dh
-05AD  30 F6       xor dh,dh
-05AF  EB 1C       jmp 5cdh
-05B1  BE 08 00    mov si,8h
-05B4  D0 DD       rcr ch,1h
-05B6  73 0C       jnb 5c4h
-05B8  02 26 00 09 add ah,byte ptr [900h]
-05BC  13 1E 01 09 adc bx,word ptr [901h]
-05C0  13 16 03 09 adc dx,word ptr [903h]
-05C4  D1 DA       rcr dx,1h
-05C6  D1 DB       rcr bx,1h
-05C8  D0 DC       rcr ah,1h
-05CA  4E          dec si
-05CB  75 E7       jne 5b4h
-05CD  FE C9       dec cl
-05CF  75 CC       jne 59dh
-05D1  91          xchg ax,cx
-05D2  9F          lahf
-05D3  F6 C6 80    test dh,80h
-05D6  75 0E       jne 5e6h
-05D8  9E          sahf
-05D9  D0 D5       rcl ch,1h
-05DB  D1 D3       rcl bx,1h
-05DD  D1 D2       rcl dx,1h
-05DF  80 F9 00    cmp cl,0h
-05E2  74 02       je 5e6h
-05E4  FE C9       dec cl
-05E6  91          xchg ax,cx
-05E7  32 36 FB 08 xor dh,byte ptr [8fbh]
-05EB  3C 00       cmp al,0h
-05ED  75 06       jne 5f5h
-05EF  31 C0       xor ax,ax
-05F1  31 DB       xor bx,bx
-05F3  31 D2       xor dx,dx
-05F5  C3          ret
-05F6  55          push bp
-05F7  8B EC       mov bp,sp
-05F9  53          push bx
-05FA  52          push dx
-05FB  56          push si
-05FC  57          push di
-05FD  FF 76 04    push word ptr [bp+4h]
-0600  8B 76 04    mov si,word ptr [bp+4h]
-0603  8B 04       mov ax,word ptr [si]
-0605  8B 4C 02    mov cx,word ptr [si+2h]
-0608  8B 54 04    mov dx,word ptr [si+4h]
-060B  89 CB       mov bx,cx
-060D  8B FE       mov di,si
-060F  8B 4D 06    mov cx,word ptr [di+6h]
-0612  8B 75 08    mov si,word ptr [di+8h]
-0615  8B 7D 0A    mov di,word ptr [di+0ah]
-0618  E8 11 00    call 62ch
-061B  5F          pop di
-061C  89 05       mov word ptr [di],ax
-061E  89 5D 02    mov word ptr [di+2h],bx
-0621  89 55 04    mov word ptr [di+4h],dx
-0624  5F          pop di
-0625  5E          pop si
-0626  5A          pop dx
-0627  5B          pop bx
-0628  89 EC       mov sp,bp
-062A  5D          pop bp
-062B  C3          ret
-062C  3C 00       cmp al,0h
-062E  75 03       jne 633h
-0630  E9 C2 FF    jmp 5f5h
-0633  28 C8       sub al,cl
-0635  F5          cmc
-0636  72 07       jb 63fh
-0638  04 80       add al,80h
-063A  72 0D       jb 649h
-063C  E9 B0 FF    jmp 5efh
-063F  04 80       add al,80h
-0641  73 06       jnb 649h
-0643  B0 01       mov al,1h
-0645  B4 4C       mov ah,4ch
-0647  CD 21       int 21h
-0649  89 0E 05 09 mov word ptr [905h],cx
-064D  8B CA       mov cx,dx
-064F  31 F9       xor cx,di
-0651  F6 D5       not ch
-0653  80 E5 80    and ch,80h
-0656  88 2E FB 08 mov byte ptr [8fbh],ch
-065A  80 CE 80    or dh,80h
-065D  81 CF 00 80 or di,8000h
-0661  89 36 07 09 mov word ptr [907h],si
-0665  89 3E 09 09 mov word ptr [909h],di
-0669  A2 FF 08    mov byte ptr [8ffh],al
-066C  BF 04 09    mov di,904h
-066F  B1 05       mov cl,5h
-0671  BE 08 00    mov si,8h
-0674  3B 16 09 09 cmp dx,word ptr [909h]
-0678  75 0A       jne 684h
-067A  3B 1E 07 09 cmp bx,word ptr [907h]
-067E  75 04       jne 684h
-0680  3A 26 06 09 cmp ah,byte ptr [906h]
-0684  72 0C       jb 692h
-0686  2A 26 06 09 sub ah,byte ptr [906h]
-068A  1B 1E 07 09 sbb bx,word ptr [907h]
-068E  1B 16 09 09 sbb dx,word ptr [909h]
-0692  F5          cmc
-0693  D0 D5       rcl ch,1h
-0695  4E          dec si
-0696  75 0A       jne 6a2h
-0698  88 2D       mov byte ptr [di],ch
-069A  FE C9       dec cl
-069C  74 1B       je 6b9h
-069E  4F          dec di
-069F  BE 08 00    mov si,8h
-06A2  D0 E4       shl ah,1h
-06A4  D1 D3       rcl bx,1h
-06A6  D1 D2       rcl dx,1h
-06A8  73 CA       jnb 674h
-06AA  2A 26 06 09 sub ah,byte ptr [906h]
-06AE  1B 1E 07 09 sbb bx,word ptr [907h]
-06B2  1B 16 09 09 sbb dx,word ptr [909h]
-06B6  F8          clc
-06B7  EB D9       jmp 692h
-06B9  D0 E4       shl ah,1h
-06BB  D1 D3       rcl bx,1h
-06BD  D1 D2       rcl dx,1h
-06BF  72 11       jb 6d2h
-06C1  3B 16 09 09 cmp dx,word ptr [909h]
-06C5  75 0A       jne 6d1h
-06C7  3B 1E 07 09 cmp bx,word ptr [907h]
-06CB  75 04       jne 6d1h
-06CD  3A 26 06 09 cmp ah,byte ptr [906h]
-06D1  F5          cmc
-06D2  8B 0E FF 08 mov cx,word ptr [8ffh]
-06D6  8B 1E 01 09 mov bx,word ptr [901h]
-06DA  8B 16 03 09 mov dx,word ptr [903h]
-06DE  9F          lahf
-06DF  F6 C6 80    test dh,80h
-06E2  75 09       jne 6edh
-06E4  9E          sahf
-06E5  D0 D5       rcl ch,1h
-06E7  D1 D3       rcl bx,1h
-06E9  D1 D2       rcl dx,1h
-06EB  EB 0A       jmp 6f7h
-06ED  FE C1       inc cl
-06EF  75 06       jne 6f7h
-06F1  B0 01       mov al,1h
-06F3  B4 4C       mov ah,4ch
-06F5  CD 21       int 21h
-06F7  E9 EC FE    jmp 5e6h
-06FA  55          push bp
-06FB  8B EC       mov bp,sp
-06FD  53          push bx
-06FE  52          push dx
-06FF  56          push si
-0700  57          push di
-0701  8B 76 04    mov si,word ptr [bp+4h]
-0704  8B 04       mov ax,word ptr [si]
-0706  8B 4C 02    mov cx,word ptr [si+2h]
-0709  8B 54 04    mov dx,word ptr [si+4h]
-070C  89 CB       mov bx,cx
-070E  8B FE       mov di,si
-0710  8B 4D 06    mov cx,word ptr [di+6h]
-0713  8B 75 08    mov si,word ptr [di+8h]
-0716  8B 7D 0A    mov di,word ptr [di+0ah]
-0719  52          push dx
-071A  31 FA       xor dx,di
-071C  5A          pop dx
-071D  79 06       jns 725h
-071F  52          push dx
-0720  D1 D2       rcl dx,1h
-0722  5A          pop dx
-0723  EB 10       jmp 735h
-0725  F6 C6 80    test dh,80h
-0728  74 08       je 732h
-072A  E8 20 00    call 74dh
-072D  74 06       je 735h
-072F  F5          cmc
-0730  EB 03       jmp 735h
-0732  E8 18 00    call 74dh
-0735  B0 00       mov al,0h
-0737  B4 00       mov ah,0h
-0739  72 06       jb 741h
-073B  74 08       je 745h
-073D  B0 01       mov al,1h
-073F  EB 04       jmp 745h
-0741  B0 FF       mov al,0ffh
-0743  B4 FF       mov ah,0ffh
-0745  5F          pop di
-0746  5E          pop si
-0747  5A          pop dx
-0748  5B          pop bx
-0749  89 EC       mov sp,bp
-074B  5D          pop bp
-074C  C3          ret
-074D  38 C8       cmp al,cl
-074F  75 0E       jne 75fh
-0751  3C 00       cmp al,0h
-0753  74 0A       je 75fh
-0755  39 FA       cmp dx,di
-0757  75 06       jne 75fh
-0759  39 F3       cmp bx,si
-075B  75 02       jne 75fh
-075D  38 EC       cmp ah,ch
-075F  C3          ret
-0760  55          push bp
-0761  8B EC       mov bp,sp
-0763  53          push bx
-0764  52          push dx
-0765  56          push si
-0766  57          push di
-0767  FF 76 04    push word ptr [bp+4h]
-076A  8B 76 04    mov si,word ptr [bp+4h]
-076D  8B 04       mov ax,word ptr [si]
-076F  8B 4C 02    mov cx,word ptr [si+2h]
-0772  8B 54 04    mov dx,word ptr [si+4h]
-0775  89 CB       mov bx,cx
-0777  3C A8       cmp al,0a8h
-0779  73 4C       jnb 7c7h
-077B  89 C1       mov cx,ax
-077D  89 DE       mov si,bx
-077F  89 D7       mov di,dx
-0781  30 E4       xor ah,ah
-0783  31 DB       xor bx,bx
-0785  31 D2       xor dx,dx
-0787  80 E9 80    sub cl,80h
-078A  76 4C       jbe 7d8h
-078C  80 F9 10    cmp cl,10h
-078F  72 0C       jb 79dh
-0791  88 FC       mov ah,bh
-0793  89 D3       mov bx,dx
-0795  BA FF FF    mov dx,0ffffh
-0798  80 E9 10    sub cl,10h
-079B  EB EF       jmp 78ch
-079D  80 F9 08    cmp cl,8h
-07A0  72 0F       jb 7b1h
-07A2  88 DC       mov ah,bl
-07A4  88 FB       mov bl,bh
-07A6  88 D7       mov bh,dl
-07A8  88 F2       mov dl,dh
-07AA  B6 FF       mov dh,0ffh
-07AC  80 E9 08    sub cl,8h
-07AF  EB EC       jmp 79dh
-07B1  80 F9 00    cmp cl,0h
-07B4  74 0B       je 7c1h
-07B6  F9          stc
-07B7  D1 DA       rcr dx,1h
-07B9  D1 DB       rcr bx,1h
-07BB  D0 DC       rcr ah,1h
-07BD  FE C9       dec cl
-07BF  75 F5       jne 7b6h
-07C1  21 FA       and dx,di
-07C3  21 F3       and bx,si
-07C5  20 EC       and ah,ch
-07C7  5F          pop di
-07C8  89 05       mov word ptr [di],ax
-07CA  89 5D 02    mov word ptr [di+2h],bx
-07CD  89 55 04    mov word ptr [di+4h],dx
-07D0  5F          pop di
-07D1  5E          pop si
-07D2  5A          pop dx
-07D3  5B          pop bx
-07D4  89 EC       mov sp,bp
-07D6  5D          pop bp
-07D7  C3          ret
-07D8  B0 00       mov al,0h
-07DA  EB EB       jmp 7c7h
+035B  E8 13 00    call 371h
+035E  8B 7E 04    mov di,word ptr [bp+4h]
+0361  89 05       mov word ptr [di],ax
+0363  89 5D 02    mov word ptr [di+2h],bx
+0366  89 55 04    mov word ptr [di+4h],dx
+0369  5F          pop di
+036A  5E          pop si
+036B  5A          pop dx
+036C  5B          pop bx
+036D  89 EC       mov sp,bp
+036F  5D          pop bp
+0370  C3          ret
+0371  83 F8 00    cmp ax,0h
+0374  75 06       jne 37ch
+0376  31 DB       xor bx,bx
+0378  31 D2       xor dx,dx
+037A  EB 2C       jmp 3a8h
+037C  88 E7       mov bh,ah
+037E  89 C2       mov dx,ax
+0380  83 FA 00    cmp dx,0h
+0383  79 02       jns 387h
+0385  F7 DA       neg dx
+0387  B8 90 00    mov ax,90h
+038A  80 FE 00    cmp dh,0h
+038D  75 04       jne 393h
+038F  B0 88       mov al,88h
+0391  86 D6       xchg dh,dl
+0393  83 FA 00    cmp dx,0h
+0396  78 06       js 39eh
+0398  FE C8       dec al
+039A  D1 E2       shl dx,1h
+039C  79 FA       jns 398h
+039E  80 FF 00    cmp bh,0h
+03A1  78 03       js 3a6h
+03A3  80 E6 7F    and dh,7fh
+03A6  31 DB       xor bx,bx
+03A8  C3          ret
+03A9  55          push bp
+03AA  8B EC       mov bp,sp
+03AC  53          push bx
+03AD  52          push dx
+03AE  56          push si
+03AF  57          push di
+03B0  FF 76 04    push word ptr [bp+4h]
+03B3  8B 76 04    mov si,word ptr [bp+4h]
+03B6  8B 04       mov ax,word ptr [si]
+03B8  8B 4C 02    mov cx,word ptr [si+2h]
+03BB  8B 54 04    mov dx,word ptr [si+4h]
+03BE  89 CB       mov bx,cx
+03C0  8B FE       mov di,si
+03C2  8B 4D 06    mov cx,word ptr [di+6h]
+03C5  8B 75 08    mov si,word ptr [di+8h]
+03C8  8B 7D 0A    mov di,word ptr [di+0ah]
+03CB  C7 06 90 0D 00 00 mov word ptr [0d90h],0h
+03D1  E8 4D 00    call 421h
+03D4  5F          pop di
+03D5  89 05       mov word ptr [di],ax
+03D7  89 5D 02    mov word ptr [di+2h],bx
+03DA  89 55 04    mov word ptr [di+4h],dx
+03DD  5F          pop di
+03DE  5E          pop si
+03DF  5A          pop dx
+03E0  5B          pop bx
+03E1  89 EC       mov sp,bp
+03E3  5D          pop bp
+03E4  C3          ret
+03E5  55          push bp
+03E6  8B EC       mov bp,sp
+03E8  53          push bx
+03E9  52          push dx
+03EA  56          push si
+03EB  57          push di
+03EC  FF 76 04    push word ptr [bp+4h]
+03EF  8B 76 04    mov si,word ptr [bp+4h]
+03F2  8B 04       mov ax,word ptr [si]
+03F4  8B 4C 02    mov cx,word ptr [si+2h]
+03F7  8B 54 04    mov dx,word ptr [si+4h]
+03FA  89 CB       mov bx,cx
+03FC  8B FE       mov di,si
+03FE  8B 4D 06    mov cx,word ptr [di+6h]
+0401  8B 75 08    mov si,word ptr [di+8h]
+0404  8B 7D 0A    mov di,word ptr [di+0ah]
+0407  C7 06 90 0D 00 80 mov word ptr [0d90h],8000h
+040D  E8 11 00    call 421h
+0410  5F          pop di
+0411  89 05       mov word ptr [di],ax
+0413  89 5D 02    mov word ptr [di+2h],bx
+0416  89 55 04    mov word ptr [di+4h],dx
+0419  5F          pop di
+041A  5E          pop si
+041B  5A          pop dx
+041C  5B          pop bx
+041D  89 EC       mov sp,bp
+041F  5D          pop bp
+0420  C3          ret
+0421  80 F9 00    cmp cl,0h
+0424  74 0E       je 434h
+0426  33 3E 90 0D xor di,word ptr [0d90h]
+042A  3C 00       cmp al,0h
+042C  75 07       jne 435h
+042E  89 C8       mov ax,cx
+0430  89 F3       mov bx,si
+0432  89 FA       mov dx,di
+0434  C3          ret
+0435  38 C8       cmp al,cl
+0437  76 05       jbe 43eh
+0439  91          xchg ax,cx
+043A  87 F3       xchg bx,si
+043C  87 FA       xchg dx,di
+043E  88 0E 94 0D mov byte ptr [0d94h],cl
+0442  28 C1       sub cl,al
+0444  80 F9 28    cmp cl,28h
+0447  72 06       jb 44fh
+0449  8A 0E 94 0D mov cl,byte ptr [0d94h]
+044D  EB DF       jmp 42eh
+044F  89 3E 90 0D mov word ptr [0d90h],di
+0453  80 26 91 0D 80 and byte ptr [0d91h],80h
+0458  89 3E 92 0D mov word ptr [0d92h],di
+045C  30 36 93 0D xor byte ptr [0d93h],dh
+0460  81 CF 00 80 or di,8000h
+0464  80 CE 80    or dh,80h
+0467  80 F9 10    cmp cl,10h
+046A  72 0B       jb 477h
+046C  88 FC       mov ah,bh
+046E  89 D3       mov bx,dx
+0470  31 D2       xor dx,dx
+0472  80 E9 10    sub cl,10h
+0475  EB F0       jmp 467h
+0477  80 F9 08    cmp cl,8h
+047A  72 0D       jb 489h
+047C  88 DC       mov ah,bl
+047E  88 FB       mov bl,bh
+0480  88 D7       mov bh,dl
+0482  88 F2       mov dl,dh
+0484  30 F6       xor dh,dh
+0486  80 E9 08    sub cl,8h
+0489  80 F9 00    cmp cl,0h
+048C  74 0A       je 498h
+048E  D1 EA       shr dx,1h
+0490  D1 DB       rcr bx,1h
+0492  D0 DC       rcr ah,1h
+0494  FE C9       dec cl
+0496  75 F6       jne 48eh
+0498  A0 94 0D    mov al,byte ptr [0d94h]
+049B  F6 06 93 0D 80 test byte ptr [0d93h],80h
+04A0  75 14       jne 4b6h
+04A2  00 EC       add ah,ch
+04A4  11 F3       adc bx,si
+04A6  11 FA       adc dx,di
+04A8  73 5F       jnb 509h
+04AA  D1 DA       rcr dx,1h
+04AC  D1 DB       rcr bx,1h
+04AE  D0 DC       rcr ah,1h
+04B0  FE C0       inc al
+04B2  75 55       jne 509h
+04B4  F9          stc
+04B5  C3          ret
+04B6  86 EC       xchg ah,ch
+04B8  87 F3       xchg bx,si
+04BA  87 FA       xchg dx,di
+04BC  28 EC       sub ah,ch
+04BE  19 F3       sbb bx,si
+04C0  19 FA       sbb dx,di
+04C2  73 14       jnb 4d8h
+04C4  80 36 91 0D 80 xor byte ptr [0d91h],80h
+04C9  F6 D4       not ah
+04CB  F7 D3       not bx
+04CD  F7 D2       not dx
+04CF  80 C4 01    add ah,1h
+04D2  83 D3 00    adc bx,0h
+04D5  83 D2 00    adc dx,0h
+04D8  B1 05       mov cl,5h
+04DA  80 FE 00    cmp dh,0h
+04DD  75 14       jne 4f3h
+04DF  88 D6       mov dh,dl
+04E1  88 FA       mov dl,bh
+04E3  88 DF       mov bh,bl
+04E5  88 E3       mov bl,ah
+04E7  30 E4       xor ah,ah
+04E9  2C 08       sub al,8h
+04EB  72 15       jb 502h
+04ED  FE C9       dec cl
+04EF  75 E9       jne 4dah
+04F1  EB 0F       jmp 502h
+04F3  F6 C6 80    test dh,80h
+04F6  75 11       jne 509h
+04F8  D0 E4       shl ah,1h
+04FA  D1 D3       rcl bx,1h
+04FC  D1 D2       rcl dx,1h
+04FE  FE C8       dec al
+0500  75 F1       jne 4f3h
+0502  31 C0       xor ax,ax
+0504  31 DB       xor bx,bx
+0506  31 D2       xor dx,dx
+0508  C3          ret
+0509  80 E6 7F    and dh,7fh
+050C  32 36 91 0D xor dh,byte ptr [0d91h]
+0510  C3          ret
+0511  55          push bp
+0512  8B EC       mov bp,sp
+0514  53          push bx
+0515  52          push dx
+0516  56          push si
+0517  57          push di
+0518  FF 76 04    push word ptr [bp+4h]
+051B  8B 76 04    mov si,word ptr [bp+4h]
+051E  8B 04       mov ax,word ptr [si]
+0520  8B 4C 02    mov cx,word ptr [si+2h]
+0523  8B 54 04    mov dx,word ptr [si+4h]
+0526  89 CB       mov bx,cx
+0528  8B FE       mov di,si
+052A  8B 4D 06    mov cx,word ptr [di+6h]
+052D  8B 75 08    mov si,word ptr [di+8h]
+0530  8B 7D 0A    mov di,word ptr [di+0ah]
+0533  E8 11 00    call 547h
+0536  5F          pop di
+0537  89 05       mov word ptr [di],ax
+0539  89 5D 02    mov word ptr [di+2h],bx
+053C  89 55 04    mov word ptr [di+4h],dx
+053F  5F          pop di
+0540  5E          pop si
+0541  5A          pop dx
+0542  5B          pop bx
+0543  89 EC       mov sp,bp
+0545  5D          pop bp
+0546  C3          ret
+0547  80 F9 00    cmp cl,0h
+054A  75 03       jne 54fh
+054C  E9 A4 00    jmp 5f3h
+054F  3C 00       cmp al,0h
+0551  75 03       jne 556h
+0553  E9 A3 00    jmp 5f9h
+0556  00 C8       add al,cl
+0558  72 07       jb 561h
+055A  04 80       add al,80h
+055C  72 0D       jb 56bh
+055E  E9 92 00    jmp 5f3h
+0561  04 80       add al,80h
+0563  73 06       jnb 56bh
+0565  B0 01       mov al,1h
+0567  B4 4C       mov ah,4ch
+0569  CD 21       int 21h
+056B  89 0E 9B 0D mov word ptr [0d9bh],cx
+056F  8B CA       mov cx,dx
+0571  31 F9       xor cx,di
+0573  F6 D5       not ch
+0575  80 E5 80    and ch,80h
+0578  88 2E 91 0D mov byte ptr [0d91h],ch
+057C  80 CE 80    or dh,80h
+057F  81 CF 00 80 or di,8000h
+0583  89 36 9D 0D mov word ptr [0d9dh],si
+0587  89 3E 9F 0D mov word ptr [0d9fh],di
+058B  A3 95 0D    mov word ptr [0d95h],ax
+058E  89 1E 97 0D mov word ptr [0d97h],bx
+0592  89 16 99 0D mov word ptr [0d99h],dx
+0596  30 E4       xor ah,ah
+0598  31 DB       xor bx,bx
+059A  31 D2       xor dx,dx
+059C  BF 9B 0D    mov di,0d9bh
+059F  B1 05       mov cl,5h
+05A1  47          inc di
+05A2  8A 2D       mov ch,byte ptr [di]
+05A4  80 FD 00    cmp ch,0h
+05A7  75 0C       jne 5b5h
+05A9  88 DC       mov ah,bl
+05AB  88 FB       mov bl,bh
+05AD  88 D7       mov bh,dl
+05AF  88 F2       mov dl,dh
+05B1  30 F6       xor dh,dh
+05B3  EB 1C       jmp 5d1h
+05B5  BE 08 00    mov si,8h
+05B8  D0 DD       rcr ch,1h
+05BA  73 0C       jnb 5c8h
+05BC  02 26 96 0D add ah,byte ptr [0d96h]
+05C0  13 1E 97 0D adc bx,word ptr [0d97h]
+05C4  13 16 99 0D adc dx,word ptr [0d99h]
+05C8  D1 DA       rcr dx,1h
+05CA  D1 DB       rcr bx,1h
+05CC  D0 DC       rcr ah,1h
+05CE  4E          dec si
+05CF  75 E7       jne 5b8h
+05D1  FE C9       dec cl
+05D3  75 CC       jne 5a1h
+05D5  91          xchg ax,cx
+05D6  9F          lahf
+05D7  F6 C6 80    test dh,80h
+05DA  75 0E       jne 5eah
+05DC  9E          sahf
+05DD  D0 D5       rcl ch,1h
+05DF  D1 D3       rcl bx,1h
+05E1  D1 D2       rcl dx,1h
+05E3  80 F9 00    cmp cl,0h
+05E6  74 02       je 5eah
+05E8  FE C9       dec cl
+05EA  91          xchg ax,cx
+05EB  32 36 91 0D xor dh,byte ptr [0d91h]
+05EF  3C 00       cmp al,0h
+05F1  75 06       jne 5f9h
+05F3  31 C0       xor ax,ax
+05F5  31 DB       xor bx,bx
+05F7  31 D2       xor dx,dx
+05F9  C3          ret
+05FA  55          push bp
+05FB  8B EC       mov bp,sp
+05FD  53          push bx
+05FE  52          push dx
+05FF  56          push si
+0600  57          push di
+0601  FF 76 04    push word ptr [bp+4h]
+0604  8B 76 04    mov si,word ptr [bp+4h]
+0607  8B 04       mov ax,word ptr [si]
+0609  8B 4C 02    mov cx,word ptr [si+2h]
+060C  8B 54 04    mov dx,word ptr [si+4h]
+060F  89 CB       mov bx,cx
+0611  8B FE       mov di,si
+0613  8B 4D 06    mov cx,word ptr [di+6h]
+0616  8B 75 08    mov si,word ptr [di+8h]
+0619  8B 7D 0A    mov di,word ptr [di+0ah]
+061C  E8 11 00    call 630h
+061F  5F          pop di
+0620  89 05       mov word ptr [di],ax
+0622  89 5D 02    mov word ptr [di+2h],bx
+0625  89 55 04    mov word ptr [di+4h],dx
+0628  5F          pop di
+0629  5E          pop si
+062A  5A          pop dx
+062B  5B          pop bx
+062C  89 EC       mov sp,bp
+062E  5D          pop bp
+062F  C3          ret
+0630  3C 00       cmp al,0h
+0632  75 03       jne 637h
+0634  E9 C2 FF    jmp 5f9h
+0637  28 C8       sub al,cl
+0639  F5          cmc
+063A  72 07       jb 643h
+063C  04 80       add al,80h
+063E  72 0D       jb 64dh
+0640  E9 B0 FF    jmp 5f3h
+0643  04 80       add al,80h
+0645  73 06       jnb 64dh
+0647  B0 01       mov al,1h
+0649  B4 4C       mov ah,4ch
+064B  CD 21       int 21h
+064D  89 0E 9B 0D mov word ptr [0d9bh],cx
+0651  8B CA       mov cx,dx
+0653  31 F9       xor cx,di
+0655  F6 D5       not ch
+0657  80 E5 80    and ch,80h
+065A  88 2E 91 0D mov byte ptr [0d91h],ch
+065E  80 CE 80    or dh,80h
+0661  81 CF 00 80 or di,8000h
+0665  89 36 9D 0D mov word ptr [0d9dh],si
+0669  89 3E 9F 0D mov word ptr [0d9fh],di
+066D  A2 95 0D    mov byte ptr [0d95h],al
+0670  BF 9A 0D    mov di,0d9ah
+0673  B1 05       mov cl,5h
+0675  BE 08 00    mov si,8h
+0678  3B 16 9F 0D cmp dx,word ptr [0d9fh]
+067C  75 0A       jne 688h
+067E  3B 1E 9D 0D cmp bx,word ptr [0d9dh]
+0682  75 04       jne 688h
+0684  3A 26 9C 0D cmp ah,byte ptr [0d9ch]
+0688  72 0C       jb 696h
+068A  2A 26 9C 0D sub ah,byte ptr [0d9ch]
+068E  1B 1E 9D 0D sbb bx,word ptr [0d9dh]
+0692  1B 16 9F 0D sbb dx,word ptr [0d9fh]
+0696  F5          cmc
+0697  D0 D5       rcl ch,1h
+0699  4E          dec si
+069A  75 0A       jne 6a6h
+069C  88 2D       mov byte ptr [di],ch
+069E  FE C9       dec cl
+06A0  74 1B       je 6bdh
+06A2  4F          dec di
+06A3  BE 08 00    mov si,8h
+06A6  D0 E4       shl ah,1h
+06A8  D1 D3       rcl bx,1h
+06AA  D1 D2       rcl dx,1h
+06AC  73 CA       jnb 678h
+06AE  2A 26 9C 0D sub ah,byte ptr [0d9ch]
+06B2  1B 1E 9D 0D sbb bx,word ptr [0d9dh]
+06B6  1B 16 9F 0D sbb dx,word ptr [0d9fh]
+06BA  F8          clc
+06BB  EB D9       jmp 696h
+06BD  D0 E4       shl ah,1h
+06BF  D1 D3       rcl bx,1h
+06C1  D1 D2       rcl dx,1h
+06C3  72 11       jb 6d6h
+06C5  3B 16 9F 0D cmp dx,word ptr [0d9fh]
+06C9  75 0A       jne 6d5h
+06CB  3B 1E 9D 0D cmp bx,word ptr [0d9dh]
+06CF  75 04       jne 6d5h
+06D1  3A 26 9C 0D cmp ah,byte ptr [0d9ch]
+06D5  F5          cmc
+06D6  8B 0E 95 0D mov cx,word ptr [0d95h]
+06DA  8B 1E 97 0D mov bx,word ptr [0d97h]
+06DE  8B 16 99 0D mov dx,word ptr [0d99h]
+06E2  9F          lahf
+06E3  F6 C6 80    test dh,80h
+06E6  75 09       jne 6f1h
+06E8  9E          sahf
+06E9  D0 D5       rcl ch,1h
+06EB  D1 D3       rcl bx,1h
+06ED  D1 D2       rcl dx,1h
+06EF  EB 0A       jmp 6fbh
+06F1  FE C1       inc cl
+06F3  75 06       jne 6fbh
+06F5  B0 01       mov al,1h
+06F7  B4 4C       mov ah,4ch
+06F9  CD 21       int 21h
+06FB  E9 EC FE    jmp 5eah
+06FE  55          push bp
+06FF  8B EC       mov bp,sp
+0701  53          push bx
+0702  52          push dx
+0703  56          push si
+0704  57          push di
+0705  8B 76 04    mov si,word ptr [bp+4h]
+0708  8B 04       mov ax,word ptr [si]
+070A  8B 4C 02    mov cx,word ptr [si+2h]
+070D  8B 54 04    mov dx,word ptr [si+4h]
+0710  89 CB       mov bx,cx
+0712  8B FE       mov di,si
+0714  8B 4D 06    mov cx,word ptr [di+6h]
+0717  8B 75 08    mov si,word ptr [di+8h]
+071A  8B 7D 0A    mov di,word ptr [di+0ah]
+071D  52          push dx
+071E  31 FA       xor dx,di
+0720  5A          pop dx
+0721  79 06       jns 729h
+0723  52          push dx
+0724  D1 D2       rcl dx,1h
+0726  5A          pop dx
+0727  EB 10       jmp 739h
+0729  F6 C6 80    test dh,80h
+072C  74 08       je 736h
+072E  E8 20 00    call 751h
+0731  74 06       je 739h
+0733  F5          cmc
+0734  EB 03       jmp 739h
+0736  E8 18 00    call 751h
+0739  B0 00       mov al,0h
+073B  B4 00       mov ah,0h
+073D  72 06       jb 745h
+073F  74 08       je 749h
+0741  B0 01       mov al,1h
+0743  EB 04       jmp 749h
+0745  B0 FF       mov al,0ffh
+0747  B4 FF       mov ah,0ffh
+0749  5F          pop di
+074A  5E          pop si
+074B  5A          pop dx
+074C  5B          pop bx
+074D  89 EC       mov sp,bp
+074F  5D          pop bp
+0750  C3          ret
+0751  38 C8       cmp al,cl
+0753  75 0E       jne 763h
+0755  3C 00       cmp al,0h
+0757  74 0A       je 763h
+0759  39 FA       cmp dx,di
+075B  75 06       jne 763h
+075D  39 F3       cmp bx,si
+075F  75 02       jne 763h
+0761  38 EC       cmp ah,ch
+0763  C3          ret
+0764  55          push bp
+0765  8B EC       mov bp,sp
+0767  53          push bx
+0768  52          push dx
+0769  56          push si
+076A  57          push di
+076B  FF 76 04    push word ptr [bp+4h]
+076E  8B 76 04    mov si,word ptr [bp+4h]
+0771  8B 04       mov ax,word ptr [si]
+0773  8B 4C 02    mov cx,word ptr [si+2h]
+0776  8B 54 04    mov dx,word ptr [si+4h]
+0779  89 CB       mov bx,cx
+077B  3C A8       cmp al,0a8h
+077D  73 4C       jnb 7cbh
+077F  89 C1       mov cx,ax
+0781  89 DE       mov si,bx
+0783  89 D7       mov di,dx
+0785  30 E4       xor ah,ah
+0787  31 DB       xor bx,bx
+0789  31 D2       xor dx,dx
+078B  80 E9 80    sub cl,80h
+078E  76 4C       jbe 7dch
+0790  80 F9 10    cmp cl,10h
+0793  72 0C       jb 7a1h
+0795  88 FC       mov ah,bh
+0797  89 D3       mov bx,dx
+0799  BA FF FF    mov dx,0ffffh
+079C  80 E9 10    sub cl,10h
+079F  EB EF       jmp 790h
+07A1  80 F9 08    cmp cl,8h
+07A4  72 0F       jb 7b5h
+07A6  88 DC       mov ah,bl
+07A8  88 FB       mov bl,bh
+07AA  88 D7       mov bh,dl
+07AC  88 F2       mov dl,dh
+07AE  B6 FF       mov dh,0ffh
+07B0  80 E9 08    sub cl,8h
+07B3  EB EC       jmp 7a1h
+07B5  80 F9 00    cmp cl,0h
+07B8  74 0B       je 7c5h
+07BA  F9          stc
+07BB  D1 DA       rcr dx,1h
+07BD  D1 DB       rcr bx,1h
+07BF  D0 DC       rcr ah,1h
+07C1  FE C9       dec cl
+07C3  75 F5       jne 7bah
+07C5  21 FA       and dx,di
+07C7  21 F3       and bx,si
+07C9  20 EC       and ah,ch
+07CB  5F          pop di
+07CC  89 05       mov word ptr [di],ax
+07CE  89 5D 02    mov word ptr [di+2h],bx
+07D1  89 55 04    mov word ptr [di+4h],dx
+07D4  5F          pop di
+07D5  5E          pop si
+07D6  5A          pop dx
+07D7  5B          pop bx
+07D8  89 EC       mov sp,bp
+07DA  5D          pop bp
+07DB  C3          ret
+07DC  B0 00       mov al,0h
+07DE  EB EB       jmp 7cbh
+07E0  55          push bp
+07E1  8B EC       mov bp,sp
+07E3  53          push bx
+07E4  52          push dx
+07E5  56          push si
+07E6  57          push di
+07E7  8B 7E 04    mov di,word ptr [bp+4h]
+07EA  88 EA       mov dl,ch
+07EC  B5 00       mov ch,0h
+07EE  B6 00       mov dh,0h
+07F0  51          push cx
+07F1  BB EB 0D    mov bx,0debh
+07F4  E8 41 02    call 0a38h
+07F7  59          pop cx
+07F8  89 D8       mov ax,bx
+07FA  BB EB 0D    mov bx,0debh
+07FD  2B C3       sub ax,bx
+07FF  A3 2B 0E    mov word ptr [0e2bh],ax
+0802  89 0E 2D 0E mov word ptr [0e2dh],cx
+0806  8B 06 2D 0E mov ax,word ptr [0e2dh]
+080A  8B 16 2B 0E mov dx,word ptr [0e2bh]
+080E  2B C2       sub ax,dx
+0810  83 F8 00    cmp ax,0h
+0813  7D 02       jnl 817h
+0815  31 C0       xor ax,ax
+0817  A3 2F 0E    mov word ptr [0e2fh],ax
+081A  8B 16 2B 0E mov dx,word ptr [0e2bh]
+081E  03 C2       add ax,dx
+0820  3D FF 00    cmp ax,0ffh
+0823  77 03       jnbe 828h
+0825  E9 03 00    jmp 82bh
+0828  B8 FF 00    mov ax,0ffh
+082B  A3 31 0E    mov word ptr [0e31h],ax
+082E  8B 56 06    mov dx,word ptr [bp+6h]
+0831  89 D7       mov di,dx
+0833  88 05       mov byte ptr [di],al
+0835  47          inc di
+0836  8B 0E 2F 0E mov cx,word ptr [0e2fh]
+083A  E3 07       jcxz 843h
+083C  B0 20       mov al,20h
+083E  88 05       mov byte ptr [di],al
+0840  47          inc di
+0841  E2 F9       loop 83ch
+0843  BE EB 0D    mov si,0debh
+0846  8B 0E 2B 0E mov cx,word ptr [0e2bh]
+084A  E3 08       jcxz 854h
+084C  8A 04       mov al,byte ptr [si]
+084E  88 05       mov byte ptr [di],al
+0850  46          inc si
+0851  47          inc di
+0852  E2 F8       loop 84ch
+0854  8B 06 31 0E mov ax,word ptr [0e31h]
+0858  5F          pop di
+0859  5E          pop si
+085A  5A          pop dx
+085B  5B          pop bx
+085C  89 EC       mov sp,bp
+085E  5D          pop bp
+085F  C3          ret
+0860  55          push bp
+0861  8B EC       mov bp,sp
+0863  53          push bx
+0864  52          push dx
+0865  56          push si
+0866  57          push di
+0867  8B 5E 04    mov bx,word ptr [bp+4h]
+086A  8B 7E 06    mov di,word ptr [bp+6h]
+086D  89 1E 33 0E mov word ptr [0e33h],bx
+0871  E8 CF 02    call 0b43h
+0874  73 03       jnb 879h
+0876  E9 0B 00    jmp 884h
+0879  89 D8       mov ax,bx
+087B  8B 16 33 0E mov dx,word ptr [0e33h]
+087F  2B C2       sub ax,dx
+0881  E9 03 00    jmp 887h
+0884  B8 FF FF    mov ax,0ffffh
+0887  5F          pop di
+0888  5E          pop si
+0889  5A          pop dx
+088A  5B          pop bx
+088B  89 EC       mov sp,bp
+088D  5D          pop bp
+088E  C3          ret
+088F  3C 00       cmp al,0h
+0891  74 03       je 896h
+0893  E9 01 00    jmp 897h
+0896  C3          ret
+0897  80 CE 80    or dh,80h
+089A  51          push cx
+089B  52          push dx
+089C  53          push bx
+089D  50          push ax
+089E  D1 EA       shr dx,1h
+08A0  D1 DB       rcr bx,1h
+08A2  D0 DC       rcr ah,1h
+08A4  D1 EA       shr dx,1h
+08A6  D1 DB       rcr bx,1h
+08A8  D0 DC       rcr ah,1h
+08AA  59          pop cx
+08AB  00 EC       add ah,ch
+08AD  59          pop cx
+08AE  13 D9       adc bx,cx
+08B0  59          pop cx
+08B1  13 D1       adc dx,cx
+08B3  59          pop cx
+08B4  72 03       jb 8b9h
+08B6  E9 0F 00    jmp 8c8h
+08B9  D1 DA       rcr dx,1h
+08BB  D1 DB       rcr bx,1h
+08BD  D0 DC       rcr ah,1h
+08BF  FE C0       inc al
+08C1  74 03       je 8c6h
+08C3  E9 02 00    jmp 8c8h
+08C6  F9          stc
+08C7  C3          ret
+08C8  80 E6 7F    and dh,7fh
+08CB  04 03       add al,3h
+08CD  C3          ret
+08CE  52          push dx
+08CF  53          push bx
+08D0  50          push ax
+08D1  88 0E AD 0D mov byte ptr [0dadh],cl
+08D5  80 F9 00    cmp cl,0h
+08D8  78 03       js 8ddh
+08DA  E9 02 00    jmp 8dfh
+08DD  F6 D9       neg cl
+08DF  88 CB       mov bl,cl
+08E1  80 E3 FC    and bl,0fch
+08E4  88 DF       mov bh,bl
+08E6  D0 EB       shr bl,1h
+08E8  00 FB       add bl,bh
+08EA  30 FF       xor bh,bh
+08EC  8D BF AF 0D lea di,[bx+0dafh]
+08F0  8B 05       mov ax,word ptr [di]
+08F2  8B 5D 02    mov bx,word ptr [di+2h]
+08F5  8B 55 04    mov dx,word ptr [di+4h]
+08F8  80 E1 03    and cl,3h
+08FB  75 03       jne 900h
+08FD  E9 0A 00    jmp 90ah
+0900  E8 8C FF    call 88fh
+0903  FE C9       dec cl
+0905  74 03       je 90ah
+0907  E9 F6 FF    jmp 900h
+090A  89 C1       mov cx,ax
+090C  89 DE       mov si,bx
+090E  89 D7       mov di,dx
+0910  58          pop ax
+0911  5B          pop bx
+0912  5A          pop dx
+0913  F6 06 AD 0D 80 test byte ptr [0dadh],80h
+0918  74 03       je 91dh
+091A  E9 03 00    jmp 920h
+091D  E9 27 FC    jmp 547h
+0920  E9 0D FD    jmp 630h
+0923  80 F9 DA    cmp cl,0dah
+0926  7D 03       jnl 92bh
+0928  E9 12 00    jmp 93dh
+092B  80 F9 26    cmp cl,26h
+092E  7E 03       jle 933h
+0930  E9 0A 00    jmp 93dh
+0933  51          push cx
+0934  56          push si
+0935  57          push di
+0936  E8 95 FF    call 8ceh
+0939  5F          pop di
+093A  5E          pop si
+093B  59          pop cx
+093C  C3          ret
+093D  F9          stc
+093E  C3          ret
+093F  8B 05       mov ax,word ptr [di]
+0941  8B 5D 02    mov bx,word ptr [di+2h]
+0944  8B 55 04    mov dx,word ptr [di+4h]
+0947  3C 00       cmp al,0h
+0949  74 03       je 94eh
+094B  E9 16 00    jmp 964h
+094E  BE A1 0D    mov si,0da1h
+0951  C7 04 30 30 mov word ptr [si],3030h
+0955  46          inc si
+0956  46          inc si
+0957  81 FE AD 0D cmp si,0dadh
+095B  74 03       je 960h
+095D  E9 F1 FF    jmp 951h
+0960  B9 00 00    mov cx,0h
+0963  C3          ret
+0964  88 F5       mov ch,dh
+0966  80 E6 7F    and dh,7fh
+0969  50          push ax
+096A  52          push dx
+096B  2C 80       sub al,80h
+096D  98          cbw
+096E  BA 4D 00    mov dx,4dh
+0971  F7 EA       imul dx
+0973  05 05 00    add ax,5h
+0976  88 E1       mov cl,ah
+0978  5A          pop dx
+0979  58          pop ax
+097A  80 F9 D9    cmp cl,0d9h
+097D  74 03       je 982h
+097F  E9 02 00    jmp 984h
+0982  FE C1       inc cl
+0984  51          push cx
+0985  F6 D9       neg cl
+0987  E8 44 FF    call 8ceh
+098A  59          pop cx
+098B  3C 81       cmp al,81h
+098D  72 03       jb 992h
+098F  E9 05 00    jmp 997h
+0992  E8 FA FE    call 88fh
+0995  FE C9       dec cl
+0997  51          push cx
+0998  80 CE 80    or dh,80h
+099B  B1 84       mov cl,84h
+099D  28 C1       sub cl,al
+099F  B0 00       mov al,0h
+09A1  80 F9 00    cmp cl,0h
+09A4  75 03       jne 9a9h
+09A6  E9 0D 00    jmp 9b6h
+09A9  D1 EA       shr dx,1h
+09AB  D1 DB       rcr bx,1h
+09AD  D0 DC       rcr ah,1h
+09AF  FE C9       dec cl
+09B1  74 03       je 9b6h
+09B3  E9 F3 FF    jmp 9a9h
+09B6  BE A1 0D    mov si,0da1h
+09B9  88 F5       mov ch,dh
+09BB  B1 04       mov cl,4h
+09BD  D2 ED       shr ch,cl
+09BF  80 C5 30    add ch,30h
+09C2  88 2C       mov byte ptr [si],ch
+09C4  80 E6 0F    and dh,0fh
+09C7  52          push dx
+09C8  53          push bx
+09C9  50          push ax
+09CA  D1 E0       shl ax,1h
+09CC  D1 D3       rcl bx,1h
+09CE  D1 D2       rcl dx,1h
+09D0  D1 E0       shl ax,1h
+09D2  D1 D3       rcl bx,1h
+09D4  D1 D2       rcl dx,1h
+09D6  59          pop cx
+09D7  03 C1       add ax,cx
+09D9  59          pop cx
+09DA  13 D9       adc bx,cx
+09DC  59          pop cx
+09DD  13 D1       adc dx,cx
+09DF  D1 E0       shl ax,1h
+09E1  D1 D3       rcl bx,1h
+09E3  D1 D2       rcl dx,1h
+09E5  46          inc si
+09E6  81 FE AD 0D cmp si,0dadh
+09EA  74 03       je 9efh
+09EC  E9 CA FF    jmp 9b9h
+09EF  59          pop cx
+09F0  C3          ret
+09F1  30 E4       xor ah,ah
+09F3  BB A1 0D    mov bx,0da1h
+09F6  03 D8       add bx,ax
+09F8  80 3F 35    cmp byte ptr [bx],35h
+09FB  C6 07 00    mov byte ptr [bx],0h
+09FE  73 03       jnb 0a03h
+0A00  E9 21 00    jmp 0a24h
+0A03  FE C8       dec al
+0A05  79 03       jns 0a0ah
+0A07  E9 11 00    jmp 0a1bh
+0A0A  4B          dec bx
+0A0B  FE 07       inc byte ptr [bx]
+0A0D  80 3F 3A    cmp byte ptr [bx],3ah
+0A10  73 03       jnb 0a15h
+0A12  E9 0F 00    jmp 0a24h
+0A15  C6 07 00    mov byte ptr [bx],0h
+0A18  E9 E8 FF    jmp 0a03h
+0A1B  C6 07 31    mov byte ptr [bx],31h
+0A1E  C6 47 01 00 mov byte ptr [bx+1h],0h
+0A22  FE C1       inc cl
+0A24  C3          ret
+0A25  8A 04       mov al,byte ptr [si]
+0A27  3C 00       cmp al,0h
+0A29  75 03       jne 0a2eh
+0A2B  E9 04 00    jmp 0a32h
+0A2E  46          inc si
+0A2F  E9 02 00    jmp 0a34h
+0A32  B0 30       mov al,30h
+0A34  88 07       mov byte ptr [bx],al
+0A36  43          inc bx
+0A37  C3          ret
+0A38  53          push bx
+0A39  81 FA 19 00 cmp dx,19h
+0A3D  73 03       jnb 0a42h
+0A3F  E9 3F 00    jmp 0a81h
+0A42  89 C8       mov ax,cx
+0A44  80 FD 00    cmp ch,0h
+0A47  75 03       jne 0a4ch
+0A49  E9 10 00    jmp 0a5ch
+0A4C  F6 C5 80    test ch,80h
+0A4F  75 03       jne 0a54h
+0A51  E9 05 00    jmp 0a59h
+0A54  31 C0       xor ax,ax
+0A56  E9 03 00    jmp 0a5ch
+0A59  B8 FF 00    mov ax,0ffh
+0A5C  B2 07       mov dl,7h
+0A5E  F6 45 05 80 test byte ptr [di+5h],80h
+0A62  75 03       jne 0a67h
+0A64  E9 02 00    jmp 0a69h
+0A67  FE C2       inc dl
+0A69  2A C2       sub al,dl
+0A6B  72 03       jb 0a70h
+0A6D  E9 02 00    jmp 0a72h
+0A70  B0 00       mov al,0h
+0A72  3C 09       cmp al,9h
+0A74  73 03       jnb 0a79h
+0A76  E9 02 00    jmp 0a7bh
+0A79  B0 09       mov al,9h
+0A7B  FE C0       inc al
+0A7D  88 C2       mov dl,al
+0A7F  88 C6       mov dh,al
+0A81  52          push dx
+0A82  E8 BA FE    call 93fh
+0A85  5A          pop dx
+0A86  8A C2       mov al,dl
+0A88  FE C0       inc al
+0A8A  80 FE 00    cmp dh,0h
+0A8D  74 03       je 0a92h
+0A8F  E9 18 00    jmp 0aaah
+0A92  00 C8       add al,cl
+0A94  78 03       js 0a99h
+0A96  E9 08 00    jmp 0aa1h
+0A99  C6 06 A1 0D 00 mov byte ptr [0da1h],0h
+0A9E  E9 0C 00    jmp 0aadh
+0AA1  3C 0C       cmp al,0ch
+0AA3  73 03       jnb 0aa8h
+0AA5  E9 02 00    jmp 0aaah
+0AA8  B0 0B       mov al,0bh
+0AAA  E8 44 FF    call 9f1h
+0AAD  5B          pop bx
+0AAE  BE A1 0D    mov si,0da1h
+0AB1  F6 C5 80    test ch,80h
+0AB4  75 03       jne 0ab9h
+0AB6  E9 05 00    jmp 0abeh
+0AB9  B0 2D       mov al,2dh
+0ABB  E8 76 FF    call 0a34h
+0ABE  88 CD       mov ch,cl
+0AC0  80 FE 00    cmp dh,0h
+0AC3  75 03       jne 0ac8h
+0AC5  E9 02 00    jmp 0acah
+0AC8  B5 00       mov ch,0h
+0ACA  80 FD 00    cmp ch,0h
+0ACD  78 03       js 0ad2h
+0ACF  E9 06 00    jmp 0ad8h
+0AD2  E8 5D FF    call 0a32h
+0AD5  E9 0A 00    jmp 0ae2h
+0AD8  E8 4A FF    call 0a25h
+0ADB  FE CD       dec ch
+0ADD  78 03       js 0ae2h
+0ADF  E9 F6 FF    jmp 0ad8h
+0AE2  80 FA 00    cmp dl,0h
+0AE5  75 03       jne 0aeah
+0AE7  E9 23 00    jmp 0b0dh
+0AEA  B0 2E       mov al,2eh
+0AEC  E8 45 FF    call 0a34h
+0AEF  FE C5       inc ch
+0AF1  75 03       jne 0af6h
+0AF3  E9 0A 00    jmp 0b00h
+0AF6  E8 39 FF    call 0a32h
+0AF9  FE CA       dec dl
+0AFB  74 03       je 0b00h
+0AFD  E9 EF FF    jmp 0aefh
+0B00  FE CA       dec dl
+0B02  79 03       jns 0b07h
+0B04  E9 06 00    jmp 0b0dh
+0B07  E8 1B FF    call 0a25h
+0B0A  E9 F3 FF    jmp 0b00h
+0B0D  80 FE 00    cmp dh,0h
+0B10  74 03       je 0b15h
+0B12  E9 01 00    jmp 0b16h
+0B15  C3          ret
+0B16  B0 45       mov al,45h
+0B18  E8 19 FF    call 0a34h
+0B1B  B0 2B       mov al,2bh
+0B1D  80 F9 00    cmp cl,0h
+0B20  78 03       js 0b25h
+0B22  E9 04 00    jmp 0b29h
+0B25  F6 D9       neg cl
+0B27  B0 2D       mov al,2dh
+0B29  E8 08 FF    call 0a34h
+0B2C  B0 2F       mov al,2fh
+0B2E  FE C0       inc al
+0B30  80 E9 0A    sub cl,0ah
+0B33  72 03       jb 0b38h
+0B35  E9 F6 FF    jmp 0b2eh
+0B38  E8 F9 FE    call 0a34h
+0B3B  80 C1 3A    add cl,3ah
+0B3E  88 C8       mov al,cl
+0B40  E9 F1 FE    jmp 0a34h
+0B43  8A 0F       mov cl,byte ptr [bx]
+0B45  80 F9 2D    cmp cl,2dh
+0B48  74 03       je 0b4dh
+0B4A  E9 01 00    jmp 0b4eh
+0B4D  43          inc bx
+0B4E  51          push cx
+0B4F  E8 1F 00    call 0b71h
+0B52  59          pop cx
+0B53  73 03       jnb 0b58h
+0B55  E9 17 00    jmp 0b6fh
+0B58  80 F9 2D    cmp cl,2dh
+0B5B  74 03       je 0b60h
+0B5D  E9 0D 00    jmp 0b6dh
+0B60  8A 05       mov al,byte ptr [di]
+0B62  3C 00       cmp al,0h
+0B64  75 03       jne 0b69h
+0B66  E9 04 00    jmp 0b6dh
+0B69  80 75 05 80 xor byte ptr [di+5h],80h
+0B6D  F8          clc
+0B6E  C3          ret
+0B6F  F9          stc
+0B70  C3          ret
+0B71  89 DE       mov si,bx
+0B73  31 C0       xor ax,ax
+0B75  31 DB       xor bx,bx
+0B77  31 D2       xor dx,dx
+0B79  31 C9       xor cx,cx
+0B7B  C6 06 AE 0D 00 mov byte ptr [0daeh],0h
+0B80  8A 0C       mov cl,byte ptr [si]
+0B82  80 F9 61    cmp cl,61h
+0B85  73 03       jnb 0b8ah
+0B87  E9 08 00    jmp 0b92h
+0B8A  80 F9 7A    cmp cl,7ah
+0B8D  77 03       jnbe 0b92h
+0B8F  80 E9 20    sub cl,20h
+0B92  E8 C8 00    call 0c5dh
+0B95  73 03       jnb 0b9ah
+0B97  E9 3A 00    jmp 0bd4h
+0B9A  E8 F2 FC    call 88fh
+0B9D  73 03       jnb 0ba2h
+0B9F  E9 B5 00    jmp 0c57h
+0BA2  57          push di
+0BA3  56          push si
+0BA4  51          push cx
+0BA5  52          push dx
+0BA6  53          push bx
+0BA7  50          push ax
+0BA8  88 C8       mov al,cl
+0BAA  30 E4       xor ah,ah
+0BAC  E8 C2 F7    call 371h
+0BAF  89 C1       mov cx,ax
+0BB1  89 DE       mov si,bx
+0BB3  89 D7       mov di,dx
+0BB5  58          pop ax
+0BB6  5B          pop bx
+0BB7  5A          pop dx
+0BB8  C7 06 90 0D 00 00 mov word ptr [0d90h],0h
+0BBE  E8 60 F8    call 421h
+0BC1  59          pop cx
+0BC2  5E          pop si
+0BC3  5F          pop di
+0BC4  F6 C5 40    test ch,40h
+0BC7  75 03       jne 0bcch
+0BC9  E9 04 00    jmp 0bd0h
+0BCC  FE 0E AE 0D dec byte ptr [0daeh]
+0BD0  46          inc si
+0BD1  E9 AC FF    jmp 0b80h
+0BD4  80 F9 2E    cmp cl,2eh
+0BD7  74 03       je 0bdch
+0BD9  E9 0E 00    jmp 0beah
+0BDC  F6 C5 40    test ch,40h
+0BDF  74 03       je 0be4h
+0BE1  E9 73 00    jmp 0c57h
+0BE4  80 CD 40    or ch,40h
+0BE7  E9 E6 FF    jmp 0bd0h
+0BEA  80 F9 45    cmp cl,45h
+0BED  8A 0E AE 0D mov cl,byte ptr [0daeh]
+0BF1  74 03       je 0bf6h
+0BF3  E9 4D 00    jmp 0c43h
+0BF6  E8 2A FD    call 923h
+0BF9  73 03       jnb 0bfeh
+0BFB  E9 59 00    jmp 0c57h
+0BFE  46          inc si
+0BFF  8A 0C       mov cl,byte ptr [si]
+0C01  80 F9 2B    cmp cl,2bh
+0C04  75 03       jne 0c09h
+0C06  E9 0B 00    jmp 0c14h
+0C09  80 F9 2D    cmp cl,2dh
+0C0C  74 03       je 0c11h
+0C0E  E9 04 00    jmp 0c15h
+0C11  80 CD 20    or ch,20h
+0C14  46          inc si
+0C15  E8 43 00    call 0c5bh
+0C18  73 03       jnb 0c1dh
+0C1A  E9 3A 00    jmp 0c57h
+0C1D  50          push ax
+0C1E  88 C8       mov al,cl
+0C20  46          inc si
+0C21  E8 37 00    call 0c5bh
+0C24  73 03       jnb 0c29h
+0C26  E9 0D 00    jmp 0c36h
+0C29  88 C4       mov ah,al
+0C2B  D0 E0       shl al,1h
+0C2D  D0 E0       shl al,1h
+0C2F  00 E0       add al,ah
+0C31  D0 E0       shl al,1h
+0C33  00 C8       add al,cl
+0C35  46          inc si
+0C36  88 C1       mov cl,al
+0C38  58          pop ax
+0C39  F6 C5 20    test ch,20h
+0C3C  75 03       jne 0c41h
+0C3E  E9 02 00    jmp 0c43h
+0C41  F6 D9       neg cl
+0C43  E8 DD FC    call 923h
+0C46  73 03       jnb 0c4bh
+0C48  E9 0C 00    jmp 0c57h
+0C4B  89 05       mov word ptr [di],ax
+0C4D  89 5D 02    mov word ptr [di+2h],bx
+0C50  89 55 04    mov word ptr [di+4h],dx
+0C53  F8          clc
+0C54  E9 01 00    jmp 0c58h
+0C57  F9          stc
+0C58  89 F3       mov bx,si
+0C5A  C3          ret
+0C5B  8A 0C       mov cl,byte ptr [si]
+0C5D  80 F9 30    cmp cl,30h
+0C60  73 03       jnb 0c65h
+0C62  E9 0C 00    jmp 0c71h
+0C65  80 F9 3A    cmp cl,3ah
+0C68  F5          cmc
+0C69  73 03       jnb 0c6eh
+0C6B  E9 03 00    jmp 0c71h
+0C6E  80 E9 30    sub cl,30h
+0C71  C3          ret