home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / windows / winsrc.zip / WGENERAL.ASM < prev    next >
Assembly Source File  |  1990-12-17  |  13KB  |  509 lines

  1. ;    Generic assembler routines that have very little at all
  2. ;    to do with fractals.
  3. ;
  4. ;
  5. ; ---- 32-bit Multiply/Divide Routines (includes 16-bit emulation)
  6. ;
  7. ;    multiply()
  8. ;    divide()
  9. ;
  10.  
  11. .MODEL    medium,c
  12.  
  13. .8086
  14.  
  15. .DATA
  16.  
  17.  
  18. ; ************************ Public variables *****************************
  19.  
  20. public        overflow        ; Mul, Div overflow flag: 0 means none
  21.  
  22. ;        arrays declared here, used elsewhere
  23. ;        arrays not used simultaneously are deliberately overlapped
  24.  
  25. public        prefix, suffix, dstack, decoderline ; for the Decoder
  26. public        strlocn, teststring, block    ; used by the Encoder
  27. public        boxx, boxy, boxvalues        ; zoom-box arrays
  28. public        olddacbox            ; temporary DAC saves
  29. public        rlebuf                ; Used ty the TARGA En/Decoder
  30.  
  31. ; ************************* "Shared" array areas **************************
  32.  
  33. ; Short forms used in subsequent comments:
  34. ;   name........duration of use......................modules....................
  35. ;   encoder    "s"aving an image                    encoder.c
  36. ;   decoder    "r"estoring an image                 decoder.c, gifview.c
  37. ;   zoom    zoom box is visible             zoom.c, video.asm
  38. ;   vidswitch    temp during video mode setting         video.asm
  39. ;   vidreset    temp during video reset          prompts.c, fractint.c, rotate.c, cmdfiles.c
  40. ;   tgaview    restore of tga image             tgaview.c
  41. ;   solidguess    image gen with "g", not to disk      calcfrac.c
  42. ;   btm     image gen with "b", not to disk      calcfrac.c
  43.  
  44. block        label    byte        ; encoder(266)
  45. suffix        dw    2048 dup(0)    ; decoder(4k), vidswitch(256)
  46.  
  47. teststring    label    byte        ; encoder(100)
  48. dstack        dw    2048 dup(0)    ; decoder(4k), solidguess(4k), btm(2k)
  49.                     ;   zoom(2k)
  50.  
  51. strlocn     label    word        ; encoder(10k)
  52. prefix        label    word        ; decoder(8k), solidguess(6k)
  53. olddacbox    label    byte        ; vidreset(768)
  54. boxx        dw    2048 dup(0)    ; zoom(4k), tgaview(4k)
  55. boxy        dw    2048 dup(0)    ; zoom(4k)
  56. boxvalues    label    byte        ; zoom(2k)
  57. decoderline    db    2050 dup(0)    ; decoder(2049), btm(2k)
  58.  
  59. rlebuf        db    258 dup(0)    ; f16.c(258) .tga save/restore?
  60.  
  61. ; Internal Overflow flag
  62.  
  63. overflow    dw    0        ; overflow flag
  64.  
  65. .CODE
  66.  
  67.  
  68. ; =======================================================
  69. ;
  70. ;    32-bit integer multiply routine with an 'n'-bit shift.
  71. ;    Overflow condition returns 0x7fffh with overflow = 1;
  72. ;
  73. ;    long x, y, z, multiply();
  74. ;    int n;
  75. ;
  76. ;    z = multiply(x,y,n)
  77. ;
  78. ;    requires the presence of an external variable, 'cpu'.
  79. ;        'cpu' == 386 if a 386 is present.
  80.  
  81. .MODEL    medium,c
  82.  
  83. .8086
  84.  
  85. .DATA
  86.  
  87. extrn    cpu:word            ; cpu flag:     88 = 8088/8086
  88.                     ;        186 = 80188/186
  89.                     ;        286 = 80286
  90.                     ;        386 = 80386/486
  91. extrn    fpu:word            ; fpu flag:      0 = none
  92.                     ;         87 = 8087
  93.                     ;               287 = 80287
  94.                     ;        387 = 80387/(487)
  95.  
  96. temp    dw    5 dup(0)        ; temporary 64-bit result goes here
  97. sign    db    0            ; sign flag goes here
  98.  
  99. .CODE
  100.  
  101. multiply    proc    x:dword, y:dword, n:word
  102.  
  103.     cmp    cpu,386         ; go-fast time?
  104.     jne    slowmultiply        ; no.  yawn...
  105.  
  106. .386                    ; 386-specific code starts here
  107.  
  108.     mov    eax,x            ; load X into EAX
  109.     imul    y            ; do the multiply
  110.     mov    cx,n            ; set up the shift
  111.     cmp    cx,32            ; ugly klooge:    check for 32-bit shift
  112.     jb    short fastm1        ;  < 32 bits:  no problem
  113.     mov    eax,edx         ;  >= 32 bits:    manual shift
  114.     mov    edx,0            ;  ...
  115.     sub    cx,32            ;  ...
  116. fastm1: shrd    eax,edx,cl        ; shift down 'n' bits
  117.     js    fastm3
  118.     sar    edx,cl
  119.     jne    overmf
  120.     shld    edx,eax,16
  121.     ret
  122. fastm3: sar    edx,cl
  123.     inc    edx
  124.     jne    overmf
  125.     shld    edx,eax,16
  126.     ret
  127. overmf:
  128.     mov    ax,0ffffh        ; overflow value
  129.     mov    dx,07fffh        ; overflow value
  130.     mov    overflow,1        ; flag overflow
  131.     ret
  132.  
  133. .8086                    ; 386-specific code ends here
  134.  
  135. slowmultiply:                ; (sigh)  time to do it the hard way...
  136.     push    di
  137.     push    si
  138.  
  139.     mov    ax,0
  140.     mov    temp+4,ax        ; first, zero out the (temporary)
  141.     mov    temp+6,ax        ;  result
  142.     mov    temp+8,ax
  143.  
  144.     mov    bx,word ptr x        ; move X to SI:BX
  145.     mov    si,word ptr x+2        ;  ...
  146.     mov    cx,word ptr y        ; move Y to DI:CX
  147.     mov    di,word ptr y+2        ;  ...
  148.  
  149.     mov    sign,0            ; clear out the sign flag
  150.     cmp    si,0            ; is X negative?
  151.     jge    mults1            ;  nope
  152.     not    sign            ;  yup.  flip signs
  153.     not    bx            ;   ...
  154.     not    si            ;   ...
  155.     stc                ;   ...
  156.     adc    bx,ax            ;   ...
  157.     adc    si,ax            ;   ...
  158. mults1: cmp    di,0            ; is DI:CX negative?
  159.     jge    mults2            ;  nope
  160.     not    sign            ;  yup.  flip signs
  161.     not    cx            ;   ...
  162.     not    di            ;   ...
  163.     stc                ;   ...
  164.     adc    cx,ax            ;   ...
  165.     adc    di,ax            ;   ...
  166. mults2:
  167.  
  168.     mov    ax,bx            ; perform BX x CX
  169.     mul    cx            ;  ...
  170.     mov    temp,ax         ;  results in lowest 32 bits
  171.     mov    temp+2,dx        ;  ...
  172.  
  173.     mov    ax,bx            ; perform BX x DI
  174.     mul    di            ;  ...
  175.     add    temp+2,ax        ;  results in middle 32 bits
  176.     adc    temp+4,dx        ;  ...
  177.     jnc    mults3            ;  carry bit set?
  178.     inc    word ptr temp+6     ;  yup.  overflow
  179. mults3:
  180.  
  181.     mov    ax,si            ; perform SI * CX
  182.     mul    cx            ;  ...
  183.     add    temp+2,ax        ;  results in middle 32 bits
  184.     adc    temp+4,dx        ;  ...
  185.     jnc    mults4            ;  carry bit set?
  186.     inc    word ptr temp+6     ;  yup.  overflow
  187. mults4:
  188.  
  189.     mov    ax,si            ; perform SI * DI
  190.     mul    di            ;  ...
  191.     add    temp+4,ax        ; results in highest 32 bits
  192.     adc    temp+6,dx        ;  ...
  193.  
  194.     mov    cx,n            ; set up for the shift loop
  195.     cmp    cx,24            ; shifting by three bytes or more?
  196.     jl    multc1            ;  nope.  check for something else
  197.     sub    cx,24            ; quick-shift 24 bits
  198.     mov    ax,temp+3        ; load up the registers
  199.     mov    dx,temp+5        ;  ...
  200.     mov    si,temp+7        ;  ...
  201.     mov    bx,0            ;  ...
  202.     jmp    short multc4        ; branch to common code
  203. multc1: cmp    cx,16            ; shifting by two bytes or more?
  204.     jl    multc2            ;  nope.  check for something else
  205.     sub    cx,16            ; quick-shift 16 bits
  206.     mov    ax,temp+2        ; load up the registers
  207.     mov    dx,temp+4        ;  ...
  208.     mov    si,temp+6        ;  ...
  209.     mov    bx,0            ;  ...
  210.     jmp    short multc4        ; branch to common code
  211. multc2: cmp    cx,8            ; shifting by one byte or more?
  212.     jl    multc3            ;  nope.  check for something else
  213.     sub    cx,8            ; quick-shift 8 bits
  214.     mov    ax,temp+1        ; load up the registers
  215.     mov    dx,temp+3        ;  ...
  216.     mov    si,temp+5        ;  ...
  217.     mov    bx,temp+7        ;  ...
  218.     jmp    short multc4        ; branch to common code
  219. multc3: mov    ax,temp         ; load up the regs
  220.     mov    dx,temp+2        ;  ...
  221.     mov    si,temp+4        ;  ...
  222.     mov    bx,temp+6        ;  ...
  223. multc4: cmp    cx,0            ; done shifting?
  224.     je    multc5            ;  yup.  bail out
  225.  
  226. multloop:
  227.     shr    bx,1            ; shift down 1 bit, cascading
  228.     rcr    si,1            ;  ...
  229.     rcr    dx,1            ;  ...
  230.     rcr    ax,1            ;  ...
  231.     loop    multloop        ; try the next bit, if any
  232. multc5:
  233.     cmp    si,0            ; overflow time?
  234.     jne    overm1            ; yup.    Bail out.
  235.     cmp    bx,0            ; overflow time?
  236.     jne    overm1            ; yup.    Bail out.
  237.     cmp    dx,0            ; overflow time?
  238.     jl    overm1            ; yup.    Bail out.
  239.  
  240.     cmp    sign,0            ; should we negate the result?
  241.     je    mults5            ;  nope.
  242.     not    ax            ;  yup.  flip signs.
  243.     not    dx            ;   ...
  244.     mov    bx,0            ;   ...
  245.     stc                ;   ...
  246.     adc    ax,bx            ;   ...
  247.     adc    dx,bx            ;   ...
  248. mults5:
  249.     jmp    multiplyreturn
  250.  
  251. overm1:
  252.     mov    ax,0ffffh        ; overflow value
  253.     mov    dx,07fffh        ; overflow value
  254.     mov    overflow,1        ; flag overflow
  255.  
  256. multiplyreturn:             ; that's all, folks!
  257.     pop    si
  258.     pop    di
  259.     ret
  260. multiply    endp
  261.  
  262.  
  263. ; =======================================================
  264. ;
  265. ;    32-bit integer divide routine with an 'n'-bit shift.
  266. ;    Overflow condition returns 0x7fffh with overflow = 1;
  267. ;
  268. ;    long x, y, z, divide();
  269. ;    int n;
  270. ;
  271. ;    z = divide(x,y,n);    /* z = x / y; */
  272. ;
  273. ;    requires the presence of an external variable, 'cpu'.
  274. ;        'cpu' == 386 if a 386 is present.
  275.  
  276.  
  277. .8086
  278.  
  279. divide        proc    x:dword, y:dword, n:word
  280.  
  281.     push    di
  282.     push    si
  283.  
  284.     cmp    cpu,386         ; go-fast time?
  285.     jne    slowdivide        ; no.  yawn...
  286.  
  287. .386                    ; 386-specific code starts here
  288.  
  289.     mov    edx,x            ; load X into EDX (shifts to EDX:EAX)
  290.     mov    ebx,y            ; load Y into EBX
  291.  
  292.     mov    sign,0            ; clear out the sign flag
  293.     cmp    edx,0            ; is X negative?
  294.     jge    short divides1        ;  nope
  295.     not    sign            ;  yup.  flip signs
  296.     neg    edx            ;   ...
  297. divides1:
  298.     cmp    ebx,0            ; is Y negative?
  299.     jge    short divides2        ;  nope
  300.     not    sign            ;  yup.  flip signs
  301.     neg    ebx            ;   ...
  302. divides2:
  303.  
  304.     mov    eax,0            ; clear out the low-order bits
  305.     mov    cx,32            ; set up the shift
  306.     sub    cx,n            ; (for large shift counts - faster)
  307. fastd1: cmp    cx,0            ; done shifting?
  308.     je    fastd2            ; yup.
  309.     shr    edx,1            ; shift one bit
  310.     rcr    eax,1            ;  ...
  311.     loop    fastd1            ; and try again
  312. fastd2:
  313.     cmp    edx,ebx         ; umm, will the divide blow out?
  314.     jae    overd1            ;  yup.  better skip it.
  315.     div    ebx            ; do the divide
  316.     cmp    eax,0            ; did the sign flip?
  317.     jl    overd1            ;  then we overflowed
  318.     cmp    sign,0            ; is the sign reversed?
  319.     je    short divides3        ;  nope
  320.     neg    eax            ; flip the sign
  321. divides3:
  322.     push    eax            ; save the 64-bit result
  323.     pop    ax            ; low-order  16 bits
  324.     pop    dx            ; high-order 16 bits
  325.     jmp    dividereturn        ; back to common code
  326.  
  327. .8086                    ; 386-specific code ends here
  328.  
  329. slowdivide:                ; (sigh)  time to do it the hard way...
  330.  
  331.     mov    ax,word ptr x        ; move X to DX:AX
  332.     mov    dx,word ptr x+2        ;  ...
  333.  
  334.     mov    sign,0            ; clear out the sign flag
  335.     cmp    dx,0            ; is X negative?
  336.     jge    divides4        ;  nope
  337.     not    sign            ;  yup.  flip signs
  338.     not    ax            ;   ...
  339.     not    dx            ;   ...
  340.     stc                ;   ...
  341.     adc    ax,0            ;   ...
  342.     adc    dx,0            ;   ...
  343. divides4:
  344.  
  345.     mov    cx,32            ; get ready to shift the bits
  346.     sub    cx,n            ; (shift down rather than up)
  347.     mov    byte ptr temp+4,cl    ;  ...
  348.  
  349.     mov    cx,0            ;  clear out low bits of DX:AX:CX:BX
  350.     mov    bx,0            ;  ...
  351.  
  352.     cmp    byte ptr temp+4,16    ; >= 16 bits to shift?
  353.     jl    dividex0        ;  nope
  354.     mov    bx,cx            ;  yup.  Take a short-cut
  355.     mov    cx,ax            ;   ...
  356.     mov    ax,dx            ;   ...
  357.     mov    dx,0            ;   ...
  358.     sub    byte ptr temp+4,16    ;   ...
  359. dividex0:
  360.     cmp    byte ptr temp+4,8    ; >= 8 bits to shift?
  361.     jl    dividex1        ;  nope
  362.     mov    bl,bh            ;  yup.  Take a short-cut
  363.     mov    bh,cl            ;   ...
  364.     mov    cl,ch            ;   ...
  365.     mov    ch,al            ;   ...
  366.     mov    al,ah            ;   ...
  367.     mov    ah,dl            ;   ...
  368.     mov    dl,dh            ;   ...
  369.     mov    dh,0            ;   ...
  370.     sub    byte ptr temp+4,8    ;   ...
  371. dividex1:
  372.     cmp    byte ptr temp+4,0    ; are we done yet?
  373.     je    dividex2        ;  yup
  374.     shr    dx,1            ; shift all 64 bits
  375.     rcr    ax,1            ;  ...
  376.     rcr    cx,1            ;  ...
  377.     rcr    bx,1            ;  ...
  378.     dec    byte ptr temp+4     ; decrement the shift counter
  379.     jmp    short dividex1        ;  and try again
  380. dividex2:
  381.  
  382.     mov    di,word ptr y        ; move Y to SI:DI
  383.     mov    si,word ptr y+2        ;  ...
  384.  
  385.     cmp    si,0            ; is Y negative?
  386.     jge    divides5        ;  nope
  387.     not    sign            ;  yup.  flip signs
  388.     not    di            ;   ...
  389.     not    si            ;   ...
  390.     stc                ;   ...
  391.     adc    di,0            ;   ...
  392.     adc    si,0            ;   ...
  393. divides5:
  394.  
  395.     mov    byte ptr temp+4,33    ; main loop counter
  396.     mov    temp,0            ; results in temp
  397.     mov    word ptr temp+2,0    ;  ...
  398.  
  399. dividel1:
  400.     shl    temp,1            ; shift the result up 1
  401.     rcl    word ptr temp+2,1    ;  ...
  402.     cmp    dx,si            ; is DX:AX >= Y?
  403.     jb    dividel3        ;  nope
  404.     ja    dividel2        ;  yup
  405.     cmp    ax,di            ;  maybe
  406.     jb    dividel3        ;  nope
  407. dividel2:
  408.     cmp    byte ptr temp+4,32    ; overflow city?
  409.     jge    overd1            ;  yup.
  410.     sub    ax,di            ; subtract Y
  411.     sbb    dx,si            ;  ...
  412.     inc    temp            ; add 1 to the result
  413.     adc    word ptr temp+2,0    ;  ...
  414. dividel3:
  415.     shl    bx,1            ; shift all 64 bits
  416.     rcl    cx,1            ;  ...
  417.     rcl    ax,1            ;  ...
  418.     rcl    dx,1            ;  ...
  419.     dec    byte ptr temp+4     ; time to quit?
  420.     jnz    dividel1        ;  nope.  try again.
  421.  
  422.     mov    ax,temp         ; copy the result to DX:AX
  423.     mov    dx,word ptr temp+2    ;  ...
  424.     cmp    sign,0            ; should we negate the result?
  425.     je    divides6        ;  nope.
  426.     not    ax            ;  yup.  flip signs.
  427.     not    dx            ;   ...
  428.     mov    bx,0            ;   ...
  429.     stc                ;   ...
  430.     adc    ax,0            ;   ...
  431.     adc    dx,0            ;   ...
  432. divides6:
  433.     jmp    short dividereturn
  434.  
  435. overd1:
  436.     mov    ax,0ffffh        ; overflow value
  437.     mov    dx,07fffh        ; overflow value
  438.     mov    overflow,1        ; flag overflow
  439.  
  440. dividereturn:                ; that's all, folks!
  441.     pop    si
  442.     pop    di
  443.     ret
  444. divide        endp
  445.  
  446. .MODEL    medium,c
  447.  
  448. .8086
  449.  
  450. .FARDATA
  451.  
  452.  
  453.  
  454. .CODE
  455.  
  456. extrn temp_array:far
  457.  
  458. ; *************** Function toextra(tooffset,fromaddr, fromcount) *********
  459.  
  460. toextra proc    uses es di si, tooffset:word, fromaddr:word, fromcount:word
  461.         cld                             ; move forward
  462.         les     di, temp_array
  463.         add     di,tooffset             ; load to here
  464.     mov    si,fromaddr        ; load from here
  465.     mov    cx,fromcount        ; this many bytes
  466.     rep    movsb            ; do it.
  467. tobad:
  468.     ret                ; we done.
  469. toextra endp
  470.  
  471.  
  472. ; *************** Function fromextra(fromoffset, toaddr, tocount) *********
  473.  
  474. fromextra proc    uses es di si, fromoffset:word, toaddr:word, tocount:word
  475.     push    ds            ; save DS for a tad
  476.     pop    es            ; restore it to ES
  477.     cld                ; move forward
  478.     mov    di,toaddr        ; load to here
  479.         mov     cx,tocount              ; this many bytes
  480.         lds     si, temp_array
  481.         add     si,fromoffset           ;  ..
  482.     rep    movsb            ; do it.
  483. frombad:
  484.     push    es            ; save ES again.
  485.     pop    ds            ; restore DS
  486.     ret                ; we done.
  487. fromextra endp
  488.  
  489.  
  490. ; *************** Function cmpextra(cmpoffset,cmpaddr, cmpcount) *********
  491.  
  492. cmpextra proc    uses es di si, cmpoffset:word, cmpaddr:word, cmpcount:word
  493.         cld                             ; move forward
  494.         les     di, temp_array
  495.         add     di,cmpoffset            ; load to here
  496.     mov    si,cmpaddr        ; load from here
  497.     mov    cx,cmpcount        ; this many bytes
  498.     rep    cmpsb            ; do it.
  499.     jnz    cmpbad            ; failed.
  500.     mov    ax,0            ; 0 == true
  501.     jmp    cmpend
  502. cmpbad:
  503.     mov    ax,1            ; 1 == false
  504. cmpend:
  505.     ret                ; we done.
  506. cmpextra    endp
  507.  
  508.     end
  509.