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