// Trace info for the Excel 2007 bug 850*77.1+1 = "100001" instead of 65536
// hex is 850*77.1+1 is IEEE754 hex 0x40EFFFFF FFFFFFFF

// data table for ESI
.text:301101B0  A0 64 38 30 A0 64 38 30  13 68 38 30 BF 66 38 30 
.text:301101C0  BF 66 38 30 2B 67 38 30  28 67 38 30 A0 64 38 30 
.text:301101D0  A0 64 38 30 A0 64 38 30  A0 64 38 30 A0 64 38 30 
.text:301101E0  5B 73 38 30 07 66 38 30  02 77 38 30 A0 64 38 30 
.text:301101F0  A0 64 38 30 A0 64 38 30  A0 64 38 30 E6 69 38 30 
.text:30110200  E3 69 38 30 F2 65 38 30  0F 77 38 30 A0 64 38 30 
.text:30110210  A0 64 38 30 A0 64 38 30  A0 64 38 30 A0 64 38 30 
.text:30110220  A0 64 38 30 A0 64 38 30  A0 64 38 30 A0 64 38 30 
.text:30110230  A0 64 38 30 A0 64 38 30  13 68 38 30 33 67 38 30 
.text:30110240  33 67 38 30 2B 67 38 30  28 67 38 30 A0 64 38 30 
.text:30110250  A0 64 38 30 A0 64 38 30  A0 64 38 30 A0 64 38 30 
.text:30110260  5B 73 38 30 07 66 38 30  02 77 38 30 A0 64 38 30 
.text:30110270  A0 64 38 30 A0 64 38 30  A0 64 38 30 E6 69 38 30 
.text:30110280  E3 69 38 30 F2 65 38 30  0F 77 38 30 A0 64 38 30 
.text:30110290  A0 64 38 30 A0 64 38 30  A0 64 38 30 A0 64 38 30 
.text:301102A0  A0 64 38 30 A0 64 38 30  A0 64 38 30 A0 64 38 30 
.text:301102B0  A0 64 38 30 A0 64 38 30  13 68 38 30 33 67 38 30 
.text:301102C0  33 67 38 30 2B 67 38 30  28 67 38 30 7F 13 7F 1F 



// Divisor table located at text:301102D0
// values are 1,10,100,1000,10000,65535
tbl1[] = {01 00 00 00 0A 00 00 00  64 00 00 00 E8 03 00 00 10 27 00 00 FF FF 00 00 }

.text:301102F0  56 8B F1 74 24 57 68 A0  49 DF 30 8D 7E FC FF 37 
.text:30110300  6A 0C 56 E8 04 45 CE 00  F6 C3 01 74 07 57 E8 1D  
.text:30110310  B2 F0 FF 59 8B C7 5F EB  13 E8 82 46 CE 00 F6 C3 
.text:30110320  01 74 07 56 E8 07 B2 F0  FF 59 8B C6 5E 5B C2 04  
.text:30110330  00 90 90 90 3C 03 11 30  E8 02 11 30 00 00 00 00 
.text:30110340  00 00 00 00 00 00 00 00  28 7B E5 30 0C 3F 10 30 
.text:30110350  33 C0 E9 79 B5 F1 FF 33  F6 E9 31 B4 F1 FF 33 F6 
.text:30110360  E9 BB B7 F1 FF 49 0F 85  52 B2 F1 FF E9 AF B7 F1 


// Divisor table at 301102D0[] = {0xFFFF, 0x2701, 0x3E8, 0x64, 0x10, 0x1}
// in decimal       301102D0[] = { 65535,  10000,  1000,  100,   10,   1}
.text:301102D0  01 00 00 00 0A 00 00 00  64 00 00 00 E8 03 00 00   // 
.text:301102E0  10 27 00 00 FF FF 00 00  53 8A 5C 24 08 F6 C3 02   // these two lines are the relevant table for 850*77.1+1

// table for constants added into value?!
.text:300663B0  00 B9 15 00 00 00 2B CB  8B D8 D3 E8 F6 D9 0F A5
.text:300663C0  D3 D3 E2 8B CA 83 EE 04  3B 86 D0 02 11 30 73 07
.text:300663D0  66 FF 4F 20 83 EE 04 85  C9 0F 84 C4 00 00 00 03
.text:300663E0  8E F7 63 06 30 83 D3 00  0F 82 89 80 0D 00 E9 B0

.text:300663F0  00 00 00 07 24 00 00 49  68 01 00 E1 12 0E 00 CC 
.text:30066400  BC 8C 00 F8 5F 7F 05 B3  BF F9 36 55 8B EC 51 51 // code uses 0x36F9BFB3 = 922 337 203
.text:30066410  56 33 F6 39 75 08 57 0F  84 F1 0A 35 00 83 7D 08

.text:30066420  04 0F 85 A1 09 35 00 56  E8 DE F6 FF FF 85 C0 0F
.text:30066430  85 50 6C 18 00 83 3D 80  71 E5 30 02 0F 84 99 0A
.text:30066440  35 00 39 35 80 B6 E7 30  0F 85 28 6C 18 00 39 35
.text:30066450  5C B6 E7 30 0F 85 2B 6C  18 00 8B 0D 8C D6 EF 30
.text:30066460  A0 56 D6 EF 30 33 FF D1  E9 47 23 CF F6 D8 1B C0
.text:30066470  85 C1 0F 85 0D 6C 18 00  FF 35 C8 CB EF 30 6A 06
.text:30066480  58 E8 C5 21 FD FF 85 C0  0F 85 F7 6B 18 00 E8 9F

.text:300663F0  00 00 00 07 24 00 00 49  68 01 00 E1 12 0E 00 CC 
.text:30066400  BC 8C 00 F8 5F 7F 05 B3  BF F9 36 55 8B EC 51 51 // code uses 0x36F9BFB3 = 922 337 203
.text:30066410  56 33 F6 39 75 08 57 0F  84 F1 0A 35 00 83 7D 08


// table located at .text:300663F7
// code uses 0x36F9BFB3 = 922 337 203
tbl2[] = {49 68 01 00 E1 12 0E 00 CC BC 8C 00 F8 5F 7F 05 B3 BF F9 36 55 8B EC 51 51};

// Last byte of floating value causes add from table to ECX, the offending values are exactly those that overflow.
// Question - why add this constant? Can a change fix anything?
0xFF -> 0xF8000000 + 0x36F9BFB3 = 0x12EF9BFB3
0xFE -> 0xF0000000 + 0x36F9BFB3 = 0x126F9BFB3
0xFD -> 0xE8000000 + 0x36F9BFB3 = 0x11EF9BFB3
0xFC ->	0xE0000000 + 0x36F9BFB3 = 0x116F9BFB3
0xFB -> 0xD8000000 + 0x36F9BFB3 = 0x10EF9BFB3
0xFA -> 0xD0000000 + 0x36F9BFB3 = 0x106F9BFB3
0xF9 ->	0xC8000000 + 0x36F9BFB3 = 0x0FEF9BFB3 // NO CARRY!
0xF8 -> 0xC0000000 + 0x36F9BFB3 = 0x0F6F9BFB3 // NO CARRY!


TempFormat definition
.text:30066344 ; FUNCTION CHUNK AT .text:30066637 SIZE 00000032 BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:30136796 SIZE 0000000B BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:3013B3A6 SIZE 00000019 BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:3013C232 SIZE 0000007D BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:3013CCE3 SIZE 0000000B BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:3013E477 SIZE 0000001F BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:30150A6E SIZE 0000009E BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:301ED076 SIZE 00000016 BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:30218285 SIZE 00000008 BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:30389A54 SIZE 0000004C BYTES
.text:30066344 ; FUNCTION CHUNK AT .text:303B6DC8 SIZE 00000156 BYTES
.text:30066344

// disassembly near the start of the offending function
.text:30066340  5D C2 08 00 C7 47 1E 00  00 00 00 8B 46 04 8B D0
.text:30066350  25 00 00 F0 7F 0F 84 29  E8 0C 00 C1 E8 14 2D FE
.text:30066360  03 00 00 8B D8 69 C0 21  9A 00 00 D1 F8 81 E2 00


// START
CS=1B DS=23 ES=23 FS=3B GS=0 SS=23 EAX=FFFE EBX=FFED061E ECX=F 
EDX=12F4C0 ESI=12F548 EDI=12F9E2 EBP=12F4C4 ESP=12F49C EFL=202  

ESI - points to the floating value V
EDI - points to some data structure

Format mov     dword ptr [edi+1Eh], 0                                            // 
       mov     eax, [esi+4]                         EAX=40EFFFFF                 // load high part of double 850*77.1+1
       mov     edx, eax                             EDX=40EFFFFF                 // store a copy
       and     eax, 7FF00000h                       EAX=40E00000 PF=1            // mask out to get exponent only
       jz      nullsub_33                                                        // if 0 exponent, bail out (returns?)
       shr     eax, 14h                             EAX=40E PF=0 AF=1            // move to low word
       sub     eax, 3FEh                            EAX=10 AF=0                  // subtract 1022, denormalized number bias?, note EAX = 16d, 2^16 = 65536
       mov     ebx, eax                             EBX=10                       // save this - 2^EBX is larger than the float value
       imul    eax, 9A21h                           EAX=9A210                    // =39457 = 2^17 * log2  rounded up - computes needed digits in base 10
       sar     eax, 1                               EAX=4D108 AF=1               // scale result
       and     edx, 80000000h                       EDX=0 PF=1 AF=0 ZF=1         // get sign
       add     eax, 40010000h                       EAX=4005D108 PF=0 ZF=0       // ??
       and     eax, FFFF0000h                       EAX=40050000 PF=1            //
       or      edx, eax                             EDX=40050000                 // replace sign
       mov     [edi+1Eh], edx                                                    // save value
       shr     eax, 10h                             EAX=4005 AF=1                // integer part - number of decimal digits
       sub     eax, 4000h                           EAX=5 AF=0                   // EAX = # decimal digits before decimal - value to determine table location later
       or      ebx, ebx                             PF=0                         // see if true exponent was > 128 ???
       jl      loc_3013C232                                                      
       cmp     ebx, 10h                             PF=1 ZF=1                    // number of bits is at most 10, so go to faster routine (we can use 16 bit math?)
       jle     short tag1                                                        // if in this cutoff range, format special
tag1   push    edi                                  ESP=12F498                   // save these
       push    ecx                                  ESP=12F494                   
       mov     edx, [esi]                           EDX=FFFFFFFF                 // get low part of the double value
       mov     esi, [esi+4]                         ESI=40EFFFFF                 // and the high part
       xchg    eax, esi                             EAX=40EFFFFF ESI=5           // EAX = high value, ESI = nunmber of decimal digits, used for table index
       shl     esi, 2                               ESI=14 AF=1 ZF=0             // 2 bytes per divisor table entry
       and     eax, 0FFFFFh                         EAX=FFFFF AF=0               // get mantissa high bits
       or      eax, 100000h                         EAX=1FFFFF                   // prepend 1 bit since normalized and not stored
       mov     ecx, 15h                             ECX=15                       // shift up to 15 bits
       sub     ecx, ebx                             ECX=5                        // final shift value
       mov     ebx, eax                             EBX=1FFFFF                   // make a copy for later shift
       shr     eax, cl                              EAX=FFFF CF=1 AF=1           // shift down the bits
       neg     cl                                   ECX=FB PF=0 SF=1             // prepare to shift other way?
       shld    ebx, edx, cl                         EBX=FFFFFFFF PF=1            // get some low mantissa bits from edx
       shl     edx, cl                              EDX=F8000000                 // shift these up. Note 65536-2^(-25,-36,-37) differs here: 0xC8000000
       mov     ecx, edx                             ECX=F8000000                 // and place here. Mantissa in EAX:EBX:ECX
       sub     esi, 4                               ESI=10 CF=0 PF=0 AF=0 SF=0   // divisor table start
       cmp     eax, ds:dword_301102D0[esi]                                       // (all variations take this?)
       jnb     short tag2                                                
  
tag2   test    ecx, ecx                             PF=1 SF=1                    
       jz      loc_300664A3                                                      
       add     ecx, dword ptr tbl2[esi]             ECX=2EF9BFB3 CF=1 PF=0 SF=0  // adds 0x36F9BFB3 = 922,337,203? Why? Causes overflow on exactly those 6 floating values ending in 0xFF-0xFA, 0xF9 does not carry!
       adc     ebx, 0                               EBX=0 PF=1 AF=1 ZF=1         // rollover - incorrect?
       jb      tag3                                                              // close to an integer, branch accordingly. some correct ones diverge here!?
       xor     ecx, ecx                             ECX=0 CF=0 AF=0              
       mov     edx, 1                               EDX=1                        
       inc     eax                                  EAX=10000 AF=1 ZF=0          // note this is 65536?!
       jz      skip                                                      
       cmp     eax, ds:dword_301102D4[esi]          PF=0                         // check against max value 0xFFFF for this branch
       jb      loc_300664A3                                                      // EAX too big?
       jmp     tag4                                                              // jump to some fixup routine??
     
tag4   cmp     eax, 0FFFFFFFFh                      CF=1                         
       jz      Digits                                                            //
       inc     word ptr [edi+20h]                   PF=1 AF=0                    // set some internal counter
       add     esi, 4                               ESI=14 CF=0                  // move table value (incorrect?!)
       jmp     Digits                                                            // jump to digit printing loop

Digits xor     edx, edx                             EDX=0 ZF=1                   // EAX holds integer part, EDX holds remainder
skip   div     ds:dword_301102D0[esi]               EAX=1 EDX=1 PF=0 AF=1 ZF=0   // EDX:EAX / FFFF -> EAX, remainder EDX - ERROR!
       or      al, 30h                              EAX=31 AF=0                  // text for '1'
       mov     [edi], al                                                         // save character here 
       mov     byte ptr [edi+1], 0                                               // Unicode - place a 0 here for two byte char
       add     edi, 2                               EDI=12F9E4 PF=1              // next char position
       or      edx, edx                             PF=0                         // see if any remainder
       jz      tag6                                                              // exit if no remainder
       mov     eax, edx                             EAX=1                        // move remiander to EAX
       sub     esi, 4                               ESI=10                       // move divisor table pointer
       ja      short Digits                                                      // and loop if table not empty

Digits xor     edx, edx                             EDX=0 PF=1 ZF=1              // EAX holds integer part, EDX holds remainder
skip   div     ds:dword_301102D0[esi]               EAX=0 EDX=1 PF=0 AF=1 ZF=0   // EDX:EAX / x2710 = 0:1		 x2710 = 10000
       or      al, 30h                              EAX=30 PF=1 AF=0             // text for '0'
       mov     [edi], al                                                         // save character here
       mov     byte ptr [edi+1], 0                                               // Unicode - place a 0 here for two byte char
       add     edi, 2                               EDI=12F9E6 PF=0              // next char position
       or      edx, edx                                                          // see if any remainder 
       jz      tag6                                                              // exit if no remainder
       mov     eax, edx                             EAX=1                        // move remiander to EAX
       sub     esi, 4                               ESI=C PF=1 AF=1              // move divisor table pointer
       ja      short Digits													  // and loop if table not empty

Digits xor     edx, edx                             EDX=0 AF=0 ZF=1              // EAX holds integer part, EDX holds remainder 
skip   div     ds:dword_301102D0[esi]               EAX=0 EDX=1 PF=0 AF=1 ZF=0   // EDX:EAX / x3E8 = 0:1	  x3E8 = 1000
       or      al, 30h                              EAX=30 PF=1 AF=0             // text for '0'
       mov     [edi], al                                                         // save character here
       mov     byte ptr [edi+1], 0                                               // Unicode - place a 0 here for two byte char
       add     edi, 2                               EDI=12F9E8                   // next char position
       or      edx, edx                             PF=0                         // see if any remainder
       jz      tag6                                                              // exit if no remainder
       mov     eax, edx                             EAX=1                        // move remiander to EAX
       sub     esi, 4                               ESI=8                        // move divisor table pointer
       ja      short Digits													  // and loop if table not empty
     
Digits xor     edx, edx                             EDX=0 PF=1 ZF=1              // EAX holds integer part, EDX holds remainder
skip   div     ds:dword_301102D0[esi]               EAX=0 EDX=1 PF=0 AF=1 ZF=0   // EDX:EAX / x64 = 0:1	x64 = 100
       or      al, 30h                              EAX=30 PF=1 AF=0             // text for '0'
       mov     [edi], al                                                         // save character here
       mov     byte ptr [edi+1], 0                                               // Unicode - place a 0 here for two byte char
       add     edi, 2                               EDI=12F9EA PF=0              // next char position
       or      edx, edx                                                          // see if any remainder
       jz      tag6                                                              // exit if no remainder
       mov     eax, edx                             EAX=1                        // move remiander to EAX
       sub     esi, 4                               ESI=4                        // move divisor table pointer
       ja      short Digits													  // and loop if table not empty

Digits xor     edx, edx                             EDX=0 PF=1 ZF=1              // EAX holds integer part, EDX holds remainder
skip   div     ds:dword_301102D0[esi]               EAX=0 EDX=1 PF=0 AF=1 ZF=0   // EDX:EAX / x0A = 0:1
       or      al, 30h                              EAX=30 PF=1 AF=0             // text for '0'
       mov     [edi], al                                                         // save character here
       mov     byte ptr [edi+1], 0                                               // Unicode - place a 0 here for two byte char
       add     edi, 2                               EDI=12F9EC PF=0              // next char position
       or      edx, edx                                                          // see if any remainder
       jz      tag6                                                              // exit if no remainder
       mov     eax, edx                             EAX=1                        // move remiander to EAX
       sub     esi, 4                               ESI=0 PF=1 ZF=1              // move divisor table pointer
       ja      short Digits													  // and loop if table not empty

       test    eax, 0FFh                            PF=0 ZF=0                    // final digit amount
       jz      tag6                                                      
       jmp     tag5                                                      
tag5   or      al, 30h                              EAX=31                       // text for '1'
       mov     [edi], al                                                         // save character here
       mov     byte ptr [edi+1], 0                                               // Unicode - place a 0 here for two byte char
       add     edi, 2                               EDI=12F9EE PF=1              // next char position
   
tag6   mov     eax, ebx                             EAX=0                        
       or      eax, ecx                             ZF=1                         
       jnz     loc_30150AD8                                                      
       mov     word ptr [edi], 30h ; '0'                                         // write another '0' character
       pop     ecx                                  ECX=F ESP=12F498             // clean stack
       pop     ebx                                  EBX=12F9E2 ESP=12F49C        
       mov     edx, edi                             EDX=12F9EE                   
       sub     edx, ebx                             EDX=C ZF=0                   // 
       sar     edx, 1                               EDX=6 AF=1                   //

tag7   mov     eax, [ebx+1Eh]                       EAX=40060000                 
       and     eax, 0FFFF0000h                      AF=0                         
       or      eax, edx                             EAX=40060006                 
       mov     [ebx+1Eh], eax                                                    
       and     eax, 7FFFFFFFh                                                    
       sub     eax, 40000000h                       EAX=60006                    // number of digits?
       ror     eax, 10h                                                          
       retn                                         ESP=12F4A0                   // and we're out
   
// end
