home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / dos / fraktale / frasr192.exe / BIGFLTA.ASM < prev    next >
Encoding:
Assembly Source File  |  1995-02-03  |  22.4 KB  |  652 lines

  1. ; bigflta.asm - asm routines for bigfloats
  2. ; Wesley Loewer's Big Numbers.
  3.  
  4. .MODEL medium, c
  5.  
  6. ifdef ??version
  7.    ideal
  8. TYPEDEF bf_t far ptr byte
  9. TYPEDEF bn_t far ptr byte
  10.    masm
  11.    masm51
  12.    quirks
  13. extern equ extrn
  14. real10 equ tbyte
  15. REAL10 equ tbyte
  16. sword  equ word
  17. ; this is a horrible kludge
  18. ; if more invokes are added to the code then this may fail
  19. invoke macro a,b
  20.    call      a, b
  21. endm
  22. endif
  23.  
  24. ifdef ??version
  25. extrn clear_bf:far
  26. extrn neg_a_bf:far
  27. endif
  28.  
  29. ifndef ??version
  30.  
  31. bf_t TYPEDEF far ptr byte   ; far pointer to bigfloat array
  32.  
  33. ; testing
  34. bn_t TYPEDEF far ptr byte   ; far pointer to bigfloat array
  35.  
  36. endif ; ??version
  37.  
  38. .DATA
  39.  
  40. extern cpu:word, fpu:word
  41. extern bflength:word
  42.  
  43. ; testing
  44. extern bnlength:word, intlength:word
  45.  
  46. .CODE
  47.  
  48. ifndef ??version
  49. clear_bf PROTO, n:bf_t
  50. neg_a_bf PROTO, n:bf_t
  51. endif
  52.  
  53. .8086
  54. .8087
  55.  
  56. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  57. ; LDBL extract_256(LDBL f, int *exp_ptr)
  58. ;
  59. ; extracts the mantissa and exponant of f
  60. ; finds m and n such that 1<=|m|<256 and f = m*256^n
  61. ; n is stored in *exp_ptr and m is returned, sort of like frexp()
  62.  
  63. extract_256   PROC f:real10, exp_ptr: ptr sword
  64. local  expon:sword, exf:real10, tmp_word:word
  65.  
  66.         fld     f               ; f
  67.         ftst                    ; test for zero
  68.         fstsw   tmp_word
  69.     fwait
  70.     mov     ax,tmp_word
  71.         sahf
  72.         jnz     not_zero        ; proceed
  73.  
  74.         mov     bx, exp_ptr
  75.         mov     word ptr [bx], 0    ; save = in *exp_ptr
  76.         jmp     bottom          ; f, which is zero, is already on stack
  77.  
  78. not_zero:
  79.  
  80. ; since a key fpu operation, fxtract, is not emulated by the MS floating
  81. ; point library, separate code is included under use_emul:
  82.         cmp     fpu, 0
  83.         je      use_emul
  84.  
  85.                                 ; f is already on stack
  86.         fxtract                 ; mant exp, where f=mant*2^exp
  87.         fxch                    ; exp mant
  88.         fistp   expon           ; mant
  89.         fwait
  90.         mov     ax, expon
  91.         mov     dx, ax          ; make copy for later use
  92.  
  93.         cmp     ax, 0           ;
  94.         jge     pos_exp         ; jump if exp >= 0
  95.  
  96.                                 ; exp is neg, adjust exp
  97.         add     ax, 8           ; exp+8
  98.  
  99. pos_exp:
  100. ; adjust mantissa
  101.         and     ax, 7           ; ax mod 8
  102.         jz      adjust_exponent ; don't bother with zero adjustments
  103.         mov     expon, ax       ; use expon as a temp var
  104.         fild    expon           ; exp mant
  105.  
  106.         fxch                    ; mant exp
  107.         fscale                  ; mant*2^exp exp
  108.         fstp    st(1)           ; mant*2^exp (store in 1 and pop)
  109.  
  110. adjust_exponent:
  111.         mov     cl, 3
  112.         sar     dx, cl          ; exp / 8
  113.         mov     bx, exp_ptr
  114.         mov     [bx], dx        ; save in *exp_ptr
  115.  
  116.         fwait
  117.         jmp     bottom
  118.  
  119.  
  120. use_emul:
  121. ; emulate above code by direct manipulation of 80 bit floating point format
  122.                                     ; f is already on stack
  123.         fstp    exf
  124.  
  125.         mov     ax, word ptr exf+8  ; get word with the exponent in it
  126.         mov     dx, ax              ; make copy for later use
  127.  
  128.         and     dx, 8000h           ; keep just the sign bit
  129.         or      dx, 3FFFh           ; 1<=f<2
  130.  
  131.         and     ax, 7FFFh           ; throw away the sign bit
  132.         sub     ax, 3FFFh           ; unbiased -> biased
  133.         mov     bx, ax
  134.         cmp     bx, 0
  135.         jge     pos_exp_emul
  136.         add     bx, 8               ; adjust negative exponent
  137. pos_exp_emul:
  138.         and     bx, 7               ; bx mod 8
  139.         add     dx, bx
  140.         mov     word ptr exf+8, dx  ; put back word with the exponent in it
  141.  
  142.         mov     cl, 3
  143.         sar     ax, cl              ; div by 8,  2^(8n) = 256^n
  144.         mov     bx, exp_ptr
  145.         mov     [bx], ax            ; save in *exp_ptr
  146.  
  147.         fld     exf                 ; for return value
  148.  
  149. bottom:
  150.         ; unlike float and double, long double is returned on fpu stack
  151.         ret
  152. extract_256   ENDP
  153.  
  154. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  155. ; LDBL scale_256( LDBL f, int n );
  156. ; calculates and returns the value of f*256^n
  157. ; sort of like ldexp()
  158. ;
  159. ; n must be in the range -2^12 <= n < 2^12 (2^12=4096),
  160. ; which should not be a problem
  161.  
  162. scale_256   PROC f:real10, n: sword
  163.  
  164.         cmp     n, 0
  165.         jne     non_zero
  166.         fld     f
  167.         jmp     bottom          ; don't bother with scales of zero
  168.  
  169. non_zero:
  170.         mov     cl, 3
  171.         shl     n, cl           ; 8n
  172.         fild    n               ; 8n
  173.         fld     f               ; f 8n
  174. ; the fscale range limits for 8087/287 processors won't be a problem here
  175.         fscale                  ; new_f=f*2^(8n)=f*256^n  8n
  176.         fstp    st(1)           ; new_f
  177.  
  178. bottom:
  179.         ; unlike float and double, long double is returned on fpu stack
  180.         ret
  181. scale_256   ENDP
  182.  
  183. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  184. ; LDBL bftofloat(bf_t n);
  185. ; converts a bf number to a 10 byte real
  186. ;
  187. bftofloat   PROC USES di si, n:bf_t
  188.    LOCAL value[11]:BYTE   ; 11=10+1
  189.  
  190.       mov      cx, 9                   ; need up to 9 bytes
  191.       cmp      bflength, 10            ; but no more than bflength-1
  192.       jae      movebytes_set
  193.       mov      cx, bflength            ; bflength is less than 10
  194.       dec      cx                      ; cx=movebytes=bflength-1, 1 byte padding
  195. movebytes_set:
  196.  
  197.       cmp     cpu, 386              ; check cpu
  198.       je      use_32_bit            ; use faster 32 bit code if possible
  199.  
  200. ; 16 bit code
  201.       ; clear value
  202.       mov      word ptr value[0], 0
  203.       mov      word ptr value[2], 0
  204.       mov      word ptr value[4], 0
  205.       mov      word ptr value[6], 0
  206.       mov      word ptr value[8], 0
  207.       mov      byte ptr value[10], 0
  208.  
  209.       ; copy bytes from n to value
  210.       lea      di, value+9
  211.       sub      di, cx               ; cx holds movebytes
  212.       mov      ax, ds               ; save ds
  213.       mov      es, ax               ; also move to es
  214.       mov      bx, bflength
  215.       dec      bx
  216.       sub      bx, cx               ; cx holds movebytes
  217.       lds      si, n
  218.       add      si, bx               ; n+bflength-1-movebytes
  219.       rep movsb
  220.       mov      bl, ds:[si]          ; save sign byte, si now points to it
  221.       inc      si                   ; point to exponent
  222.       mov      dx, ds:[si]          ; use dx as exponent
  223.       mov      ds, ax               ; restore ds
  224.       mov      cl, 3                ; put exponent (dx) in base 2
  225.       shl      dx, cl               ; 256^n = 2^(8n)
  226.  
  227.       ; adjust for negative values
  228.       and      bl, 10000000b           ; isolate sign bit
  229.       jz       not_neg_16
  230.       neg      word ptr value[0]       ; take the negative of the 9 byte number
  231.       cmc                              ; toggle carry flag
  232.       not      word ptr value[2]
  233.       adc      word ptr value[2], 0
  234.       not      word ptr value[4]
  235.       adc      word ptr value[4], 0
  236.       not      word ptr value[6]
  237.       adc      word ptr value[6], 0
  238.       not      byte ptr value[8]       ; notice this last one is byte ptr
  239.       adc      byte ptr value[8], 0
  240. not_neg_16:
  241.  
  242.       cmp      byte ptr value[8], 0          ; test for 0
  243.       jz       return_zero
  244.  
  245.       ; Shift until most signifcant bit is set.
  246. top_shift_16:
  247.       test     byte ptr value[8], 10000000b  ; test msb
  248.       jnz      bottom_shift_16
  249.       dec      dx                      ; decrement exponent
  250.       shl      word ptr value[0], 1    ; shift left the 9 byte number
  251.       rcl      word ptr value[2], 1
  252.       rcl      word ptr value[4], 1
  253.       rcl      word ptr value[6], 1
  254.       rcl      byte ptr value[8], 1    ; notice this last one is byte ptr
  255.       jmp      top_shift_16
  256. bottom_shift_16:
  257.  
  258.       ; round last byte
  259.       cmp      byte ptr value[0], 80h  ;
  260.       jb       bottom                  ; no rounding necessary
  261.       add      word ptr value[1], 1
  262.       adc      word ptr value[3], 0
  263.       adc      word ptr value[5], 0
  264.       adc      word ptr value[7], 0
  265.       jnc      bottom
  266.  
  267.       ; to get to here, the pattern was rounded from +FFFF...
  268.       ; to +10000... with the 1 getting moved to the carry bit
  269.       jmp      rounded_past_end
  270.  
  271. return_zero:
  272.       fldz
  273.       jmp      return
  274.  
  275. use_32_bit:
  276. .386
  277.       ; clear value
  278.       mov      dword ptr value[0], 0
  279.       mov      dword ptr value[4], 0
  280.       mov      word ptr value[8],  0
  281.       mov      byte ptr value[10], 0
  282.  
  283.       ; copy bytes from n to value
  284.       lea      di, value+9
  285.       sub      di, cx               ; cx holds movebytes
  286.       mov      ax, ds               ; save ds
  287.       mov      es, ax               ; also move to es
  288.       mov      bx, bflength
  289.       dec      bx
  290.       sub      bx, cx               ; cx holds movebytes
  291.       lds      si, n
  292.       add      si, bx               ; n+bflength-1-movebytes
  293.       rep movsb
  294.       mov      bl, ds:[si]          ; save sign byte, si now points to it
  295.       inc      si                   ; point to exponent
  296.       mov      dx, ds:[si]          ; use dx as exponent
  297.       mov      ds, ax               ; restore ds
  298.       shl      dx, 3                ; 256^n = 2^(8n)
  299.  
  300.       ; adjust for negative values
  301.       and      bl, 10000000b           ; determine sign
  302.       jz       not_neg_32
  303.       neg      dword ptr value[0]      ; take the negative of the 9 byte number
  304.       cmc                              ; toggle carry flag
  305.       not      dword ptr value[4]
  306.       adc      dword ptr value[4], 0
  307.       not      byte ptr value[8]       ; notice this last one is byte ptr
  308.       adc      byte ptr value[8], 0
  309. not_neg_32:
  310.  
  311.       cmp      byte ptr value[8], 0          ; test for 0
  312.       jz       return_zero
  313.  
  314.       ; Shift until most signifcant bit is set.
  315. top_shift_32:
  316.       test     byte ptr value[8], 10000000b  ; test msb
  317.       jnz      bottom_shift_32
  318.       dec      dx                      ; decrement exponent
  319.       shl      dword ptr value[0], 1   ; shift left the 9 byte number
  320.       rcl      dword ptr value[4], 1
  321.       rcl      byte ptr value[8], 1    ; notice this last one is byte ptr
  322.       jmp      top_shift_32
  323. bottom_shift_32:
  324.  
  325.       ; round last byte
  326.       cmp      byte ptr value[0], 80h  ;
  327.       jb       bottom                  ; no rounding necessary
  328.       add      dword ptr value[1], 1
  329.       adc      dword ptr value[5], 0
  330.       jnc      bottom
  331.  
  332.       ; to get to here, the pattern was rounded from +FFFF...
  333.       ; to +10000... with the 1 getting moved to the carry bit
  334. rounded_past_end:
  335. .8086 ; used in 16 it code as well
  336.       mov      byte ptr value[8], 10000000b
  337.       inc      dx                      ; adjust the exponent
  338.  
  339. bottom:
  340. .8086
  341.       ; adjust exponent
  342.       add      dx, 3FFFh+7             ; unbiased -> biased, + adjusted
  343.       or       dh, bl                  ; set sign bit if set
  344.       mov      word ptr value[9], dx
  345.  
  346.       ; unlike float and double, long double is returned on fpu stack
  347.       fld      real10 ptr value[1]    ; load return value
  348. return:
  349.       ret
  350.  
  351. bftofloat   endp
  352.  
  353. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  354. ; LDBL floattobf(bf_t n, LDBL f);
  355. ; converts a 10 byte real to a bf number
  356. ;
  357. floattobf   PROC USES di si, n:bf_t, f:REAL10
  358.    LOCAL value[9]:BYTE   ; 9=8+1
  359. ; I figured out a way to do this with no local variables,
  360. ; but it's not worth it.
  361.  
  362.       invoke   clear_bf, n
  363.  
  364.       ; check to see if f is 0
  365.       cmp      byte ptr f[7], 0        ; f[7] can only be 0 if f is 0
  366.       jz       return                  ; if f is 0, bailout now
  367.  
  368.       mov      cx, 9                   ; need up to 9 bytes
  369.       cmp      bflength, 10            ; but no more than bflength-1
  370.       jae      movebytes_set
  371.       mov      cx, bflength            ; bflength is less than 10
  372.       dec      cx                      ; movebytes = bflength-1, 1 byte padding
  373. movebytes_set:
  374.  
  375.       cmp     cpu, 386              ; check cpu
  376.       je      use_32_bit            ; use faster 32 bit code if possible
  377.  
  378. ; 16 bit code
  379.       ; copy bytes from f's mantissa to value
  380.       mov      byte ptr value[0], 0    ; clear least sig byte
  381.       mov      ax, word ptr f[0]
  382.       mov      word ptr value[1], ax
  383.       mov      ax, word ptr f[2]
  384.       mov      word ptr value[3], ax
  385.       mov      ax, word ptr f[4]
  386.       mov      word ptr value[5], ax
  387.       mov      ax, word ptr f[6]
  388.       mov      word ptr value[7], ax
  389.  
  390.       ; get exponent in dx
  391.       mov      dx, word ptr f[8]       ; location of exponent
  392.       and      dx, 7FFFh               ; remove sign bit
  393.       sub      dx, 3FFFh+7             ; biased -> unbiased, + adjust
  394.  
  395.       ; Shift down until exponent is a mult of 8 (2^8n=256n)
  396. top_shift_16:
  397.       test     dx, 111b                ; expon mod 8
  398.       jz       bottom
  399.       inc      dx                      ; increment exponent
  400.       shr      word ptr value[7], 1    ; shift right the 9 byte number
  401.       rcr      word ptr value[5], 1
  402.       rcr      word ptr value[3], 1
  403.       rcr      word ptr value[1], 1
  404.       rcr      byte ptr value[0], 1    ; notice this last one is byte ptr
  405.       jmp      top_shift_16
  406.  
  407.  
  408. use_32_bit:
  409. .386
  410.       ; copy bytes from f's mantissa to value
  411.       mov      byte ptr value[0], 0    ; clear least sig byte
  412.       mov      eax, dword ptr f[0]
  413.       mov      dword ptr value[1], eax
  414.       mov      eax, dword ptr f[4]
  415.       mov      dword ptr value[5], eax
  416.  
  417.       ; get exponent in dx
  418.       mov      dx, word ptr f[8]       ; location of exponent
  419.       and      dx, 7FFFh               ; remove sign bit
  420.       sub      dx, 3FFFh+7             ; biased -> unbiased, + adjust
  421.  
  422.       ; Shift down until exponent is a mult of 8 (2^8n=256n)
  423. top_shift_32:
  424.       test     dx, 111b                ; expon mod 8
  425.       jz       bottom
  426.       inc      dx                      ; increment exponent
  427.       shr      dword ptr value[5], 1   ; shift right the 9 byte number
  428.       rcr      dword ptr value[1], 1
  429.       rcr      byte ptr value[0], 1    ; notice this last one is byte ptr
  430.       jmp      top_shift_32
  431.  
  432. bottom:
  433. .8086
  434.       ; Don't bother rounding last byte as it would only make a difference
  435.       ; when bflength < 9, and then only on the last bit.
  436.  
  437.       ; move data into place, from value to n
  438.       lea      si, value+9
  439.       sub      si, cx               ; cx holds movebytes
  440.       les      di, n
  441.       add      di, bflength
  442.       dec      di
  443.       sub      di, cx               ; cx holds movebytes
  444.       rep movsb
  445.       inc      di
  446.       mov      cl, 3
  447.       sar      dx, cl               ; divide expon by 8, 256^n=2^8n
  448.       mov      word ptr es:[di], dx ; store exponent
  449.  
  450.       ; get sign
  451.       test     byte ptr f[9], 10000000b           ; test sign bit
  452.       jz       not_negative
  453.       invoke   neg_a_bf, n
  454. not_negative:
  455. return:
  456.       les      ax, n                   ; load es again in case f was 0
  457.       mov      dx, es                  ; return r in dx:ax
  458.       ret
  459. floattobf   endp
  460.  
  461. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  462. ; LDBL bntofloat(bf_t n);
  463. ; converts a bn number to a 10 byte real
  464. ; (the most speed critical of these to/from float routines)
  465. bntofloat   PROC USES di si, n:bn_t
  466.    LOCAL value[11]:BYTE   ; 11=10+1
  467.  
  468.       ; determine the most significant byte, not 0 or FF
  469.       les      si, n
  470.       dec      si
  471.       add      si, bnlength            ; n+bnlength-1
  472.       mov      bl, es:[si]             ; top byte
  473.       mov      cx, bnlength            ; initialize cx with full bnlength
  474.       cmp      bl, 0                   ; test top byte against 0
  475.       je       determine_sig_bytes
  476.       cmp      bl, 0FFh                ; test top byte against -1
  477.       jne      sig_bytes_determined
  478.  
  479. determine_sig_bytes:
  480.       dec      cx                      ; now bnlength-1
  481. top_sig_byte:
  482.       dec      si                      ; previous byte
  483.       cmp      es:[si], bl             ; does it have the right stuff?
  484.       jne      sig_bytes_determined    ; (ie: does it match top byte?)
  485.       loop     top_sig_byte            ; decrement cx and repeat
  486.  
  487. ; At this point, it must be 0 with no sig figs at all
  488. ; or -1/(256^bnlength), one bit away from being zero.
  489.       cmp      bl, 0                   ; was it zero?
  490.       jz       return_zero             ; yes
  491.                                        ; no, it was a very small negative
  492.       mov      ax, intlength
  493.       sub      ax, bnlength
  494.       mov      cl, 3
  495.       shl      ax, cl                  ; 256^n=2^8n, now more like movebits
  496.       add      ax, 3FFFh+0             ; bias, no adjustment necessary
  497.       or       ah, 10000000b           ; turn on sign flag
  498.       mov      word ptr value[9], ax   ; store exponent
  499.       mov      word ptr value[7], 8000h ; store mantissa of 1 in most sig bit
  500.       ; clear rest of value that is actually used
  501.       mov      word ptr value[1], 0
  502.       mov      word ptr value[3], 0
  503.       mov      word ptr value[5], 0
  504.  
  505.       fld      real10 ptr value[1]
  506.       jmp      return
  507.  
  508. sig_bytes_determined:
  509.       mov      dx, cx               ; save in dx for later
  510.       cmp      cx, 9-1              ; no more than cx bytes
  511.       jb       set_movebytes
  512.       mov      cx, 9-1              ; up to 8 bytes
  513. set_movebytes:                      ; cx now holds movebytes
  514.                                     ; si still points to most non-0 sig byte
  515.       sub      si, cx               ; si now points to first byte to be moved
  516.       inc      cx                   ; can be up to 9
  517.  
  518.       cmp     cpu, 386              ; check cpu
  519.       je      use_32_bit            ; use faster 32 bit code if possible
  520.  
  521. ; 16 bit code
  522.       ; clear value
  523.       mov      word ptr value[0], 0
  524.       mov      word ptr value[2], 0
  525.       mov      word ptr value[4], 0
  526.       mov      word ptr value[6], 0
  527.       mov      word ptr value[8], 0
  528.       mov      byte ptr value[10], 0
  529.  
  530.       ; copy bytes from n to value  ; es:si still holds first move byte of n
  531.       mov      di, es               ; swap es and ds
  532.       mov      ax, ds
  533.       mov      es, ax               ; ax is left with original ds
  534.       mov      ds, di
  535.       lea      di, value+9
  536.       sub      di, cx               ; cx holds movebytes
  537.       rep movsb
  538.       mov      ds, ax               ; restore ds
  539.  
  540.       ; adjust for negative values
  541.       xor      ax, ax                  ; use ax as a flag
  542.       ; get sign flag                  ; top byte is still in bl
  543.       and      bl, 10000000b           ; isolate the sign bit
  544.       jz       not_neg_16
  545.       neg      word ptr value[0]       ; take the negative of the 9 byte number
  546.       cmc                              ; toggle carry flag
  547.       not      word ptr value[2]
  548.       adc      word ptr value[2], 0
  549.       not      word ptr value[4]
  550.       adc      word ptr value[4], 0
  551.       not      word ptr value[6]
  552.       adc      word ptr value[6], 0
  553.       not      byte ptr value[8]       ; notice this last one is byte ptr
  554.       adc      byte ptr value[8], 0
  555.       jnc      not_neg_16              ; normal
  556.       mov      byte ptr value[8], 10000000b    ;n was FFFF...0000...
  557.       inc      ax                      ; set ax to 1 to flag this special case
  558.  
  559. not_neg_16:
  560.       sub      dx, bnlength            ; adjust exponent
  561.       add      dx, intlength           ; adjust exponent
  562.       mov      cl, 3
  563.       shl      dx, cl                  ; 256^n=2^8n
  564.       add      dx, ax                  ; see special case above
  565.       ; Shift until most signifcant bit is set.
  566. top_shift_16:
  567.       test     byte ptr value[8], 10000000b  ; test msb
  568.       jnz      bottom
  569.       dec      dx                      ; decrement exponent
  570.       shl      word ptr value[0], 1    ; shift left the 9 byte number
  571.       rcl      word ptr value[2], 1
  572.       rcl      word ptr value[4], 1
  573.       rcl      word ptr value[6], 1
  574.       rcl      byte ptr value[8], 1    ; notice this last one is byte ptr
  575.       jmp      top_shift_16
  576.  
  577. ; don't bother rounding, not really needed while speed is.
  578.  
  579. return_zero:
  580.       fldz
  581.       jmp      return
  582.  
  583. use_32_bit:
  584. .386
  585.       ; clear value
  586.       mov      dword ptr value[0], 0
  587.       mov      dword ptr value[4], 0
  588.       mov      word ptr value[8],  0
  589.       mov      byte ptr value[10], 0
  590.  
  591.       ; copy bytes from n to value  ; es:si still holds first move byte of n
  592.       mov      di, es               ; swap es and ds
  593.       mov      ax, ds
  594.       mov      es, ax               ; ax is left with original ds
  595.       mov      ds, di
  596.       lea      di, value+9
  597.       sub      di, cx               ; cx holds movebytes
  598.       rep movsb
  599.       mov      ds, ax               ; restore ds
  600.  
  601.       ; adjust for negative values
  602.       xor      ax, ax                  ; use ax as a flag
  603.       ; get sign flag                  ; top byte is still in bl
  604.       and      bl, 10000000b           ; determine sign
  605.       jz       not_neg_32
  606.       neg      dword ptr value[0]      ; take the negative of the 9 byte number
  607.       cmc                              ; toggle carry flag
  608.       not      dword ptr value[4]
  609.       adc      dword ptr value[4], 0
  610.       not      byte ptr value[8]       ; notice this last one is byte ptr
  611.       adc      byte ptr value[8], 0
  612.       jnc      not_neg_32              ; normal
  613.       mov      byte ptr value[8], 10000000b    ;n was FFFF...0000...
  614.       inc      ax                      ; set ax to 1 to flag this special case
  615.  
  616. not_neg_32:
  617.       sub      dx, bnlength            ; adjust exponent
  618.       add      dx, intlength           ; adjust exponent
  619.       shl      dx, 3                   ; 256^n=2^8n
  620.       add      dx, ax                  ; see special case above
  621.       ; Shift until most signifcant bit is set.
  622. top_shift_32:
  623.       test     byte ptr value[8], 10000000b  ; test msb
  624.       jnz      bottom
  625.       dec      dx                      ; decrement exponent
  626.       shl      dword ptr value[0], 1   ; shift left the 9 byte number
  627.       rcl      dword ptr value[4], 1
  628.       rcl      byte ptr value[8], 1    ; notice this last one is byte ptr
  629.       jmp      top_shift_32
  630.  
  631. ; don't bother rounding, not really needed while speed is.
  632.  
  633. bottom:
  634. .8086
  635.       ; adjust exponent
  636.       add      dx, 3FFFh+7-8           ; unbiased -> biased, + adjusted
  637.       or       dh, bl                  ; set sign bit if set
  638.       mov      word ptr value[9], dx
  639.  
  640.       ; unlike float and double, long double is returned on fpu stack
  641.       fld      real10 ptr value[1]    ; load return value
  642. return:
  643.       ret
  644.  
  645. bntofloat   endp
  646.  
  647. ;
  648. ; LDBL floattobn(bf_t n, LDBL f) is in BIGNUM.C
  649. ;
  650.  
  651. END
  652.