home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / toadhall / long / toadconv.inc next >
Encoding:
Text File  |  1988-05-23  |  19.5 KB  |  517 lines

  1. {TOADCONV.INC}
  2. (* Copyright (C) 1988 David P Kirschbaum  All Rights Reserved *)
  3.  
  4. VAR
  5.   radix : INTEGER;             {for AnyNum_Str support}
  6.   NrStr : Str12;               {global Number working string}
  7.  
  8.  
  9. FUNCTION real_Mod(r1,r2 : REAL) : REAL;
  10.   {Turbo's MOD doesn't work with REALs.
  11.    WARNING:  On some numbers (namely even divisors),
  12.    we will get a mod that's not visibly different from the
  13.    intuitive MOD, but WILL in fact be different!
  14.    That's why I had to do the real mod "rounding".
  15.   }
  16.   VAR r3 : REAL;
  17.   BEGIN
  18.     IF r2 > r1 THEN real_Mod := r1      {divisor > dividend}
  19.     ELSE if r2 = r1 THEN real_Mod := 0.0 {divisor = dividend}
  20.     ELSE BEGIN
  21.       r3 := Frac(r1 / r2);              {mod's in the decimals}
  22.       IF r3 <> 0.0 THEN r3 := r2 * r3;  {nonzero, so get the mod}
  23.  
  24.       IF (r3 + 0.5) > Int(r3 + 0.5)     {real mod rounding}
  25.       THEN r3 := r3 + 0.5;
  26.  
  27.       real_Mod := Int(r3);              {return the Mod}
  28.     END;
  29.   END;  {of real_Mod}
  30.  
  31.  
  32. PROCEDURE Make_Long(hi,lo : INTEGER; VAR long : long_int);
  33.   {Create a long integer from two integers}
  34.   BEGIN
  35.     Inline(
  36.   $C4/$BE/>LONG    { les  di,>long[bp]  ;get target long's address}
  37.   /$FC             { cld                ;insure fwd}
  38.   /$8B/$86/>LO     { mov ax,>lo[bp]     ;get the low word}
  39.   /$AB             { stosw              ;stuff low word}
  40.   /$8B/$86/>HI     { mov ax,>hi[bp]     ;get the high word}
  41.   /$AB             { stosw              ;stuff it}
  42. );
  43.   END;  {of Make_Long}
  44.  
  45.  
  46. PROCEDURE Zero_Long(VAR long : long_int);
  47.   {Zero a long integer's lo and hi words}
  48.   BEGIN
  49.     Inline(
  50.   $C4/$BE/>LONG    {les  di,>long[bp]  ;get target long's address}
  51.   /$31/$C0         {xor  ax,ax         ;get a 0}
  52.   /$FC             {cld                ;insure fwd}
  53.   /$AB             {stosw              ; .lo}
  54.   /$AB             {stosw              ; .hi}
  55. );
  56.   END;  {of Zero_Long}
  57.  
  58.  
  59. FUNCTION unsigned_To_Real(u : integer) : REAL;
  60.   { v1.3 Convert unsigned integer to real
  61.     Note: INT is a FUNCTION that returns a REAL!!!
  62.     From DEARC.PAS package.
  63.     NO SIGNS!  This is part of UNSIGNED INTEGER MATH!
  64.   }
  65.   BEGIN
  66.     IF u >= 0 THEN unsigned_To_Real := Int(u)
  67.     ELSE IF u = $8000 then unsigned_To_Real := 32768.0
  68.     ELSE unsigned_To_Real := 65536.0 + u;
  69.   END;  {of unsigned_To_Real}
  70.  
  71.  
  72. FUNCTION real_To_Int(r : REAL) : INTEGER;
  73.   {Converts a REAL to an integer.
  74.    Works like TRUNC, but avoids the overflow problems.
  75.    NO SIGNS!  This is part of UNSIGNED INTEGER MATH!
  76.   }
  77.    VAR
  78.      i : INTEGER;
  79.      r1 : REAL;
  80.   BEGIN
  81.     r1 := real_Mod(r,65536.0);          {insure it's in integer range}
  82.     IF r1 < 1.0 THEN BEGIN              {nope, or negative}
  83.       real_To_Int := 0;                 {no negatives}
  84.       Exit;
  85.     END;
  86.  
  87.     IF r1 > 32768.0 THEN real_To_Int := TRUNC(r1 - 65536.0)
  88.     ELSE IF r1 = 32768.0 THEN real_To_Int := $8000
  89.     ELSE real_To_Int := TRUNC(r1);
  90.   END;  {of real_To_Int}
  91.  
  92.  
  93. FUNCTION long_To_Real (VAR long : long_int) : REAL;
  94.   {This function takes the high and low words of a long int
  95.   and converts it to a REAL.
  96.   }
  97.   VAR r : REAL;
  98.   BEGIN
  99.     IF long.hi = 0 THEN r := 0.0
  100.     ELSE r := unsigned_To_Real(long.hi) * 65536.0;
  101.  
  102.     IF long.lo <> 0
  103.     THEN r := r + unsigned_To_Real(long.lo);
  104.     long_To_Real := r;
  105.   END;  {of long_To_Real}
  106.  
  107.  
  108. PROCEDURE Real_To_Long(r : REAL; VAR long : long_int);
  109.   {This procedure changes a REAL to a long integer.
  110.    v1.3 }
  111.   VAR
  112.     r1,r2 : REAL;
  113.   BEGIN
  114.     long := LONG_ZERO;                  {assume zero}
  115.     IF r <= 0.0 THEN Exit;              {done, NO SIGNS!}
  116.  
  117.     IF r > MAXREALINT THEN BEGIN        {max long int size}
  118.       Stc;                              {set global Carry to show overflow}
  119.       long := MAXLONGINT;               {equivalent typed constant record}
  120.       Exit;
  121.     END;
  122.  
  123.     IF r >= 65536.0                     {we have a long.hi}
  124.     THEN long.hi := real_To_Int(Int(r / 65536.0)); {get its value}
  125.  
  126.     long.lo := real_To_Int(Int(real_Mod(r,65536.0)) );
  127.   END;  {of Real_To_Long}
  128.  
  129.  
  130. FUNCTION long_Kb(VAR long : long_int) : INTEGER;
  131.   {Convert long int to Kb integer.  Handy for
  132.    simple file size conversion.
  133.    v1.3 recoded in assembler
  134.   }
  135.   BEGIN
  136. (* In Turbo:  1.59 secs in a test vs assembler's 1.48 secs
  137.     long_kb := (long.lo SHR 10) + (long.hi SHL 6);
  138. *)
  139.     Inline(
  140.   $8C/$DB          {mov  bx,DS         ;save dx}
  141.   /$C5/$B6/>LONG   {lds  si,>long[bp]  ;get long address}
  142.   /$B9/$0A/$06     {mov  cx,$060A      ;ch=shr, cl=shl values}
  143.   /$AD             {lodsw              ;long.hi}
  144.   /$8B/$14         {mov  dx,[si]       ;long.lo}
  145.   /$D3/$E0         {shl  ax,cl         ;long.hi shl 6}
  146.   /$88/$E9         {mov  cl,ch         ;10}
  147.   /$D3/$E2         {shl  dx,cl         ;long.lo shr 10}
  148.   /$01/$D0         {add  ax,dx         ;product in kb}
  149.   /$89/$46/$08     {mov  [bp+8],ax     ;stuff function's integer}
  150.   /$8E/$DB         {mov  DS,bx         ;restore DS}
  151. );
  152.   END;  {of long_Kb1}
  153.  
  154. (* long integer string conversions.
  155.    I assume you wish number strings padded to a consistent length
  156.    for easy screen or printer columns.
  157.  
  158.    That's reflected in the Str%% length returned from each of these
  159.    functions.  You can tweak the required padding as desired,
  160.    OR run the strings through a Stripper function that strips out
  161.    left-padding spaces.
  162. *)
  163.  
  164. FUNCTION Long_Size_Str(VAR size : long_int) : Str12;
  165.   {Returns a long int as a 6-digit left-padded number string,
  166.    converted to Kb if above an arbitrary size (MAXINT),
  167.    plus " Bytes" or "Kb" appended as appropriate.
  168.    Handy for displaying file sizes.
  169.    I use the global NrStr here as a working string for speed, tightness.
  170.    Sooooo bad, I know .....  Just making sure you're paying attention.
  171.   }
  172.   BEGIN
  173.     IF (size.hi = 0) AND (size.lo >= 0)   { Small # or small enough }
  174.     THEN BEGIN
  175.       Str(size.lo:6,NrStr);
  176.       Long_Size_Str := NrStr + ' Bytes';
  177.     END
  178.     ELSE BEGIN                            {too big, do in Kb}
  179.       Str(long_Kb(size):6,NrStr);
  180.       Long_Size_Str := NrStr + ' Kb   ';
  181.     END;
  182.   END;  {of Long_Size_Str}
  183.  
  184.  
  185. FUNCTION Long_Str(VAR long : long_int) : Str12;
  186.   {Converts long int to a left-padded 8-character string
  187.    if you just GOTTA have all them byte digits.
  188.    Uses global working string NrStr for speed, tightness.
  189.   }
  190.   BEGIN
  191.     Str(long_To_Real(long):12:0,NrStr);
  192.     Long_Str := NrStr;
  193.   END;  {of Long_Str}
  194.  
  195.  
  196. FUNCTION Flashy_Long_Str(VAR long : long_int) : Str10;
  197.   {Converts long int to a left-padded 10-char string,
  198.    but this time with commas.
  199.    Uses global working string NrStr for speed, tightness.
  200.   }
  201.   BEGIN
  202.     NrStr := Long_Str(long);           {returns up to 12345678,
  203.                                         padded left with spaces}
  204.                                        {12345678}
  205.     IF NrStr[5] <> ' ' THEN BEGIN      {    ^ got at least 4 digits}
  206.       Insert(',', NrStr, 6);           {12345,678  stuff the comma}
  207.       IF NrStr[2] <> ' '               { ^    still digits}
  208.       THEN Insert(',', NrStr, 3);      {12,345,678  that's it!}
  209.     END;
  210.     Flashy_Long_Str := NrStr;          {return the string}
  211.   END;  {of Flashy_Long_Str}
  212.  
  213.  
  214. (* Hexifying routines, integer and long integer *)
  215.  
  216.  
  217. PROCEDURE Hexify(i : INTEGER; VAR NrStr : Str5);
  218.   {Fills NrStr (somewhere out there) with x converted to Hex.
  219.    Does NOT left-pad with spaces!
  220.    We do this with a PROCEDURE and a VAR string rather than a FUNCTION
  221.    returning a string because of speed and tightness.
  222.  
  223.    Naturally, NrStr does not HAVE to be a STRING[4];
  224.    it could be any string TYPEd as 4 chars or more, but you'd better
  225.    not use a smaller one!  This routine does NOT check and could
  226.    overwrite other adjacent variables if you try to stuff 4 characters
  227.    into a STRING[2]!
  228.    v1.3 tightened.
  229.   }
  230.   BEGIN
  231.     Inline(
  232.   $C4/$BE/>NRSTR   {  les  di,>NrStr[bp] ;string offset, seg}
  233.   /$B8/$04/$04     {  mov  ax,$0404}
  234.   /$FC             {  cld                ;insure fwd}
  235.   /$AA             {  stosb              ;force string len to 4}
  236.   /$89/$C1         {  mov  cx,ax         ;ch=loop cntr, cl=ROL const}
  237.   /$BA/$0F/$30     {  mov  dx,$300F      ;2 constants $30, $0F}
  238.   /$8B/$9E/>I      {  mov  bx,>i[bp]     ;get the integer parm}
  239.                    {Rotate:}
  240.   /$D3/$C3         {  rol  bx,cl         ;get a nibble (4 bytes)}
  241.   /$88/$D8         {  mov  al,bl         ;asciify this nibble}
  242.   /$20/$D0         {  and  al,dl         ;mask (constant $0F)}
  243.   /$00/$F0         {  add  al,dh         ;asciify (constant $30)}
  244.   /$3C/$3A         {  cmp  al,$3A        ;ran out of regs!}
  245.   /$72/$02         {  jb   StuffIt       ;<= '9'}
  246.   /$04/$07         {  add  al,7          ;bump to 'A'..'F'}
  247.                    {StuffIt:}
  248.   /$AA             {  stosb              ;stuff char in string}
  249.   /$FE/$CD         {  dec  ch            ;done yet?}
  250.   /$75/$ED         {  jnz  Rotate        ;nope, loop until done}
  251. );
  252.   END;  {of Hexify}
  253.  
  254.  
  255. FUNCTION Hex(i : INTEGER) : Str5;
  256.   {Returns integer as a hex string.
  257.    Faster than table-driven hexify routines.
  258.    v1.3 tightened
  259.   }
  260.   BEGIN
  261.     Inline(
  262.   $8C/$D0          {  mov  ax,SS}
  263.   /$8E/$C0         {  mov  ES,ax      ;ES=SS}
  264.   /$89/$EF         {  mov  di,bp      ;stack offset}
  265.   /$81/$C7/$06/$00 {  add  di,6       ;where string will begin}
  266.   /$B8/$04/$04     {  mov  ax,$0404}
  267.   /$89/$C1         {  mov  cx,ax      ;loop cntr4, ROL constant}
  268.   /$FC             {  cld                ;insure fwd}
  269.   /$AA             {  stosb              ;force string len to 4}
  270.   /$BA/$0F/$30     {  mov  dx,$300F      ;2 constants $30, $0F}
  271.   /$8B/$9E/>I      {  mov  bx,>i[bp]     ;get the integer parm}
  272.                    {Rotate:}
  273.   /$D3/$C3         {  rol  bx,cl         ;get a nibble (4 bytes)}
  274.   /$88/$D8         {  mov  al,bl         ;asciify this nibble}
  275.   /$20/$D0         {  and  al,dl         ;mask (constant $0F)}
  276.   /$00/$F0         {  add  al,dh         ;asciify (constant $30)}
  277.   /$3C/$3A         {  cmp  al,$3A        ;ran out of regs!}
  278.   /$72/$02         {  jb   StuffIt       ;<= '9'}
  279.   /$04/$07         {  add  al,7          ;bump to 'A'..'F'}
  280.                    {StuffIt:}
  281.   /$AA             {  stosb              ;stuff char in string}
  282.   /$FE/$CD         {  dec  ch            ;done yet?}
  283.   /$75/$ED         {  jnz  Rotate        ;nope, loop until done}
  284. );
  285.   END;  {of Hex3}
  286.  
  287.  
  288. PROCEDURE LStr_Hex(VAR long : long_int; VAR NrStr : Str12);
  289.   {Converts a long integer into the Hexidecimal string NrStr.
  290.    Format:  0000:0000  hi word, then lo word.
  291.    v1.3 tightened.
  292.   }
  293.   BEGIN
  294.     Inline(
  295.   $1E              {  push DS}
  296.   /$C4/$BE/>NRSTR  {  les  di,>NrStr[bp] ;string offset, seg}
  297.   /$C5/$B6/>LONG   {  lds  si,>long[bp]  ;long ofs}
  298.   /$B0/$09         {  mov  al,9          ;9 digits for 32-bit}
  299.   /$FC             {  cld                ;from left to right}
  300.   /$AA             {  stosb              ;force string len to 9}
  301.   /$B8/$04/$04     {  mov  ax,$0404      ;ah is constant}
  302.   /$89/$C1         {  mov  cx,ax         ;cl=ROL, ch=loop cntr}
  303.   /$BA/$0F/$30     {  mov  dx,$300F      ;2 constants $30, $0F}
  304.   /$8B/$5C/$02     {  mov  bx,[si+2]     ;long.hi}
  305.   /$E8/$0C/$00     {  call Rotate        ;do first integer}
  306.   /$B0/$3A         {  mov  al,$3A        ;":"}
  307.   /$AA             {  stosb              ;stuff in string}
  308.   /$8B/$1C         {  mov  bx,[si]       ;long.lo}
  309.   /$88/$E5         {  mov  ch,ah         ;refresh loop cntr}
  310.   /$E8/$02/$00     {  call Rotate}
  311.   /$EB/$14         {  jmp  short Exit    ;done}
  312.                    
  313.                    {Rotate:}
  314.   /$D3/$C3         {  rol  bx,cl         ;get a nibble (4 bytes)}
  315.   /$88/$D8         {  mov  al,bl         ;asciify this nibble}
  316.   /$20/$D0         {  and  al,dl         ;mask (constant $0F)}
  317.   /$00/$F0         {  add  al,dh         ;asciify (constant $30)}
  318.   /$3C/$3A         {  cmp  al,$3A        ;ran out of regs!}
  319.   /$72/$02         {  jb   StuffIt       ;<= '9'}
  320.   /$04/$07         {   add al,7          ;bump to 'A'..'F'}
  321.                    {StuffIt:}
  322.   /$AA             {  stosb              ;stuff char in string}
  323.   /$FE/$CD         {  dec  ch            ;done yet?}
  324.   /$75/$ED         {  jnz  Rotate        ;nope, loop until done}
  325.   /$C3             {  ret}
  326.  
  327.                    {Exit:}
  328.   /$1F             {  pop  DS            ;restore}
  329. );
  330.   END;  {of LStr_Hex}
  331.  
  332.  
  333. FUNCTION LHex(VAR long : long_int) : Str12;
  334.   {Converts the long integer into a string, returns it
  335.    as the function (in case you don't have a string variable
  336.    handy to use LStr_Hex).
  337.    Format:  0000:0000  (hi word, then lo word)
  338.    v1.3 recoded in assembler.
  339.   }
  340.   BEGIN
  341. (* In Turbo, 7.9 secs vs assembler's 5.43 secs
  342.     LStr_Hex(long, S);
  343.     LHex := S;
  344. *)
  345.     Inline(
  346.   $1E              {  push DS}
  347.   /$8C/$D0         {  mov  ax,SS}
  348.   /$8E/$C0         {  mov  ES,ax         ;ES=SS}
  349.   /$89/$EF         {  mov  di,bp         ;stack offset}
  350.   /$81/$C7/$08/$00 {  add  di,8          ;where string will begin}
  351.   /$C5/$B6/>LONG   {  lds  si,>long[bp]  ;long ofs}
  352.   /$FC             {  cld                ;from left to right}
  353.   /$B0/$09         {  mov  al,9          ;9 digits for 32-bit}
  354.   /$AA             {  stosb              ;force string len to 9}
  355.   /$B8/$04/$04     {  mov  ax,$0404      ;ah is constant}
  356.   /$89/$C1         {  mov  cx,ax         ;cl=ROL, ch=loop cntr}
  357.   /$BA/$0F/$30     {  mov  dx,$300F      ;2 constants $30, $0F}
  358.   /$8B/$5C/$02     {  mov  bx,[si+2]     ;long.hi}
  359.   /$E8/$0C/$00     {  call Rotate        ;do first integer}
  360.   /$B0/$3A         {  mov  al,$3A        ;":"}
  361.   /$AA             {  stosb              ;stuff in string}
  362.   /$8B/$1C         {  mov  bx,[si]       ;long.lo}
  363.   /$88/$E5         {  mov  ch,ah         ;refresh loop cntr}
  364.   /$E8/$02/$00     {  call Rotate}
  365.   /$EB/$14         {  jmp  short Exit    ;done}
  366.  
  367.                    {Rotate:}
  368.   /$D3/$C3         {  rol  bx,cl         ;get a nibble (4 bytes)}
  369.   /$88/$D8         {  mov  al,bl         ;asciify this nibble}
  370.   /$20/$D0         {  and  al,dl         ;mask (constant $0F)}
  371.   /$00/$F0         {  add  al,dh         ;asciify (constant $30)}
  372.   /$3C/$3A         {  cmp  al,$3A        ;ran out of regs!}
  373.   /$72/$02         {  jb   StuffIt       ;<= '9'}
  374.   /$04/$07         {   add al,7          ;bump to 'A'..'F'}
  375.                    {StuffIt:}
  376.   /$AA             {  stosb              ;stuff char in string}
  377.   /$FE/$CD         {  dec  ch            ;done yet?}
  378.   /$75/$ED         {  jnz  Rotate        ;nope, loop until done}
  379.   /$C3             {  ret}
  380.  
  381.                    {Exit:}
  382.   /$1F             {  pop  DS            ;restore}
  383. );
  384.   END;  {of LHex1}
  385.  
  386.  
  387. FUNCTION AnyNum_Str(VAR num; typ : numtype) : Str64;
  388.   {Returns a string for ANY number (integer, real, long integer).
  389.    Uses the global numtype (inttyp, realtyp, longtyp) to tell the
  390.    function what kinda number you're dealing with.
  391.    Only works with VARs, notice!
  392.    Using global radix, you can set 10 bit or 16 bit (hex).  Haven't set it
  393.    up for any other number bases yet.
  394.   }
  395.   CONST
  396.     BADRADIX = 'Unsupported Radix!';
  397.   VAR
  398.     tlong : long_int;
  399.     S : Str64;
  400.     answer : REAL;
  401.     r : REAL absolute num;
  402.     i : INTEGER absolute num;
  403.     l : long_int absolute num;
  404.   BEGIN {AnyNum_Str}
  405.     S := BADRADIX;  {assume the worst}
  406.     CASE typ OF
  407.       realtyp : CASE radix OF
  408.                   10 : BEGIN
  409.                          IF r = 0 THEN S := '0'
  410.                          ELSE STR(r:20:0,S);
  411.                        END;
  412.                   16 : BEGIN
  413.                          Real_To_Long(r,tlong);  {convert to long}
  414.                          LStr_Hex(tlong,S);      {and to hex string}
  415.                        END;
  416.                   ELSE;  { S := 'Unsupported Radix!';}
  417.                 END;  {case}
  418.       inttyp  : CASE radix OF
  419.                   10 : STR(i:6,S);
  420.                   16 : S := '0000:' + Hex(i);
  421.                   ELSE; { Writeln('Unsupported Radix!');}
  422.                 END;  {case}
  423.       longtyp : CASE radix OF
  424.                   10 : BEGIN
  425.                          answer := long_To_Real(l);
  426.                          IF answer = 0.0 THEN S := '0'
  427.                          ELSE STR(answer:20:0,S);
  428.                        END;
  429.                   16 : LStr_Hex(l, S);
  430.                   ELSE; { Writeln('Unsupported Radix!');}
  431.                 END;  {case}
  432.     END;  {case}
  433.     IF (LENGTH(S) > 0)
  434.     THEN WHILE (S[1] = ' ') DO
  435.       Delete(S,1,1);                    {delete any leading spaces}
  436.     AnyNum_Str := S;                    {return the function}
  437.   END;  {of AnyNum_Str}
  438.  
  439.  
  440. (* Other handy number/string functions *)
  441.  
  442.  
  443. FUNCTION Zero_Padded(S : Str12) : Str12;
  444.   {Pad a string with zeroes .. e.g., if a space, stuff in a '0'.
  445.    The length here is purely arbitrary.
  446.    Works good with left-padded numbers from Long_Str and
  447.    Long_Size_Str.
  448.    This routine won't ADD zeros beyond the length of the original
  449.    left-padded string.  Didn't bother with that since I always
  450.    passed a string left-padded to the length (width) I wanted.
  451.   }
  452.   VAR
  453.     p : INTEGER;
  454.   BEGIN
  455.     p := POS(' ', S);                  {any spaces?}
  456.     WHILE p <> 0 DO BEGIN              {yep, go for it}
  457.       S[p] := '0';                     {stuff a zero in the space}
  458.       p := pos(' ', S);                {and loop through the test again}
  459.     END;
  460.     Zero_Padded := S;                  {return the string}
  461.   END;  {of Zero_Padded}
  462.  
  463.  
  464. FUNCTION Byte32_Str(VAR long : long_int) : Str64;
  465.   {Build a long string of 32 bits from a long integer.
  466.    String is actually 36 chars long.
  467.    v1.3 recoded in assembler
  468.   }
  469.   BEGIN
  470.     Inline(
  471.   $1E              {  push DS          ;save DS}
  472.   /$8C/$D0         {  mov  ax,SS}
  473.   /$8E/$C0         {  mov  ES,ax       ;ES=SS}
  474.   /$89/$EF         {  mov  di,bp       ;point to heap}
  475.   /$81/$C7/$08/$00 {  add  di,8        ;string start}
  476.   /$B8/$24/$00     {  mov  ax,36       ;str length}
  477.   /$26             {  ES:}
  478.   /$88/$05         {  mov  [di],al     ;force length}
  479.   /$01/$C7         {  add  di,ax       ;point to end}
  480.   /$C5/$B6/>LONG   {  lds  si,>long[bp] ;get long addr}
  481.   /$FC             {  cld              ;insure fwd}
  482.   /$AD             {  lodsw            ;long.lo}
  483.   /$8B/$14         {  mov  dx,[si]     ;long.hi}
  484.   /$52             {  push dx          ;save on stack}
  485.   /$BA/$30/$3A     {  mov  dx,$3A30    ;constants in dh,dh}
  486.   /$FD             {  std              ;go backwards}
  487.   /$89/$C3         {  mov  bx,ax       ;need int in bx}
  488.   /$E8/$0A/$00     {  call DoBin       ;go do it}
  489.   /$88/$F0         {  mov  al,dh       ;":" separator}
  490.   /$AA             {  stosb            ;stuff}
  491.   /$AA             {  stosb            ;twice between words}
  492.   /$5B             {  pop  bx          ;get long.hi}
  493.   /$E8/$02/$00     {  call DoBin       ;go do it}
  494.   /$EB/$17         {  jmp  short Done}
  495.                    
  496.                    {DoBin:}
  497.   /$B9/$10/$00     {  mov  cx,16       ;16 chars}
  498.                    {ShLup:}
  499.   /$89/$D8         {  mov  ax,bx       ;ax=decint}
  500.   /$D1/$EB         {  shr  bx,1        ;result=decint shr 1}
  501.   /$24/$01         {  and  al,1        ;remainder=decint AND 1}
  502.   /$00/$D0         {  add  al,dl       ;$30, asciify}
  503.   /$AA             {  stosb            ;stuff char}
  504.   /$80/$F9/$08     {  cmp  cl,8        ;divider every 8 bits}
  505.   /$75/$03         {  jne  Lup         ;nope}
  506.   /$88/$F0         {   mov al,dh       ; ":" divider}
  507.   /$AA             {   stosb           ;stuff}
  508.                    {Lup:}
  509.   /$E2/$ED         {  loop ShLup}
  510.   /$C3             {  ret}
  511.                    
  512.                    {Done:}
  513.   /$FC             {  cld              ;neaten up}
  514.   /$1F             {  pop  DS          ;restore DS}
  515. );
  516.   END;  {of Byte32_Str}
  517.