home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / MISC / BBENCH21.ZIP / SOURCE.ZIP / BENCHSUB.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-04-10  |  49.0 KB  |  2,515 lines

  1. ; «PL1»
  2. ;
  3. ; Assembly routines for BYTE benchmarks
  4. ; This is the heart of all of the routines.
  5. ;
  6.  
  7. ;General equates
  8. TRUE        equ    1
  9. FALSE        equ    0
  10.  
  11. ;Equates for timer routine
  12. BIOS_TIME_LO    equ    006ch
  13. BIOS_DATASEG    equ    0040h
  14. TIMER_MODE    equ    43h
  15. TIMER0        equ    40h
  16. MAX_COUNT    equ    0ffffh
  17.  
  18. DOSSEG
  19. .MODEL    small
  20. FDATA    SEGMENT DWORD PUBLIC
  21. FAC1    DQ    3.0E0
  22. FAC2    DQ      2.0E0
  23. FAC3    DQ    5.050E0
  24. FAC4    DQ    5.050E0
  25. FRESULT    DQ    ?
  26. FDATA    ENDS
  27.  
  28. .DATA
  29.  
  30. ;Definitions for high-resolution timer.
  31. count_low    dw    0    ;number of interrupt tics
  32. count_micro    dw    0    ;calc. from interrrupt tics
  33. count_milli    dw    0    ;calc. from interrrupt tics
  34. timer_micro    dw    0    ;final value
  35. timer_milli    dw    0    ;  "
  36. timer_sec    dw    0    ;  "
  37. svd_8253_count    dw    0    ;storage space
  38. timer_convert    dw    8381    ;838.096 nsec per tick
  39. count_convert    dw    54926    ;54.925 mill-sec per count
  40. ten_thousand    dw    10000
  41. five_thousand    dw    5000
  42. thousand    dw    1000
  43.  
  44. extrn        _timeradjust:word    ;timer adjustment value
  45. extrn        _machine_config: BYTE
  46. coproc        equ    word ptr _machine_config+6
  47.  
  48. ;Definitions for floating-point
  49. INDEFINITE DD    0FFC00000R    ;Indefinite value
  50. IOMEGA    DQ    ?        ;Holds value of i omega
  51. FSTATUS    DW    ?        ;Holds status field
  52. STARTX    DQ    ?        ;For trapezoid
  53. MINUS2    DD    -2.0        ;Guess
  54. PIDIV2    DT    1.5707963267948966192 ;pi/2
  55.  
  56. ;Definitions for 8087
  57. CW_87 RECORD RES871:3,INF:1,RND:2,PRECC:2,ERRE:1,RES872:1,PRECM:1,UNFM:1,OVFM:1,ZDM:1,DNM:1,INVM:1
  58.  
  59. SW_87    RECORD    BUSY:1,COND3:1,TOP:3,COND2:1,COND1:1,COND0:1,ERRP:1,RES873:1,PRCE:1,UNFE:1,OVFE:1,ZDE:1,DNE:1,INVE:1
  60.  
  61. ;Definitions for EMS routines
  62. HANDLE1        DW    ?    ;Storage for first handle
  63. HANDLE2        DW    ?    ;Storage for second handle
  64.  
  65. ;Configuration stuff for Hercules mode
  66. CRTCP    DB    00H,35H        ;54 chars horizontal
  67.     DB    01,2DH        ;45 displayed
  68.     DB    02,2EH        ;Sync at 46th char
  69.     DB    03,07H        ;Sync width 7 char clocks
  70.     DB    4,5BH        ;Vert total of 92 characters
  71.     DB    05,02H        ;Vert adjust of 2 scan lines
  72.     DB    06,57H        ;Vert displayed of 87 char rows
  73.     DB    07,57H        ;Vert. sync after 87th char row
  74.     DB    09,03H        ;Max scan line, 4 scan lines per char
  75. BDATA    DB    7        ;CRT_MODE
  76.     DW    80        ;CRT_COLS
  77.     DW    8000H        ;CRT_LEN
  78.     DW    0        ;CRT_START
  79.     DW    8 DUP (0)    ;CURSOR_POSN
  80.     DW    0        ;CURSOR_MODE
  81.     DB    0        ;ACTIVE_PAGE
  82.     DW    3B4H        ;ADDR_6845
  83. CRTMD    DB    0AH        ;CRT_MODE_SET
  84.     DB    0        ;PALLETTE
  85. BDLEN    EQU    $-BDATA
  86.  
  87. .CODE
  88.  
  89.  
  90. ;****************************
  91. ;       do_sieve            *
  92. ;****************************
  93. ; This routine is called from C with the following
  94. ;       int do_sieve(flagseg,size);
  95. ; flagseg is the segment holding the flags array
  96. ; size  is the size of the flags array
  97. ; The routine returns the number of primes found
  98.     PUBLIC    _do_sieve
  99. FLAGSEG        equ    [BP+4]
  100. SSIZE        equ    [BP+6]
  101.  
  102. _do_sieve    PROC    NEAR
  103. ;Save registers
  104.         PUSH    BP
  105.         MOV    BP,SP
  106.         PUSH    BX
  107.         PUSH    CX
  108.         PUSH    DX
  109.         PUSH    SI
  110.         PUSH    DI
  111.         PUSH    DS
  112.         PUSH    ES
  113. ;Clear count
  114.         XOR    DX,DX
  115. ;Set up DS and ES to point to flags segment
  116.         MOV    AX,FLAGSEG
  117.         MOV    DS,AX
  118.         MOV    ES,AX
  119. ;Set all flags to true
  120.         XOR    DI,DI
  121.         MOV    CX,SSIZE
  122.         MOV    AL,TRUE
  123.         REP    STOSB
  124. ;Do the main loop
  125.         XOR    SI,SI        ;i=0
  126. DS1:        CMP    SI,SSIZE    ;for(i=0;i<=size;...)
  127.         JG    DS5
  128.         CMP    BYTE PTR [SI],TRUE    ;if(flags[i])
  129.         JNZ    DS4A
  130.         MOV    BX,SI
  131.         ADD    BX,SI
  132.         ADD    BX,3        ;prime=i+i+3
  133. ;Inner loop
  134.         MOV    DI,BX
  135.         ADD    DI,SI        ;k=i+prime
  136. DS3:        CMP    DI,SSIZE    ;k<=size
  137.         JG    DS4
  138.         MOV    BYTE PTR [DI],FALSE
  139.         ADD    DI,BX        ;k+=prime
  140.         JMP    DS3
  141. DS4:        INC    DX        ;count++
  142. DS4A:        INC    SI        ;...i++)
  143.         JMP    DS1
  144. DS5:        MOV    AX,DX        ;Return count
  145. ;Restore
  146.         POP    ES
  147.         POP    DS
  148.         POP    DI
  149.         POP    SI
  150.         POP    DX
  151.         POP    CX
  152.         POP    BX
  153.         POP    BP
  154.         RET
  155. _do_sieve    ENDP
  156.  
  157. ;****************************
  158. ;       do_shell            *
  159. ;****************************
  160. ; This routine performs the shell-sort on an integer array.
  161. ; Call with:
  162. ;           do_shell(arrayseg,top)
  163. ; arrayseg is segment address of array to sort
  164. ; top is the maximum number of elements in the array
  165. ; NOTE: The array to sort MUST begin on a segment boundary.
  166.     PUBLIC    _do_shell
  167. SHARRAYSEG    equ    [BP+4]
  168. SHTOP        equ    [BP+6]
  169.  
  170. _do_shell    PROC    NEAR
  171. ;Save registers
  172.         PUSH    BP
  173.         MOV    BP,SP
  174.         PUSH    BX
  175.         PUSH    DX
  176.         PUSH    SI
  177.         PUSH    DI
  178.         PUSH    DS
  179. ;Set up data segment
  180.         MOV    AX,SHARRAYSEG
  181.         MOV    DS,AX
  182. ;Calculate the gap
  183.         MOV    BX,SHTOP        ;gap=(top-bot)/2
  184.         SHR    BX,1
  185. ;
  186. SHS1:        MOV    DL,1        ;nex=1
  187.         XOR    DI,DI        ;for(i=0...
  188. SHS2:        MOV    AX,SHTOP
  189.         SUB    AX,BX
  190.         SHL    AX,1        ;Word boundary
  191.         CMP    DI,AX        ;...;i<=top-gap
  192.         JG    SHS3
  193.         MOV    SI,DI
  194.         ADD    SI,BX        ;Word boundary
  195.         ADD    SI,BX
  196.         MOV    AX,[SI]
  197.         CMP    AX,[DI]
  198.         JGE    SHS2A
  199.         MOV    AX,[SI]        ;exchange elements
  200.         XCHG    AX,[DI]
  201.         MOV    [SI],AX
  202.         XOR    DL,DL        ;Swap has occurred
  203. SHS2A:        INC    DI
  204.         INC    DI        ;++i
  205.         JMP    SHS2
  206. SHS3:        OR    DL,DL
  207.         JZ    SHS1
  208. ;
  209.         SHR    BX,1        ;gap=gap/2
  210.         JNZ    SHS1        ;while(gap!=0)
  211. ;Restore
  212.         POP    DS
  213.         POP    DI
  214.         POP    SI
  215.         POP    DX
  216.         POP    BX
  217.         POP    BP
  218.         RET
  219. _do_shell    ENDP
  220.  
  221. ;****************************
  222. ;      do_qsort             *
  223. ;****************************
  224. ; This routine performs the quicksort algorithm on an integer array.
  225. ; Call with:
  226. ;       do_qsort(arrayseg,bot,top)
  227. ;  arrayseg is the segment of the array to sort
  228. ;  bot is to lowest element in the partition
  229. ;  top is the highest element in the partition
  230. QSTOP        equ    [BP+8]
  231. QSBOT        equ    [BP+6]
  232. QSARRAYSEG    equ    [BP+4]
  233.         PUBLIC    _do_qsort
  234. _do_qsort    PROC    NEAR
  235. ;Set up the stack
  236.         PUSH    BP
  237.         MOV    BP,SP
  238.         PUSH    DX
  239.         PUSH    SI
  240.         PUSH    DI
  241.         PUSH    DS
  242. ;Point DS register properly
  243.         MOV    AX,QSARRAYSEG
  244.         MOV    DS,AX
  245. ;while(bot<top)
  246. QS0:        MOV    AX,QSBOT
  247.         CMP    AX,QSTOP
  248.         JGE    QS6
  249. ;Set ranges and choose partitioning element
  250.         MOV    SI,AX        ;SI holds i
  251.         SHL    SI,1        ;Word align
  252.         MOV    DI,QSTOP    ;DI holds j
  253.         SHL    DI,1        ;Word align
  254.         MOV    DX,[SI]        ;temp=array[bot]
  255. ;Partition array
  256. QS1:        CMP    SI,DI        ;while(i<j)
  257.         JGE    QS5A
  258. QS2:        CMP    [DI],DX        ;while(array[j]>temp)
  259.         JLE    QS3
  260.         DEC    DI        ;j-=1
  261.         DEC    DI        ;(Word aligned)
  262.         JMP    QS2
  263. QS3:        MOV    AX,[DI]        ;array[i]=array[j]
  264.         MOV    [SI],AX
  265. QS4:        CMP    SI,DI        ;while((i<j) && ...
  266.         JGE    QS5
  267.         CMP    [SI],DX        ;...(array[i]<=temp))
  268.         JG    QS5
  269.         INC    SI        ;i+=1
  270.         INC    SI        ;(Word aligned)
  271.         JMP    QS4
  272. QS5:        MOV    AX,[SI]        ;array[j]=array[i]
  273.         MOV    [DI],AX
  274.         JMP    QS1
  275. QS5A:        MOV    [SI],DX        ;array[i]=temp
  276. ;Call qsort recursively
  277.         MOV    AX,SI
  278.         SHR    AX,1        ;Back to non-word alignment
  279.         DEC    AX
  280.         PUSH    AX
  281.         MOV    AX,QSBOT
  282.         PUSH    AX
  283.         PUSH    DS
  284.         CALL    _do_qsort
  285.         ADD    SP,6        ;Clear stack
  286.         SHR    SI,1        ;bot=i+1
  287.         INC    SI
  288.         MOV    QSBOT,SI
  289.         JMP    QS0
  290. QS6:        POP    DS        ;Restore
  291.         POP    DI
  292.         POP    SI
  293.         POP    DX
  294.         POP    BP
  295.         RET
  296. _do_qsort    ENDP
  297.  
  298. ;****************************
  299. ;       do_bmove            *
  300. ;****************************
  301. ; Byte-wide move
  302. ; Call with:
  303. ;    do_bmove(seg1,off1,seg2,off2,nbytes)
  304. ;    seg1,off1 = segment/offset of source
  305. ;    seg2,off2 = segment/offset of destination
  306. ;    nbytes = unsigned count of number of bytes to move
  307.         PUBLIC    _do_bmove
  308. _do_bmove    PROC    NEAR
  309. SEG1        equ    [BP+4]
  310. OFF1        equ    [BP+6]
  311. SEG2        equ    [BP+8]
  312. OFF2        equ    [BP+10]
  313. NBYTES        equ    [BP+12]
  314. ;Save everything
  315.         PUSH    BP
  316.         MOV    BP,SP
  317.         PUSH    CX
  318.         PUSH    SI
  319.         PUSH    DI
  320.         PUSH    DS
  321.         PUSH    ES
  322. ;Load up the registers
  323.         MOV    AX,SEG1
  324.         MOV    DS,AX
  325.         MOV    AX,SEG2
  326.         MOV    ES,AX
  327.         MOV    SI,OFF1
  328.         MOV    DI,OFF2
  329.         MOV    CX,NBYTES
  330.         CLD
  331.         REP    MOVSB
  332. ;Restore and return
  333.         POP    ES
  334.         POP    DS
  335.         POP    DI
  336.         POP    SI
  337.         POP    CX
  338.         POP    BP
  339.         RET
  340. _do_bmove    ENDP
  341. ;****************************
  342. ;       do_wmove            *
  343. ;****************************
  344. ; Word-wide move
  345. ; Call with:
  346. ;    do_bmove(seg1,off1,seg2,off2,nwords)
  347. ;    seg1,off1 = segment/offset of source
  348. ;    seg2,off2 = segment/offset of destination
  349. ;    nwords = unsigned count of number of words to move
  350.         PUBLIC    _do_wmove
  351. _do_wmove    PROC    NEAR
  352. SEG1        equ    [BP+4]
  353. OFF1        equ    [BP+6]
  354. SEG2        equ    [BP+8]
  355. OFF2        equ    [BP+10]
  356. NWORDS        equ    [BP+12]
  357. ;Save everything
  358.         PUSH    BP
  359.         MOV    BP,SP
  360.         PUSH    CX
  361.         PUSH    SI
  362.         PUSH    DI
  363.         PUSH    DS
  364.         PUSH    ES
  365. ;Load up the registers
  366.         MOV    AX,SEG1
  367.         MOV    DS,AX
  368.         MOV    AX,SEG2
  369.         MOV    ES,AX
  370.         MOV    SI,OFF1
  371.         MOV    DI,OFF2
  372.         MOV    CX,NWORDS
  373.         CLD
  374.         REP    MOVSW
  375. ;Restore and return
  376.         POP    ES
  377.         POP    DS
  378.         POP    DI
  379.         POP    SI
  380.         POP    CX
  381.         POP    BP
  382.         RET
  383. _do_wmove    ENDP
  384.  
  385. ;****************************
  386. ;         do_dmove          *
  387. ;****************************
  388. ; do_dmove(seg1,off1,seg1,off2,ndwords
  389.     PUBLIC    _do_dmove
  390. _do_dmove    PROC    NEAR
  391. SEG1        equ    [BP+4]
  392. OFF1        equ    [BP+6]
  393. SEG2        equ    [BP+8]
  394. OFF2        equ    [BP+10]
  395. NDWORDS        equ    [BP+12]
  396.         PUSH    BP
  397.         MOV    BP,SP
  398.         PUSH    CX
  399.         PUSH    SI
  400.         PUSH    DI
  401.         PUSH    DS
  402.         PUSH    ES
  403. ;Set up segments
  404.         MOV    AX,SEG1
  405.         MOV    DS,AX
  406.         MOV    AX,SEG2
  407.         MOV    ES,AX
  408. .386
  409.         XOR    ESI,ESI
  410.         XOR    EDI,EDI
  411.         XOR    ECX,ECX
  412.         MOV    SI,OFF1
  413.         MOV    DI,OFF2
  414.         MOV    CX,NDWORDS
  415.         CLD
  416.         REP    MOVSD
  417. .8086
  418. ;Restore and return
  419.         POP    ES
  420.         POP    DS
  421.         POP    DI
  422.         POP    SI
  423.         POP    CX
  424.         POP    BP
  425.         RET
  426. _do_dmove    ENDP
  427.  
  428. ;****************************
  429. ;      do_ifourbang         *
  430. ;****************************
  431. ; do_ifourbang(ifacseg,numvals)
  432.     PUBLIC    _do_ifourbang
  433. _do_ifourbang    PROC    NEAR
  434. IFACSEG        equ    [BP+4]
  435. NUMVALS        equ    [BP+6]
  436.         PUSH    BP
  437.         MOV    BP,SP
  438.         PUSH    BX
  439.         PUSH    CX
  440.         PUSH    SI
  441.         PUSH    DS
  442. ;Load up registers
  443.         MOV    AX,IFACSEG
  444.         MOV    DS,AX
  445.         MOV    CX,NUMVALS
  446. ;Start the loop
  447.         XOR    SI,SI
  448.         MOV    BX,8
  449.         XOR    AX,AX
  450. IFB1:        ADD    AX,[SI]
  451.         SUB    AX,[SI+2]
  452.         IMUL    WORD PTR [SI+4]
  453.         IDIV    WORD PTR [SI+6]
  454.         ADD    SI,BX
  455.         LOOP    IFB1
  456. ;Go home
  457.         POP    DS
  458.         POP    SI
  459.         POP    CX
  460.         POP    BX
  461.         POP    BP
  462.         RET
  463. _do_ifourbang    ENDP
  464. .8087
  465. ;****************************
  466. ;     init_fpu              *
  467. ;****************************
  468. ; Initialize FPU
  469.     PUBLIC    _init_fpu
  470. _init_fpu    PROC    NEAR
  471.         FINIT
  472.         RET
  473. _init_fpu    ENDP
  474. ;****************************
  475. ;       do_fourbang         *
  476. ;****************************
  477. ; This routine performs the floating-point "four-banger" test.
  478. ; Call with:
  479. ;    do_fourbang(iterations)
  480. ;    uint iterations
  481. ; Where:
  482. ;   Iterations is the number of times to repeat the loop
  483.         PUBLIC    _do_fourbang
  484. NFOURBANGS    equ    [BP+4]
  485. _do_fourbang    PROC    NEAR
  486.         PUSH    BP
  487.         MOV    BP,SP
  488. ;See what kind of coprocessor
  489.         MOV    AX, coproc
  490.         PUSH    DS        ;Swap segment
  491.         MOV    BX,FDATA
  492.         MOV    DS,BX
  493.         CMP    AX,1
  494.         JG      FNLP        ;Do no-waits
  495. ASSUME    DS:FDATA
  496. ;Initialize the result field
  497.         FLDZ
  498.         FSTP    QWORD PTR FRESULT
  499. ;Load loop count
  500.         MOV    CX,NFOURBANGS
  501. ;Do the loops
  502. FLP1:
  503.         FLD    QWORD PTR FRESULT
  504.         FLD    QWORD PTR FAC1
  505.         FADD
  506.         FLD    QWORD PTR FAC2
  507.         FSUB
  508.         FLD    QWORD PTR FAC3
  509.         FMUL
  510.         FLD    QWORD PTR FAC4
  511.         FDIV
  512.         FSTP    QWORD PTR FRESULT
  513.         LOOP    FLP1
  514. ;Return
  515.         POP    DS
  516.         POP    BP
  517.         RET
  518. .387
  519. FNLP:
  520.         FLDZ
  521.         FSTP   QWORD PTR FRESULT
  522.         MOV    CX,NFOURBANGS
  523.         EVEN
  524. FNLP1:          FLD    QWORD PTR FRESULT
  525.         FLD    QWORD PTR FAC1
  526.         FADD
  527.         FLD    QWORD PTR FAC2
  528.         FSUB
  529.         FLD    QWORD PTR FAC3
  530.         FMUL
  531.         FLD    QWORD PTR FAC4
  532.         FDIV
  533.         FSTP    QWORD PTR FRESULT
  534.         LOOP    FNLP1
  535.         POP    DS
  536.         POP    BP
  537.         RET
  538. _do_fourbang    ENDP
  539.  
  540. .8087
  541. ASSUME DS:_DATA
  542. ;****************************
  543. ;     square_fourier        *
  544. ;****************************
  545. ; Fourier series for a square wave of period 2
  546. ; Call with:
  547. ;    square_fourier(ncoeff,coeffarray)
  548. ;    ncoeff = number of coefficients
  549. ;    coeffarray = array of doubles holding results
  550. ; NOte that since the period is 2, omega is 2*pi/period = pi.
  551. ; Knowing this, we advance the i*omega by simply adding pi
  552. ; to that variable on each pass.
  553. ; Hey, it works.
  554. STEPSIZE    equ    501
  555.     PUBLIC    _square_fourier
  556. NCOEFF        equ    [BP+4]
  557. COEFFARRAY    equ    [BP+6]
  558. _square_fourier    PROC    NEAR
  559.         PUSH    BP
  560.         MOV    BP,SP
  561.         PUSH    SI
  562.         MOV    CX,NCOEFF    ;Get # of coefficients
  563.         MOV    SI,COEFFARRAY    ;Pointer to array
  564. ;First calculate a0
  565.         PUSH    CX
  566.         MOV    CX,STEPSIZE    ;Stepsize
  567.         MOV    BX,OFFSET square_wave
  568.         FLD1
  569.         FLD1
  570.         FADD            ;Upper integration limit
  571.         FLDZ            ;Lover limit
  572.         CALL    do_trapezoid    ;Integrate
  573.         FLD1
  574.         FLD1
  575.         FADD
  576.         FDIV            ;Result/2 = a0
  577.         FSTP    QWORD PTR [SI]    ;Save a0
  578.         ADD    SI,4        ;Bump pointer
  579.         POP    CX
  580. ;Set up iw (i omega)
  581.         FLDPI
  582.         FSTP    QWORD PTR IOMEGA
  583. ;Calculate remaining a(i) coefficients
  584. SQF1:        PUSH    CX        ;Save loop counter
  585.         MOV    CX,STEPSIZE    ;Stepsize
  586.         MOV    BX,OFFSET square_cosine
  587.         FLD1
  588.         FLD1
  589.         FADD            ;Upper limit
  590.         FLDZ            ;Lower limit
  591.         CALL    do_trapezoid
  592.         FSTP    QWORD PTR [SI]    ;Store a(i) coefficient
  593.         ADD    SI,4        ;Bump pointer
  594. ;Calculate remaining b(i) coefficients
  595.         MOV    CX,STEPSIZE    ;Intervals
  596.         MOV    BX,OFFSET square_sine
  597.         FLD1
  598.         FLD1
  599.         FADD            ;Upper limit
  600.         FLDZ            ;Lower limit
  601.         CALL    do_trapezoid
  602.         FSTP    QWORD PTR [SI]    ;Store b(i) coefficient
  603.         ADD    SI,4
  604. ;Incremenmt iomega
  605.         FLDPI
  606.         FADD    QWORD PTR IOMEGA
  607.         FSTP    QWORD PTR IOMEGA
  608. ;See if the loop is finished
  609.         POP    CX
  610.         LOOP    SQF1
  611. ;All done - restore
  612.         POP    SI
  613.         POP    BP
  614.         RET
  615. _square_fourier    ENDP
  616.  
  617. ;****************************
  618. ;     square_wave           *
  619. ;****************************
  620. ; A square wave of period 2.  Valid from x=0.0 to x<2.0
  621. ; Wave amplitude is +1/-1
  622. ; On entry:
  623. ;    ST(0)=x
  624. ; On exit
  625. ;    ST(0)=f(x)
  626. square_wave:
  627.     FLD1                ;Get a 1.0 on top
  628.     FCOM                ;See where x is
  629.     FSTSW    FSTATUS
  630.     FWAIT
  631.     MOV    AX,FSTATUS
  632.     AND    AH,01000101B        ;Get condition bits
  633.     FSTP    ST(1)            ;Discard x
  634.     CMP    AH,1
  635.     JNE    SQC2
  636. ;x>1 - return a -1
  637.     FCHS                ;1.0 is now -1.0
  638. SQC2:
  639.     RET
  640.  
  641. ;****************************
  642. ;     square_cosine         *
  643. ;****************************
  644. ; Returns cosine component for fourier series.
  645. ; On entry:
  646. ;     ST(0) = x
  647. ;     IOMEGA = iw
  648. ; On exit:
  649. ;     ST(0) = f(x) * cos(iwx)
  650. ; Where f(x) is a square wave of period 2.
  651. square_cosine:
  652.     FLD    ST(0)            ;Dup x
  653.     FMUL    QWORD PTR IOMEGA        ;iw * x
  654.     CALL    calc_cosine        ;Get cosine of ST(0)
  655. SQC1:    FXCH                ;Swap
  656.     CALL    square_wave        ;Get f(x) on top
  657.     FMUL                ;f(x) * cos(iwx)
  658.     RET
  659.  
  660. ;****************************
  661. ;      square_sine          *
  662. ;****************************
  663. ; On entry:
  664. ;     ST(0) = x
  665. ;     IOMEGA = iw
  666. ; On exit:
  667. ;     ST(0) = f(x) * sin(iwx)
  668. ; Where f(x) is a square wave of period 2.
  669. square_sine:
  670.     FLD    ST(0)            ;Dup x
  671.     FMUL    QWORD PTR IOMEGA    ;iw * x
  672.     CALL    calc_sine        ;sin(iwx)
  673.     JMP    SQC1            ;Link to common code
  674.  
  675. ;****************************
  676. ;      do_trapezoid         *
  677. ;****************************
  678. ; On entry:
  679. ;     CX = number of intervals for integration
  680. ;     BX = pointer to routine that will push the value of f(x)
  681. ;          on the FPU stack.  x will be stored in ST(0).
  682. ;     ST(0) = Lower limit of integration
  683. ;     ST(1) = upper limit of integration
  684. ; On exit:
  685. ;     ST(0) holds value of integration formula
  686. do_trapezoid    PROC    NEAR
  687. ;Save the starting value of x
  688.         FST    QWORD PTR STARTX
  689. ;Calculate the increment width
  690.         FSUB            ;top - bottom
  691.         MOV    FSTATUS,CX    ;Borrow FSTATUS field
  692.         FILD    WORD PTR FSTATUS ;Get n (number of intervals)
  693.         FDIV            ;dx=(top-bottom)/n
  694. ;Get f(bottom)
  695.         FLD    QWORD PTR STARTX
  696.         CALL    BX        ;Call f(x)
  697.         FLD1
  698.         FADD    ST(0),ST    ;Calculate 2.0
  699.         FDIV            ;f(x0)/2
  700.         FXCH    ST(1)        ;-- f(x0)/2 dx
  701.         FLD    QWORD PTR STARTX ; -- f(x0)/2 dx x
  702. ; Stack is now x, dx, f(x0)/2
  703. ; Begin the loop
  704.         DEC    CX
  705. FINTEG1:
  706.         FADD    ST,ST(1)    ;x'=x+dx
  707.         FLD    ST(0)        ;DUP x'
  708.         CALL    BX        ;Get f(x')
  709.         FADDP    ST(3),ST    ;Accumulate and pop f(x)
  710.         LOOP    FINTEG1
  711. ;Calculate f(x)/2 x=endpoint
  712.         FADD    ST,ST(1)
  713.         CALL    BX
  714.         FLD1
  715.         FADD    ST(0),ST
  716.         FDIV            ;Divide by 2
  717.         FADDP    ST(2),ST    ;Accumulate
  718.         FMUL            ;Times dx
  719. ;Return
  720.         RET
  721. do_trapezoid    ENDP
  722.  
  723.  
  724. ;****************************
  725. ;        calc_cosine        *
  726. ;****************************
  727. ; On entry:
  728. ;       x is stored in ST(0)
  729. ; On exit
  730. ;       cosine(x) is stored in ST(0)
  731. ; This routine uses the identities:
  732. ;   cos(x) = cos(x + pi/2)
  733. ;   cos(x) = cos(|x|)
  734. calc_cosine:
  735.     FLD    PIDIV2        ;Load pi/2
  736.     FADDP    ST(1),ST(0)    ;Add to x
  737.     FABS            ;Take absolute value
  738.     CALL    calc_sine
  739.     RET
  740.  
  741. ;****************************
  742. ;        calc_sine          *
  743. ;****************************
  744. ; On entry:
  745. ;    x is stored in ST(0)
  746. ; On exit
  747. ;    sine(x) is stored in ST(0).
  748. ; NOTE: This routine is based on the floating-point routines
  749. ; found in the public-domain FORTH system ABUNDANCE.
  750. calc_sine:
  751.     MOV    AX,coproc
  752.     CMP    AX,3        ;80387?
  753.     JNZ    CSIN0
  754.     JMP    SIN387
  755. CSIN0:
  756.     PUSH    BX
  757.     PUSH    CX
  758.     PUSH    DX
  759.     XOR    DX,DX        ;Clear DX
  760.     FTST
  761.     FSTSW    FSTATUS        ;Store status word
  762.     FWAIT
  763.     MOV    AX,FSTATUS
  764.     SAHF            ;Status in flags
  765.     JAE    CSIN1
  766.     MOV    DL,0FFH        ;Indicate negative
  767.     FABS
  768. ;Set ST(0) between 0 and pi/4
  769. CSIN1:    FLD    DWORD PTR MINUS2
  770.     FLDPI
  771.     FSCALE
  772.     FSTP    ST(1)
  773.     FXCH    ST(1)
  774. CSIN2:    FPREM
  775.     FSTSW    FSTATUS
  776.     FWAIT
  777.     MOV    AX,FSTATUS
  778.     SAHF
  779.     JP    CSIN2        ;Jump if C2!=0
  780.     FTST
  781.     FSTSW    FSTATUS
  782.     FWAIT
  783.     XOR    BX,BX
  784.     AND    FSTATUS,4100H
  785.     MOV    CX,FSTATUS
  786.     CMP    CH,40H
  787.     JNZ    CSIN3
  788.     DEC    BX        ;BX=-1
  789. CSIN3:    TEST    AH,2
  790.     JNZ    CSIN5
  791.     FSTP    ST(1)
  792.     OR    BX,BX
  793.     JZ    CSIN4
  794.     FSTP    ST(0)
  795.     FLDZ
  796.     FLD1
  797.     JMP    CSIN7
  798. CSIN4:    FPTAN
  799.     JMP    CSIN7
  800. CSIN5:    OR    BX,BX
  801.     JNZ    CSIN6
  802.     FSUBP    ST(1),ST(0)
  803.     FPTAN
  804.     JMP    CSIN7
  805. CSIN6:    FSTP    ST(0)
  806.     FSTP    ST(0)
  807.     FLD1
  808.     FLD1
  809. CSIN7:    XOR    BX,BX
  810.     TEST    AH,40H
  811.     JZ    CSIN8
  812.     INC    BX        ;BX=1
  813. CSIN8:    TEST    AH,2
  814.     JZ    CSIN9
  815.     XOR    BX,1
  816.     JMP    CSIN10
  817. CSIN9:
  818. CSIN10:    CMP    BX,1
  819.     JNZ    CSIN11
  820.     FXCH    ST(1)
  821. CSIN11:    FMUL    ST(0),ST(0)
  822.     FLD    ST(1)
  823.     FMUL    ST(0),ST(0)
  824.     FADDP    ST(1),ST(0)
  825.     FSQRT
  826.     FDIVP    ST(1),ST(0)
  827.     TEST    AH,1
  828.     JZ    CSIN12
  829.     NOT    DL
  830. CSIN12:    OR    DL,DH
  831.     JZ    CSIN13
  832.     FCHS
  833. CSIN13:    POP    DX
  834.     POP    CX
  835.     POP    BX
  836.     RET
  837.  
  838. .387
  839. ;**************************************
  840. ;          sine387                    *
  841. ;**************************************
  842. ; Sine routine for 80387
  843. sin387:    FSIN
  844. ;    FSTP    ST(0)
  845.     RET
  846.  
  847. ;**************************************
  848. ;          GRAPHICS BENCHMARKS        *
  849. ;**************************************
  850.  
  851. ;**************************************
  852. ;           random_text               *
  853. ;**************************************
  854. ; Call with:
  855. ;    random_text(rcseg,attrseg,n,vpage)
  856. ; Where:
  857. ;    rcseg = points to array containing row,col coordinate
  858. ;            pairs (column in lo byte, row in high)
  859. ;    attrseg = points to array containing attribute
  860. ;            bytes
  861. ;    nbytes = number of entries
  862. ;    vpage = video page address
  863.     PUBLIC    _random_text
  864. RTEXTRCSEG    equ    [BP+4]
  865. RTEXTATTRSEG    equ    [BP+6]
  866. RTEXTN        equ    [BP+8]
  867. RTEXTVPAGE    equ    [BP+10]
  868. _random_text    PROC    NEAR
  869.         PUSH    BP
  870.         MOV    BP,SP
  871.         PUSH    BX
  872.         PUSH    CX
  873.         PUSH    DX
  874.         PUSH    SI
  875.         PUSH    DI
  876.         PUSH    DS
  877.         PUSH    ES
  878. ; Load up segment registers
  879.         MOV    AX,RTEXTRCSEG
  880.         MOV    DS,AX
  881.         XOR    SI,SI
  882.         MOV    AX,RTEXTATTRSEG
  883.         MOV    ES,AX
  884.         XOR    DI,DI
  885. ;Set count and video page
  886.         MOV    CX,RTEXTN
  887.         MOV    BX,RTEXTVPAGE
  888.         MOV    BH,BL
  889. ;Initialize character
  890.         MOV    AL,'A'
  891. ;Do it
  892. RTXT1:        PUSH    CX
  893.         MOV    DX,[SI]
  894.         MOV    AH,02H
  895.         PUSH    AX
  896.         INT    10H        ;Position cursor
  897.         POP    AX
  898.         MOV    BL,ES:[DI]
  899.         MOV    CX,1
  900.         MOV    AH,09H
  901.         INT    10H        ;Write the character
  902.         INC    SI        ;Bump pointers
  903.         INC    SI
  904.         INC    DI
  905.         INC    AL
  906.         CMP    AL,'['
  907.         JNZ    RTXT2
  908.         MOV    AL,'A'
  909. RTXT2:        POP    CX
  910.         LOOP    RTXT1
  911. ;Done
  912.         POP    ES
  913.         POP    DS
  914.         POP    DI
  915.         POP    SI
  916.         POP    DX
  917.         POP    CX
  918.         POP    BX
  919.         POP    BP
  920.         RET
  921. _random_text    ENDP
  922.  
  923. ;****************************
  924. ;         scroll_text       *
  925. ;****************************
  926. ; Benchmark for text scrolling
  927. ;  Call with:
  928. ;     scroll_text(rcaseg,n,vpage)
  929. ;  Where:
  930. ;     rcaseg = segment holding array of row/col/attrib coordinates
  931. ;     n = number of iterations
  932. ;     vpage = video page
  933. ; This benchmark reads the rcseg array 4 elements at a time.
  934. ; The first elements holds the row/column coordinates of the
  935. ;  upper left corner of the rectangle to scroll, while the
  936. ;  second holds the lower right corner coordinates.
  937. ; The third element holds the number of lines to scroll
  938. ; The fourth holds attribute bytes used for the background fill
  939. ; We assume you've loaded the screen up with stuff before you
  940. ;  call this routine.
  941.     PUBLIC    _scroll_text
  942. SCLTXRCASEG    equ    [BP+4]
  943. SCLTXN        equ    [BP+6]
  944. SCLTXVPAGE    equ    [BP+8]
  945. _scroll_text     PROC    NEAR
  946.         PUSH    BP
  947.         MOV    BP,SP
  948.         PUSH    BX
  949.         PUSH    CX
  950.         PUSH    DX
  951.         PUSH    SI
  952.         PUSH    DS
  953. ;Set up the segment
  954.         MOV    AX,SCLTXRCASEG
  955.         MOV    DS,AX
  956.         XOR    SI,SI
  957. ;Get iteration count
  958.         MOV    CX,SCLTXN
  959. ;Get video page
  960.         MOV    BX,SCLTXVPAGE
  961. ;Do it
  962. SCLTX1:        PUSH    CX
  963. ;Scroll up
  964.         MOV    CX,[SI]        ;Upper left corner
  965.         MOV    DX,[SI+2]    ;Lowr right corner
  966.         MOV    AL,[SI+4]    ;# of lines
  967.         MOV    BH,[SI+5]    ;Attribute
  968.         MOV    AH,06H
  969.         INT    10H
  970. ;Fill up blank area
  971. ;**NOTE: I use [SI+4] in the next line instead of AL, because INT 10H,
  972. ;function 6 on the Model 80 munges AL.  Go figure. --rg
  973.         ADD    CH,[SI+4]    ;Modify ulc
  974.         XCHG    BH,BL
  975.         MOV    AL,'A'
  976.         CALL    FILL_RECT
  977. ;Scroll down
  978.         XCHG    BH,BL
  979.         ADD    SI,6
  980.         MOV    CX,[SI]        ;Upper left corner
  981.         MOV    DX,[SI+2]    ;Lower right corner
  982.         MOV    AL,[SI+4]    ;# of lines
  983.         MOV    BH,[SI+5]    ;Attribute
  984.         MOV    AH,07H
  985.         INT    10H
  986. ;Fill up blank area
  987.         SUB    DH,[SI+4]    ;MOdify lower right corner
  988.         XCHG    BH,BL
  989.         MOV    AL,'B'
  990.         CALL    FILL_RECT
  991. ;See if we're done
  992.         XCHG    BH,BL
  993.         ADD    SI,6
  994.         POP    CX
  995.         LOOP    SCLTX1
  996. ;Go home
  997.         POP    DS
  998.         POP    SI
  999.         POP    DX
  1000.         POP    CX
  1001.         POP    BX
  1002.         POP    BP
  1003.         RET
  1004. _scroll_text    ENDP
  1005.  
  1006. ;Fill_rect
  1007. ; Called by the scroll routine to fill the blank lines created
  1008. ; when a window is scrolled.
  1009. ; On entry:
  1010. ;  CH,CL = row/column of ulhc of rectangle
  1011. ;  DH,CL = row/column of lrhc of rectangle
  1012. ;  AL = character to write
  1013. ;  BL = attribute
  1014. ;  BH = video page
  1015. FILL_RECT    PROC    NEAR
  1016. ;Calculate number of columns
  1017.         MOV    AH,DL
  1018.         SUB    AH,CL
  1019.         INC    AH
  1020.         MOV    DL,CL
  1021. FRECT1:        CMP    DH,CH
  1022.         JA    FRECT2
  1023.         RET
  1024. FRECT2:
  1025.         PUSH    AX
  1026. ;Set cursor
  1027.         MOV    AH,2
  1028.         INT    10H
  1029. ;Write characters
  1030.         POP    AX
  1031.         PUSH    CX
  1032.         MOV    CL,AH
  1033.         XOR    CH,CH
  1034.         MOV    AH,9
  1035.         INT    10H
  1036.         MOV    AH,CL
  1037.         POP    CX
  1038. ;Increment location
  1039.         DEC    DH
  1040.         JMP    FRECT1
  1041. FILL_RECT    ENDP
  1042.  
  1043. ;****************************
  1044. ;        draw_circle        *
  1045. ;****************************
  1046. ; Call with:
  1047. ;  draw_circle (cx,cy,r,color,mode,esseg)
  1048. ; Where:
  1049. ;    cx,cy are coordinates of center
  1050. ;    r is circle radius in pixels
  1051. ;    color is color
  1052. ;    mode is current graphics mode
  1053. ;    esseg is graphics segment
  1054.     PUBLIC    _draw_circle
  1055. DCX        equ    [BP+4]
  1056. DCY        equ    [BP+6]
  1057. DCR        equ    [BP+8]
  1058. DCCOLOR        equ    [BP+10]
  1059. DCMODE        equ    [BP+12]
  1060. DCESSEG        equ    [BP+14]
  1061. _draw_circle    PROC    NEAR
  1062.         PUSH    BP
  1063.         MOV    BP,SP
  1064.         PUSH    BX
  1065.             PUSH    CX
  1066.         PUSH    DX
  1067.         PUSH    SI
  1068.         PUSH    DI
  1069.         PUSH    ES
  1070. ;Set up graphics segment
  1071.         MOV    AX,DCESSEG
  1072.         MOV    ES,AX
  1073. ;Do initial 4 corners
  1074.         MOV    AX,DCY        ;Initial y coord
  1075.         MOV    BX,DCX        ;Initial x coord
  1076.         ADD    BX,DCR        ;add radius
  1077.         MOV    CX,DCMODE
  1078.         MOV    DX,DCCOLOR
  1079.         CALL    SETPIXEL        ;One corner
  1080.         MOV    BX,DCX
  1081.         SUB    BX,DCR
  1082.         CALL    SETPIXEL        ;another
  1083.         MOV    BX,DCX
  1084.         ADD    AX,DCR
  1085.         CALL    SETPIXEL        ;Another
  1086.         MOV    AX,DCY
  1087.         SUB    AX,DCR
  1088.         CALL    SETPIXEL        ;And another
  1089. ;Do arc from 0 to 45 degrees and reflect
  1090.         MOV    SI,DCR        ;x offset
  1091.         XOR    DI,DI        ;y offset
  1092.         MOV    DX,DI        ;rate of change
  1093. DRC1:        ADD    DX,DI        ;dv=dv+y+y+1
  1094.         ADD    DX,DI
  1095.         INC    DX
  1096.         INC    DI        ;y+=1
  1097.         CMP    DX,SI        ;dv>x?
  1098.         JLE    DRC2
  1099.         SUB    DX,SI        ;dv=dv-x-x+1
  1100.         SUB    DX,SI
  1101.         INC    DX
  1102.         DEC    SI        ;x-=1
  1103. ;Now do reflections
  1104. DRC2:        PUSH    DX        ;Save rate of change
  1105.         MOV    DX,DCCOLOR    ;Reload color
  1106.         MOV    AX,DCY
  1107.         MOV    BX,DCX
  1108.         ADD    BX,SI
  1109.         ADD    AX,DI
  1110.         CALL    SETPIXEL
  1111.         SUB    AX,DI
  1112.         SUB    AX,DI
  1113.         CALL    SETPIXEL
  1114.         SUB    BX,SI
  1115.         SUB    BX,SI
  1116.         CALL    SETPIXEL
  1117.         ADD    AX,DI
  1118.         ADD    AX,DI
  1119.         CALL    SETPIXEL
  1120. ;If x!=y, do other reflections
  1121.         CMP    SI,DI
  1122.         JZ    DRC3
  1123.         MOV    AX,DCY
  1124.         MOV    BX,DCX
  1125.         ADD    AX,SI
  1126.         ADD    BX,DI
  1127.         CALL    SETPIXEL
  1128.         SUB    AX,SI
  1129.         SUB    AX,SI
  1130.         CALL    SETPIXEL
  1131.         SUB    BX,DI
  1132.         SUB    BX,DI
  1133.         CALL    SETPIXEL
  1134.         ADD    AX,SI
  1135.         ADD    AX,SI
  1136.         CALL    SETPIXEL
  1137. ;See if done
  1138. DRC3:        POP    DX        ;Restore rate of change
  1139.         CMP    DI,SI        ;y=x?
  1140.         JB    DRC1
  1141. ;Go home
  1142.         POP    ES
  1143.         POP    DI
  1144.         POP    SI
  1145.         POP    DX
  1146.         POP    CX
  1147.         POP    BX
  1148.         POP    BP
  1149.         RET
  1150. _draw_circle    ENDP
  1151.  
  1152. ;****************************
  1153. ;      do_flood             *
  1154. ;****************************
  1155. ; Call with:
  1156. ;   do_flood(x,y,color,mode,floodseg,esseg)
  1157. ;    x,y coordinates within bounded region to flood
  1158. ;    color - color to flood with
  1159. ;    mode - graphics mode
  1160. ;    floodseg - use in place of recursive calls; this is
  1161. ;               the pointer to a segment where intermediate
  1162. ;               values will be stored
  1163. ;    esseg - graphics segment
  1164. ; NOTE: This fellow does NOT check for out-of-screen bounds
  1165. ;  condition.  Region MUST be bounded.
  1166.     PUBLIC    _do_flood
  1167. DOFLX        equ    [BP+4]
  1168. DOFLY        equ    [BP+6]
  1169. DOFLCOLOR    equ    [BP+8]
  1170. DOFLMODE    equ    [BP+10]
  1171. DOFLSEG        equ    [BP+12]
  1172. DOFLESSEG    equ    [BP+14]
  1173. _do_flood    PROC    NEAR
  1174.         PUSH    BP
  1175.         MOV    BP,SP
  1176.         PUSH    BX
  1177.         PUSH    CX
  1178.         PUSH    DX
  1179.         PUSH    SI
  1180.         PUSH    DS
  1181.         PUSH    ES
  1182. ;Set segment for temporaries
  1183.         MOV    AX,DOFLSEG
  1184.         MOV    DS,AX
  1185. ;Set up graphics segment
  1186.         MOV    AX,DOFLESSEG
  1187.         MOV    ES,AX
  1188.         XOR    SI,SI
  1189. ;Initialize coordinates and stuff
  1190.         MOV    BX,DOFLX
  1191.         MOV    AX,DOFLY
  1192.         MOV    CX,DOFLMODE
  1193. ;Set current pixel
  1194. DOFL1:        MOV    DX,DOFLCOLOR
  1195.         CALL    SETPIXEL
  1196. ;See if pixel above is filled
  1197.         DEC    AX
  1198.         CALL    TESTNPUSH
  1199. ;See if pixel to right is filled
  1200.         INC    AX
  1201.         INC    BX
  1202.         CALL    TESTNPUSH
  1203. ;See if pixel below is filled
  1204.         INC    AX
  1205.         DEC    BX
  1206.         CALL    TESTNPUSH
  1207. ;See if pixel to left is filled
  1208.         DEC    AX
  1209.         DEC    BX
  1210.         CALL    TESTNPUSH
  1211. ;Anything on pixel stack?
  1212.         OR    SI,SI
  1213.         JZ    DOFL9
  1214. ;Something there...fetch and loop
  1215.         SUB    SI,4
  1216.         MOV    AX,[SI]
  1217.         MOV    BX,[SI+2]
  1218.         JMP    DOFL1
  1219. ;Go home
  1220. DOFL9:
  1221.         POP    ES
  1222.         POP    DS
  1223.         POP    SI
  1224.         POP    DX
  1225.         POP    CX
  1226.         POP    BX
  1227.         POP    BP
  1228.         RET
  1229. _do_flood    ENDP
  1230.  
  1231. ; TESTNPUSH
  1232. ; This routine is used by do_flood to see if a pixel should
  1233. ; be filled.  If the pixel qualified, it is "pushed" onto a
  1234. ; pixel stack pointed to by DS:SI
  1235. TESTNPUSH    PROC    NEAR
  1236.         PUSH    SI        ;Save
  1237.         CALL    GETP        ;Get pixel's color
  1238.         POP    SI
  1239.         XOR    DH,DH        ;Clear hi byte
  1240.         CMP    DX,DOFLCOLOR    ;Match?
  1241.         JZ    TNPX        ;Already filled if match
  1242.         MOV    [SI],AX        ;Push y coordinate
  1243.         MOV    [SI+2],BX    ;Push x coordinate
  1244.         ADD    SI,4        ;Increment "stack" pointer
  1245. TNPX:        RET
  1246. TESTNPUSH    ENDP
  1247.  
  1248. ;**************************************
  1249. ;            DISK BENCHMARKS          *
  1250. ;**************************************
  1251.  
  1252. ;****************************
  1253. ;     rand_cyl_seek         *
  1254. ;****************************
  1255. ; Random cylinder seek benchmark.
  1256. ; Call with:
  1257. ;   rand_cyl_seek(arrayseg,size,buffseg,drivenum)
  1258. ; Where:
  1259. ;    arrayseg = pointer to segment holding array of random
  1260. ;               integers
  1261. ;    size = number of elements in the array
  1262. ;    buffseg = pointer to segment that will be the read buffer
  1263. ;              (In this case, 512 bytes is all you need )
  1264. ;    drivenum = drive number (0=first fixed disk, 1=second)
  1265. ; NOTE: Elements in arrayseg must already be in cylinder/sector
  1266. ;       format.
  1267.         PUBLIC    _rand_cyl_seek
  1268. RCYLARRAYSEG    equ    [BP+4]
  1269. RCYLARRAYSIZE    equ    [BP+6]
  1270. RCYLBUFFSEG    equ    [BP+8]
  1271. RCYLDRIVE    equ    [BP+10]
  1272. _rand_cyl_seek    PROC    NEAR
  1273.         PUSH    BP
  1274.         MOV    BP,SP
  1275.         PUSH    BX
  1276.         PUSH    CX
  1277.         PUSH    DX
  1278.         PUSH    SI
  1279.         PUSH    ES
  1280.         PUSH    DS
  1281. ;Load count
  1282.         MOV    CX,RCYLARRAYSIZE
  1283. ;Load segment of random numbers and initialize pointer
  1284.         MOV    AX,RCYLARRAYSEG
  1285.         MOV    DS,AX
  1286.         XOR    SI,SI
  1287. ;Load the buffer segment
  1288.         MOV    AX,RCYLBUFFSEG
  1289.         MOV    ES,AX
  1290.         XOR    BX,BX
  1291. ;Load drive and head number
  1292.         MOV    DX,RCYLDRIVE
  1293.         OR    DL,80H
  1294.         XOR    DH,DH
  1295. ;Do it
  1296. RCYL1:        PUSH    CX        ;Save loop count
  1297.         MOV    CX,[SI]        ;Get cylinder
  1298.         MOV    AH,2
  1299.         MOV    AL,1        ;1 sector
  1300.         INT     13H
  1301.         POP    CX
  1302.         JC    RCYLE        ;Bum out if error
  1303.         INC    SI
  1304.         INC    SI
  1305.         LOOP    RCYL1
  1306.         XOR    AX,AX        ;show all ok
  1307. RCYLX:        POP    DS
  1308.         POP    ES
  1309.         POP    SI
  1310.         POP    DX
  1311.         POP    CX
  1312.         POP    BX
  1313.         POP    BP
  1314.         RET
  1315. RCYLE:        MOV    AL,AH        ;Move error to lo byte
  1316.         XOR    AH,AH
  1317.         JMP    RCYLX        ;Return with error
  1318. _rand_cyl_seek    ENDP
  1319.  
  1320. ;****************************
  1321. ;        hd_rread           *
  1322. ;****************************
  1323. ; Hard disk random read benchmark.
  1324. ; This test performs a series of seeks to sector 1 head 0
  1325. ; for the random cylinder numbers held in arrayseg.
  1326. ;  Call with:
  1327. ;    hd_rread(drive,arrayseg,buffseg,n)
  1328. ;  Where:
  1329. ;    drive = drive number
  1330. ;    arrayseg = segment of array of random cylinder numbers
  1331. ;    nsecseg= number of sectors segment
  1332. ;    buffseg = segment to act as read buffer
  1333. ;    n = number of iterations
  1334. ; Returns nonzero error code if something happened, else
  1335. ; returns error.
  1336.     PUBLIC    _hd_rread
  1337. HDDRIVE        equ    [BP+4]
  1338. HDARRAYSEG    equ    [BP+6]
  1339. HDBUFFSEG    equ    [BP+8]
  1340. HDN        equ    [BP+10]
  1341. _hd_rread    PROC    NEAR
  1342.         PUSH    BP
  1343.         MOV    BP,SP
  1344.         PUSH    BX
  1345.         PUSH    CX
  1346.         PUSH    DX
  1347.         PUSH    SI
  1348.         PUSH    DS
  1349.         PUSH    ES
  1350. ;Load count
  1351.         MOV    CX,HDN
  1352. ;Load segment of random numbers and initialize pointer
  1353.         MOV    AX,HDARRAYSEG
  1354.         MOV    DS,AX
  1355.         XOR    SI,SI
  1356. ;Fix buffer pointer
  1357.         MOV    AX,HDBUFFSEG
  1358.         MOV    ES,AX
  1359.         XOR    BX,BX
  1360. ;Load drive number
  1361.         MOV    DX,HDDRIVE
  1362.         XOR    DH,DH
  1363. ;Do it
  1364. HDRRD1:        PUSH    CX
  1365.         MOV    CX,[SI]
  1366.         MOV    AX,[SI+2]
  1367.         MOV    AH,2        ;Set code
  1368.         INT    13H        ;Call interrupt
  1369.         POP    CX
  1370. ;        JC    HDRRDERR    ;Jump if error
  1371.         ADD    SI,4
  1372.         LOOP    HDRRD1
  1373.         XOR    AX,AX        ;All ok
  1374. ;Exit
  1375. HDRRDX:
  1376.         POP    ES
  1377.         POP    DS
  1378.         POP    SI
  1379.         POP    DX
  1380.         POP    CX
  1381.         POP    BX
  1382.         POP    BP
  1383.         RET
  1384. ; HDRRDERR:    MOV    AX,CX
  1385. ;        MOV    AL,AH         ;Error code in AX
  1386. ;        XOR    AH,AH
  1387. ;        JMP    HDRRDX
  1388. _hd_rread    ENDP
  1389.  
  1390. ;***************************
  1391. ;     hd_1seek             *
  1392. ;***************************
  1393. ; Call with:
  1394. ;       hd_1seek(drive,cyl,bufseg)
  1395. ;    drive = drive to seek on
  1396. ;    cyl = cylinder to seek to (head 0, sector 1)
  1397. ;    bufseg = seg. of buffer to hold 1 sector
  1398. ;
  1399. HD1DRIVE    =    [BP+4]
  1400. HD1CYL        =    [BP+6]
  1401. HD1SEG        =    [BP+8]
  1402.         PUBLIC    _hd_1seek
  1403. _hd_1seek    PROC    NEAR
  1404.         PUSH    BP
  1405.         MOV    BP,SP
  1406.         PUSH    BX
  1407.         PUSH    CX
  1408.         PUSH    DX
  1409.         PUSH    ES
  1410. ; Set up segments
  1411.         MOV    AX,HD1SEG
  1412.         MOV    ES,AX
  1413. ; Zero offset
  1414.         XOR    BX,BX
  1415. ;Set up drive
  1416.         MOV    DX,HD1DRIVE
  1417.         XOR    DH,DH        ;Head 0
  1418.         MOV    CX,HD1CYL    ;Cylinder
  1419.         MOV    AX,CX
  1420.         SHR    AX,1
  1421.         SHR    AX,1
  1422.         MOV    CH,CL        ;Adjust
  1423.         MOV    CL,AH
  1424.         AND    CL,0C0H
  1425.         INC    CL
  1426.         MOV    AL,1
  1427.         MOV    AH,2
  1428.         INT    13H
  1429.         JC    HD1SERR
  1430.  
  1431. HD1SEX:        POP    ES
  1432.         POP    DX
  1433.         POP    CX
  1434.         POP    BX
  1435.         POP    BP
  1436.         RET
  1437. HD1SERR:    MOV    AL,AH
  1438.         XOR    AH,AH
  1439.         JMP    HD1SEX
  1440. _hd_1seek    ENDP
  1441.  
  1442. ;**************************************
  1443. ;        EMS FUNCTIONS FOLLOW         *
  1444. ;**************************************
  1445.  
  1446. ;****************************
  1447. ;       do_ems              *
  1448. ;****************************
  1449. ; Call with:
  1450. ;    do_ems(pfseg,numpages,memseg,width)
  1451. ;    pfseg is the page frame segment address
  1452. ;    numpages is number of EMS pages to allocate per handle
  1453. ;    memseg is pointer to a 16K segment in conventional memory
  1454. ;    width is transfer width -1=byte, 0=word, 1=doubleword
  1455. ; This fellow runs the following test
  1456. ;   1. Create two handles, allocating to each numpages EMS
  1457. ;      pages
  1458. ;   2. Copy contents of memseg into first handle's EMS memory
  1459. ;   3. Copy contents of memseg into second handle's EMS memory
  1460. ;   4. Copy entire contents of second handle's EMS memory back
  1461. ;      into first.
  1462. ;   5. Deallocate pages
  1463. ;
  1464.     PUBLIC    _do_ems
  1465. PFSEG        equ    [BP+4]
  1466. NUMPAGES    equ    [BP+6]
  1467. MEMSEG        equ    [BP+8]
  1468. EMSWIDTH    equ    [BP+10]
  1469. _do_ems    PROC    NEAR
  1470. ;Save registers
  1471.     PUSH    BP
  1472.     MOV    BP,SP
  1473.     PUSH    BX
  1474.     PUSH    CX
  1475.     PUSH    DX
  1476.     PUSH    SI
  1477.     PUSH    DI
  1478.     PUSH    ES
  1479.     PUSH    DS
  1480. ;Allocate numpages for handle 1
  1481.     MOV    AH,43H
  1482.     MOV    BX,NUMPAGES
  1483.     INT    67H
  1484.     OR    AH,AH        ;Any errors?
  1485.     JZ    DOEMS1
  1486.     MOV    AL,1        ;Phase in AL
  1487.     JMP    EMSERR
  1488. DOEMS1:    MOV    HANDLE1,DX
  1489. ;Allocate numpages for handle 2
  1490.     MOV    AH,43H
  1491.     MOV    BX,NUMPAGES
  1492.     INT    67H
  1493.     OR    AH,AH        ;All ok?
  1494.     JZ    DOEMS2
  1495.     MOV    AL,2
  1496.     JMP    EMSERR
  1497. DOEMS2:    MOV    HANDLE2,DX
  1498. ;Load handle 1 up with information
  1499.     MOV    DX,HANDLE1
  1500.     CALL    LOAD_HANDLE
  1501.     OR    AX,AX
  1502.     JZ    DOEMS3
  1503.     MOV    AL,3        ;Error in phase 3
  1504.     JMP    EMSERR
  1505. ;Load handle 2 with information
  1506. DOEMS3:    MOV    DX,HANDLE2
  1507.     CALL    LOAD_HANDLE
  1508.     OR    AX,AX
  1509.     JZ    DOEMS4
  1510.     MOV    AL,4        ;Error in phase 4
  1511.     JMP    EMSERR
  1512. ;Copy handle 2's contents into handle 1
  1513. DOEMS4:    MOV    AX,PFSEG
  1514.     MOV    DS,AX        ;Set up source
  1515.     ADD    AX,1024        ;Destination is 2nd page in frame
  1516.     MOV    ES,AX
  1517. ;
  1518.     XOR    BX,BX
  1519. DOEMS5:    PUSH    BX        ;Save number of pages
  1520. ;Map handle 2's page in
  1521.     XOR    AL,AL        ;Physical page 0
  1522.     MOV    AH,44H        ;Interrupt
  1523.     INT    67H
  1524.     OR    AH,AH        ;All ok?
  1525.     JZ    DOEMS6
  1526.     MOV    AL,5        ;Error in phase 5
  1527.     JMP    EMSERR    
  1528. ;Map handle 1's page in
  1529. DOEMS6:
  1530.     MOV    AL,1        ;Physical page 1
  1531.     MOV    AH,44H        ;Interrupt
  1532.     INT    67H
  1533.     OR    AH,AH        ;All ok?
  1534.     JZ    DOEMS7
  1535.     MOV    AL,6        ;Error in phase 6
  1536.     JMP    EMSERR
  1537. ;Copy stuff
  1538. DOEMS7:
  1539.     CALL    COPYPAGE
  1540. ;See if done
  1541.     POP    BX
  1542.     INC    BX
  1543.     CMP    BX,NUMPAGES
  1544.     JL    DOEMS5
  1545. ;All done with copy - deallocate
  1546.     CALL    DEALLOC_PAGES
  1547. ;Show all ok
  1548.     XOR    AX,AX
  1549. ;Restore registers and exit
  1550. EMSXIT:
  1551.     POP    DS
  1552.     POP    ES
  1553.     POP    DI
  1554.     POP    SI
  1555.     POP    DX
  1556.     POP    CX
  1557.     POP    BX
  1558.     POP    BP
  1559.     RET
  1560. ;Error exit
  1561. EMSERR:
  1562.     XCHG    AH,AL
  1563.     PUSH    AX
  1564.     CALL    DEALLOC_PAGES
  1565.     JMP    EMSXIT
  1566. _do_ems    ENDP
  1567.  
  1568. ;****************************
  1569. ;     dealloc_pages         *
  1570. ;****************************
  1571. DEALLOC_PAGES    PROC    NEAR
  1572.     MOV    DX,HANDLE1
  1573.     MOV    AH,45H
  1574.     INT    67H
  1575.     MOV    DX,HANDLE2
  1576.     MOV    AH,45H
  1577.     INT    67H
  1578.     RET
  1579. DEALLOC_PAGES    ENDP
  1580.  
  1581. ;****************************
  1582. ;     load_handle           *
  1583. ;****************************
  1584. ; Call with:
  1585. ;   DX = handle number to load
  1586. ; Returns:
  1587. ;   AX = 0 if ok, else error
  1588. LOAD_HANDLE    PROC    NEAR
  1589. ;Load up segment registers
  1590.     MOV    AX,MEMSEG
  1591.     MOV    DS,AX        ;Memory segment
  1592.     MOV    AX,PFSEG
  1593.     MOV    ES,AX        ;Page frame segment
  1594.     XOR    BX,BX        ;Start at page 0
  1595. LOADHAN1:
  1596.     PUSH    BX
  1597.     XOR    AL,AL        ;Physical page 0
  1598.     MOV    AH,44H        ;Interrupt
  1599.     INT    67H
  1600.     OR    AH,AH        ;All ok?
  1601.     JZ    LOADHAN2
  1602.     POP    BX        ;Clear stack
  1603.     JMP    LOADHANX    ;Error exit
  1604. ;Page now in page frame, copy stuff in
  1605. LOADHAN2:
  1606.     CALL    COPYPAGE
  1607. ;Move to next frame
  1608.     POP    BX
  1609.     INC    BX
  1610.     CMP    BX,NUMPAGES
  1611.     JL    LOADHAN1
  1612.     XOR    AX,AX        ;All ok
  1613. LOADHANX:
  1614.     RET
  1615. LOAD_HANDLE    ENDP
  1616.  
  1617. ;****************************
  1618. ;       copypage            *
  1619. ;****************************
  1620. ; Copies one page.  It is the caller's responsibility to set
  1621. ; up the segment registers appropriately
  1622. COPYPAGE    PROC    NEAR
  1623. ;Set up common stuff
  1624.     MOV    AX,EMSWIDTH    ;Copy width?
  1625.     OR    AX,AX
  1626.     JS    COPYBYTE
  1627.     JZ    COPYWORD
  1628. ;Doubleword copy (386/486 only! )
  1629. .386
  1630.     MOV    CX,4096        ;Number of doublewords
  1631.     XOR    ESI,ESI
  1632.     XOR    EDI,EDI
  1633.      REP    MOVSD
  1634.     RET
  1635. .8086
  1636. ;Word-wide copy
  1637. COPYWORD:
  1638.     MOV    CX,8192
  1639.     XOR    SI,SI
  1640.     XOR    DI,DI
  1641.     REP    MOVSW
  1642.     RET
  1643. ;Byte-wide copy
  1644. COPYBYTE:
  1645.     MOV    CX,16384
  1646.     XOR    SI,SI
  1647.     XOR    DI,DI
  1648.     REP    MOVSB
  1649.     RET
  1650. COPYPAGE    ENDP
  1651.  
  1652. ;
  1653. ; void start_timer(void)
  1654. ; call as:
  1655. ;    start_timer()
  1656.     public    _start_timer
  1657. _start_timer    proc    near
  1658.  
  1659.     push    ax
  1660.     push    dx
  1661.     push    ds
  1662. ;clear the accumulators
  1663.     mov    timer_micro,0
  1664.     mov    timer_milli,0
  1665.     mov    timer_sec,0
  1666. ;initialize counter 0 of 8253 timer
  1667.     mov    al,00110100b        ;ctr 0, lsb then msb,
  1668.                     ;...mode 2, binary
  1669.     out    TIMER_MODE,al        ;mode register for 8253
  1670.     sub    ax,ax            ;0 results in max count
  1671.     out     TIMER0,al        ; lsb
  1672.     out    TIMER0,al        ; msb
  1673.  
  1674. ;read current bios time-of-day
  1675.     mov    dx,BIOS_DATASEG
  1676.     mov    ds,dx
  1677.     mov    ax, ds:[BIOS_TIME_LO]
  1678.     pop    ds            ;restore my ds
  1679.     mov    count_low,ax
  1680.     pop    dx
  1681.     pop    ax
  1682.     ret
  1683. _start_timer    endp
  1684.  
  1685. ;
  1686. ; void stop_timer (unsigned int *)
  1687. ; call:
  1688. ;   stop_timer(tarray)
  1689. ; where:
  1690. ;   tarray is defined as    unsigned int tarray[3]
  1691. ;   tarray[0]=elapsed time, microseconds
  1692. ;   tarray[1]=elapsed time, milliseconds
  1693. ;   tarray[2]=elapsed time, seconds
  1694. ;
  1695.  
  1696.     public    _stop_timer
  1697. _stop_timer     proc     near
  1698.     push    bp
  1699.     mov    bp,sp
  1700.     push    ax
  1701.     push    bx
  1702.     push    cx
  1703.     push    dx
  1704.     push    di
  1705.     push    si
  1706. ;read counter 0 of 8253 timer
  1707.     xor    al,al        ;latch counter for read
  1708.     cli            ;interrupts off
  1709.     out    TIMER_MODE,al
  1710.     in    al,TIMER0
  1711.     mov    dl,al
  1712.     in    al,TIMER0
  1713.     mov    dh,al        ;dx has 16-bit timer count
  1714.  
  1715. ; we'll defer calculations till after sti
  1716.     mov    svd_8253_count, dx
  1717.  
  1718. ;get bios time
  1719.     push    ds        ;save my data seg
  1720.     mov    dx,BIOS_DATASEG
  1721.     mov    ds,dx
  1722.     mov    ax,ds:[BIOS_TIME_LO]
  1723.     pop    ds
  1724.     sti            ;ints ok now
  1725.     sub    ax,count_low
  1726.     mul    count_convert
  1727.     cmp    dx, 1000
  1728.     jb    no_overflow
  1729.  
  1730. ; dx is too large, need to pre-divide by 1000
  1731.  
  1732.     push    cx    ; use cx as swapping reg
  1733.     push    ax    ; save current low word microsecs
  1734.     mov    ax, dx    ; move hi word microsecs to dividend
  1735.     xor    dx, dx    
  1736.     div    thousand    ; now ax = hi word millis, dx = hi w micros
  1737.     mov    cx, ax        ; save hi word millis
  1738.     pop    ax        ; pop low word microsecs to dividend lo
  1739.     div    thousand
  1740.     mov    count_micro, dx ; save microseconds
  1741.     mov    dx, cx        ; now dx=count_milli_hi, ax=count_milli_lo
  1742.     div    thousand    ; now ax=count secs, dx=count_milli
  1743.     mov    count_milli, dx
  1744.     mov    timer_sec, ax
  1745.     pop    cx
  1746. jmp    short    gotcount
  1747.  
  1748. no_overflow:
  1749.     div    thousand
  1750.     mov    count_milli,ax    ;save milliseconds
  1751.     mov    count_micro,dx    ;save microseconds
  1752. gotcount:
  1753.  
  1754. ;calc time from 8253
  1755.     mov    dx, svd_8253_count
  1756.     or    ax, MAX_COUNT
  1757.     sub    ax,dx        ;timer count value
  1758.     mul    timer_convert    ;<10000, so overflow not possible
  1759.     div    ten_thousand    ;give time in usec
  1760.     mov    timer_micro,ax    ;save usec, round nsec
  1761.     cmp    dx,five_thousand
  1762.     jb    cont
  1763.     inc    timer_micro    ;round up
  1764. cont:
  1765.  
  1766. ;restore bios numbers
  1767.  
  1768.     mov    ax, count_milli
  1769.     mov    dx, count_micro
  1770.  
  1771. ;check for jitter
  1772.  
  1773.     cmp    timer_sec, 0
  1774.     jne    jitter_ok
  1775.     cmp    ax,0
  1776.     jne    jitter_ok
  1777.     mov    ax,_timeradjust
  1778.     cmp    timer_micro,ax
  1779.     jae    jitter_ok
  1780.     mov    timer_micro,ax
  1781.  
  1782. ;put results in timer variables
  1783. jitter_ok:
  1784.     mov    ax,dx        ;get count_micro
  1785.     add    ax,timer_micro    ;sum micro fields
  1786.     cmp    ax,_timeradjust    ;check for underflow
  1787.     jae    compensate
  1788.     dec    count_milli    ;borrow
  1789.     add    ax,1000
  1790. compensate:
  1791.     sub    ax,_timeradjust    ;compensate for timer delays
  1792.     mov    timer_micro,ax
  1793.     cmp    ax,1000        ;check field overflow
  1794.     jb    fld_ok        ;timer micro field ok
  1795.     sub    dx,dx        ;too large
  1796.     div    thousand    ;so carry out into timer_milli
  1797.     mov    timer_milli,ax
  1798.     mov    timer_micro,dx
  1799. fld_ok:
  1800.     mov    ax,count_milli    ;sum milli field
  1801.     add    timer_milli,ax
  1802.     cmp    timer_milli,1000    ;check as above
  1803.     jb    goback
  1804.     sub    dx,dx
  1805.     mov    ax,timer_milli
  1806.     div    thousand
  1807.     add    timer_sec,ax
  1808.     mov    timer_milli,dx
  1809. ;send it all back
  1810. goback:
  1811.     push    ds
  1812.     pop    es
  1813.     mov    di, [bp+4]        ;pointer to array
  1814.     mov    si, offset timer_micro
  1815.     movsw
  1816.     movsw
  1817.     movsw
  1818.     pop    si
  1819.     pop    di
  1820.     pop    dx
  1821.     pop    cx
  1822.     pop    bx
  1823.     pop    ax
  1824.     pop    bp
  1825.     ret
  1826. _stop_timer    endp
  1827.  
  1828.  
  1829. ;****************************
  1830. ;           setp            *
  1831. ;****************************
  1832. ; Set pixel at x,y to color. Mode is mode #.
  1833. ; Call with:
  1834. ;   AX = y coordinate of pixel to set
  1835. ;   BX = x coordinate of pixel to set
  1836. ;   CX = mode
  1837. ;   DX = color
  1838. ; NOTE:
  1839. ;  This routine assumes that ES points to the current video
  1840. ;  page.  It is the caller's job to do this.
  1841. SETPIXEL    PROC    NEAR
  1842.         PUSH    AX
  1843.         PUSH    BX
  1844.         PUSH    CX
  1845.         PUSH    DX
  1846. ;Determine which routine to execute using mode
  1847. ;First check for Hercules
  1848.         CMP    CL,255
  1849.         JNE    SETPIXEL10
  1850. ;
  1851. ; Hercules mode
  1852.         CALL CALCPH
  1853. SETPIXEL01:
  1854.         SHL    DX,CL        ;Shift color
  1855.         NOT    DH
  1856.         AND    ES:[BX],DH    ;Zero the pixel
  1857.         OR    ES:[BX],DL    ;Set it
  1858. SETPIXEXIT:
  1859.         POP    DX
  1860.         POP    CX
  1861.         POP    BX
  1862.         POP    AX
  1863.         RET
  1864. ;
  1865. SETPIXEL10:
  1866.         CMP    CL,6
  1867.         JGE    SETPIXEL20
  1868. ;
  1869. ;Modes 4 and 5
  1870. ;
  1871.         CALL     CALCP4
  1872.         JMP    SHORT SETPIXEL01    ;Borrow code
  1873. ;
  1874. SETPIXEL20:
  1875.         CMP    CL,13
  1876.         JGE    SETPIXEL30
  1877. ;
  1878. ;Mode 6
  1879. ;
  1880.         CALL     CALCP6
  1881.         JMP    SHORT SETPIXEL01    ;Borrow code
  1882. ;
  1883. SETPIXEL30:
  1884.         CMP    CL,14
  1885.         JGE    SETPIXEL40
  1886. ;
  1887. ;Mode 13
  1888. ;
  1889.         CALL     CALCP13
  1890. SETPIXEL31:
  1891.         SHL    DH,CL        ;Position mask
  1892.         MOV    CX,DX        ;Move mask/color to safety
  1893.         MOV    AH,DH
  1894.         MOV    DX,3CEH        ;Address register port
  1895.         MOV    AL,8        ;Mask register number
  1896.         OUT    DX,AX
  1897.         MOV    AX,205H        ;Mode register number 2, write mode 2
  1898.         OUT    DX,AX
  1899.         MOV    AH,0        ;Replace mode
  1900.         MOV    AL,3        ;Data rotate/function select register
  1901.         OUT    DX,AX
  1902.         MOV    AL,ES:[BX]    ;Load the latches
  1903.         MOV    ES:[BX],CL    ;Store it
  1904.         MOV    AX,0FF08H    ;Restore defaults
  1905.         OUT    DX,AX
  1906.         MOV    AX,5
  1907.         OUT    DX,AX
  1908.         MOV    AX,3
  1909.         OUT    DX,AX
  1910.         JMP    SETPIXEXIT
  1911. ;
  1912. SETPIXEL40:
  1913.         CMP    CL,17
  1914.         JGE    SETPIXEL50
  1915. ;
  1916. ; Modes 14,15,16
  1917. ;
  1918. SETPIXEL41:
  1919.         CALL    CALCP14
  1920.         JMP    SHORT SETPIXEL31    ;Borrow code
  1921. ;
  1922. SETPIXEL50:
  1923.         CMP    CL,18
  1924.         JGE    SETPIXEL60
  1925. ;
  1926. ; Mode 17
  1927. ;
  1928.         CALL    CALCP14
  1929.         JMP    SHORT SETPIXEL01    ;Borrow code
  1930. ;
  1931. SETPIXEL60:
  1932.         CMP    CL,18
  1933.         JZ    SETPIXEL41            ;18 same as EGA
  1934. ;
  1935. ; Mode 19
  1936. ;
  1937.         CALL     CALCP19
  1938.         MOV    ES:[BX],DL    ;set it
  1939.         JMP    SETPIXEXIT
  1940. SETPIXEL        ENDP
  1941.  
  1942. ;****************************
  1943. ;        getp               *
  1944. ;****************************
  1945. ; Get a pixel's contents.
  1946. ; Call with:
  1947. ;  AX = y coordinate
  1948. ;  BX = x coordinate
  1949. ;  CX = mode
  1950. ; Returns:
  1951. ;  DL = color
  1952. ;
  1953. GETP        PROC    NEAR
  1954.         PUSH    AX
  1955.         PUSH    BX
  1956.         PUSH    CX
  1957.         CMP    CL,255        ;Hercules mode selected by 255
  1958.         JNE    GETP10
  1959. ;
  1960. ; Hercules monochrome mode
  1961. ;
  1962.         CALL    CALCPH
  1963. GETP01:
  1964.         MOV    DL,ES:[BX]
  1965.         SHR     DL,CL
  1966.         AND     DL,DH
  1967. GETPEXIT:    POP    CX
  1968.         POP    BX
  1969.         POP    AX
  1970.         RET
  1971. ;
  1972. GETP10:
  1973.         CMP    CL,6
  1974.         JGE    GETP20
  1975. ;
  1976. ; Modes 4 and 5
  1977. ;
  1978.         CALL    CALCP4
  1979.         JMP    SHORT GETP01    ;Borrow code
  1980. ;
  1981. GETP20:
  1982.         CMP    CL,7
  1983.         JGE    GETP30
  1984. ;
  1985. ; Mode 6
  1986. ;
  1987.         CALL    CALCP6
  1988.         JMP    SHORT GETP01    ;Borrow code
  1989. ;
  1990. GETP30:
  1991.         CMP    CL,14
  1992.         JGE    GETP40
  1993. ;
  1994. ; Mode 13
  1995. ;
  1996.         CALL    CALCP13
  1997. GETP31:
  1998.         MOV    CH,DH
  1999.         SHL    CH,CL
  2000.         MOV    SI,BX
  2001.         MOV    DX,3CEH
  2002.         MOV    AX,304H
  2003.         XOR    BL,BL
  2004. GETP32:
  2005.         OUT    DX,AX
  2006.         MOV    BH,ES:[SI]
  2007.         AND    BH,CH
  2008.         NEG    BH
  2009.         ROL    BX,1
  2010.         DEC    AH
  2011.         JGE    GETP32
  2012.         MOV    DL,BL
  2013.         JMP    GETPEXIT
  2014. ;
  2015. GETP40:
  2016.         CMP    CL,15
  2017.         JL      GETP51
  2018.         JNE    GETP50
  2019. ;
  2020. ; Special for mode 15
  2021. ;
  2022.         CALL    CALCP14
  2023.         MOV    CH,DH
  2024.         SHL    CH,CL
  2025.         MOV    SI,BX
  2026.         MOV    DX,3CEH
  2027.         MOV    AX,204H
  2028.         XOR    BL,BL
  2029. GETP41:
  2030.         OUT    DX,AX
  2031.         MOV    BH,ES:[SI]
  2032.         AND    BH,CH
  2033.         NEG    BH
  2034.         ROL    BX,1
  2035.         SUB    AH,2
  2036.         JGE    GETP41
  2037.         MOV    DL,BL
  2038.         JMP    GETPEXIT
  2039. ; Mode 17
  2040. GETP50:
  2041.         CMP    CL,17
  2042.         JNZ    GETP60
  2043.         CALL    CALCP14
  2044.         MOV    DL,ES:[BX]
  2045.         SHR    DL,CL
  2046.         AND    DL,DH
  2047.         JMP    GETPEXIT
  2048. ;
  2049. ; Modes 14 and 16
  2050. ;
  2051. GETP51:
  2052.         CALL    CALCP14
  2053.         JMP    GETP31        ;Borrow code
  2054. ;
  2055. GETP60:
  2056.         CMP    CL,18
  2057.         JLE    GETP51        ;Mode 18 same as EGA 14 and 16
  2058. ;
  2059. ; Mode 19
  2060. ;
  2061.         CALL    CALCP19
  2062.         MOV    DL,ES:[BX]
  2063.         JMP    GETPEXIT
  2064. GETP        ENDP
  2065.  
  2066. ;****************************
  2067. ; ROUTINES FOR CALCULATING A
  2068. ; PIXEL'S ADDRESS FOLLOW.
  2069. ;
  2070. ; Calculate pixel address for modes 4 and 5
  2071. ; Entry: AX = y coord
  2072. ;        BX = x coord
  2073. ; Exit:  DH = bit mask
  2074. ;        BX = byte offset
  2075. ;        CL = number of bits to shift
  2076. CALCP4        PROC    NEAR
  2077.         MOV    CL,BL
  2078.         XCHG    AH,AL
  2079.         SHR    AX,1
  2080.         ADD    BH,AL
  2081.         XOR    AL,AL
  2082.         ADD    BX,AX
  2083.         SHR    AX,1
  2084.         SHR    AX,1
  2085.         ADD    BX,AX
  2086.         SHR    BX,1
  2087.         SHR    BX,1
  2088.         MOV    DH,3
  2089.         AND    CL,DH
  2090.         XOR    CL,DH
  2091.         SHL    CL,1
  2092.         RET
  2093. CALCP4        ENDP
  2094. ;
  2095. ; Calculate address of pixel for mode 6
  2096. ; Entry: See abov
  2097. ; Exit: See above
  2098. ;
  2099. CALCP6        PROC    NEAR
  2100.         MOV    CL,BL
  2101.         XCHG    AH,AL
  2102.         SHR    BX,1
  2103.         SHR    AX,1
  2104.         ADD    BH,AL
  2105.         XOR    AL,AL
  2106.         ADD    BX,AX
  2107.         SHR    AX,1
  2108.         SHR    AX,1
  2109.         ADD    BX,AX
  2110.         SHR    BX,1
  2111.         SHR    BX,1
  2112.         AND    CL,7
  2113.         XOR    CL,7
  2114.         MOV    DH,1
  2115.         RET
  2116. CALCP6        ENDP
  2117. ;
  2118. ; Calculate pixel address for mode 13
  2119. ; Entry: See above
  2120. ; Exit: See above
  2121. ;
  2122. CALCP13:
  2123.         MOV    CL,BL
  2124.         MOV    CH,DL        ;Save color and borrow...
  2125.         MOV    DX,40        ;...DX
  2126. CP13COM:
  2127.         MUL    DX
  2128.         SHR    BX,1
  2129.         SHR    BX,1
  2130.         SHR    BX,1
  2131.         ADD    BX,AX
  2132.         AND    CL,7
  2133.         XOR    CL,7
  2134.         MOV    DL,CH        ;Restore color
  2135.         MOV     DH,1
  2136.         RET
  2137. ;
  2138. ; Calculate pixel address for modes 14,15,16,17,18
  2139. ; Entry: See above
  2140. ; Exit: See above
  2141. ;
  2142. CALCP14:
  2143.         MOV    CL,BL
  2144.         MOV    CH,DL        ;Save color
  2145.         MOV    DX,80
  2146.         JMP    SHORT CP13COM
  2147. ;
  2148. ; Calculate pixel address for mode 19
  2149. ; Entry: See above
  2150. ; Exit: See above
  2151. ; Note: we don't need a bit mask in AH or a shift count in CL 
  2152. ;       for this mode.
  2153. ;
  2154. CALCP19        PROC    NEAR
  2155.         XCHG    AH,AL
  2156.         ADD    BX,AX
  2157.         SHR    AX,1
  2158.         SHR    AX,1
  2159.         ADD    BX,AX
  2160.         RET
  2161. CALCP19        ENDP
  2162. ;
  2163. ; Calculate pixel address for Hercules graphics mode
  2164. ;
  2165. CALCPH        PROC    NEAR
  2166.         MOV    CL,BL
  2167.         SHR     AX,1
  2168.         RCR     BX,1
  2169.         SHR     AX,1
  2170.         RCR     BX,1
  2171.         SHR     BX,1
  2172.         MOV     AH,90
  2173.         MUL     AH
  2174.         ADD     BX,AX
  2175.         AND     CL,7
  2176.         XOR     CL,7
  2177.         MOV     DH,1
  2178.         RET
  2179. CALCPH        ENDP
  2180. ;****************************
  2181. ;         svmode            *
  2182. ;****************************
  2183. ; Set video mode.  Call with:
  2184. ;* svmode(mode) int mode; 
  2185. ;  Set video mode.
  2186. ;  Mode is:
  2187. ;  0 - 40 x 25 chars b&w (cga,ega,mcga,vga)
  2188. ;  1 - 40 x 25 chars color (cga,ega,mcga,vga)
  2189. ;  2 - 80 x 25 chars b&w (cga,ega,mcga,vga)
  2190. ;  3 - 80 x 25 chars color (cga,ega,mcga,vga)
  2191. ;  4 - 320 x 200 4-color graph (cga,ega,mcga,vga)
  2192. ;  5 - 320 x 200 b&w graph (cga,ega,mcga,vga)
  2193. ;  6 - 640 x 200 b&w graph (cga,ega,mcga,vga)
  2194. ;  7 - 80 x 25 chars b&w (mda,ega,vga)
  2195. ;  8 - 160 x 200 16-color graph (jr)
  2196. ;  9 - 320 x 200 16-color graph (jr)
  2197. ;  10 - 640 x 200 4-color graph (jr)
  2198. ;  11 - reserved by EGA video BIOS
  2199. ;  12 - reserved by EGA video BIOS
  2200. ;  13 - 320 x 200 16-color graph (ega,vga)
  2201. ;  14 - 640 x 200 16-color graph (ega,vga)
  2202. ;  15 - 640 x 350 2-color graph (ega,vga)
  2203. ;  16 - 640 x 350 4- or 16-color (ega,vga)
  2204. ;  17 - 640 x 480 2-color (mcga,vga)
  2205. ;  18 - 640 x 480 16-color (vga)
  2206. ;  19 - 320 x 200 256-color (mcga,vga)
  2207. ;  255 - Heculese 720x348 monochrome graphics
  2208.     PUBLIC    _svmode
  2209. _svmode    PROC    NEAR
  2210.     PUSH    BP
  2211.     MOV    BP,SP
  2212.     PUSH    SI
  2213.     PUSH    DI
  2214.     MOV    AX,4[BP]
  2215.     CMP    AX,255        ;Hercules?
  2216.     JZ    HERC
  2217.     PUSH    DS
  2218.     MOV    BX,40H        ;Video display data area
  2219.     MOV    DS,BX
  2220.     MOV    BL,32        ;Presence of CGA
  2221.     MOV    AX,4[BP]
  2222.     MOV    DL,AL
  2223.     AND    DL,7
  2224.     CMP    DL,7
  2225.     JNE    SVM1
  2226.     MOV    BL,48        ;Presence of MDA
  2227. SVM1:    AND    BYTE PTR DS:[10H],11001111B
  2228.     OR    BYTE PTR DS:[10H],BL
  2229.     INT    10H    ;Set the mode
  2230.     POP    DS        ;Restore DS
  2231.     POP    DI
  2232.     POP    SI
  2233.     POP    BP
  2234.     RET
  2235. HERC:
  2236. ;Update video bios data area
  2237.     PUSH    ES
  2238.     MOV    AX,40H
  2239.     MOV    ES,AX
  2240.     MOV    DI,49H    ;ES:DI is video bios data area
  2241.     MOV    SI,OFFSET BDATA
  2242.     MOV    CX,BDLEN
  2243.     REP    MOVSB        ;Update video bios data
  2244. ;Set config. switch
  2245.     MOV    DX,3BFH        ;Config switch port
  2246.     MOV    AL,1        ;Exclude second 32K of video buffer
  2247.     OUT    DX,AL
  2248. ;Blank the screen
  2249.     MOV    DX,3B8H
  2250.     XOR    AL,AL
  2251.     OUT    DX,AL
  2252. ;Program the CRTC
  2253.     SUB    DL,4        ;3b4H is addres reg port of CRTC
  2254.     MOV    SI,OFFSET CRTCP
  2255.     MOV    CX,9        ;9 parameters to load
  2256. HERC1:    LODSW            ;Al=crtc register number/AH=VALUE
  2257.     OUT    DX,AX
  2258.     LOOP    HERC1
  2259. ;Set graphics mode
  2260.     ADD    DL,4
  2261.     MOV    AL,CRTMD
  2262.     OUT     DX,AL
  2263. ;Clear the video buffer
  2264.     MOV    AX,0B000H
  2265.     MOV    ES,AX
  2266.     XOR    AX,AX        ;Clear to zero
  2267.     XOR    DI,DI
  2268.     MOV    CX,4000H
  2269.     REP    STOSW
  2270.     POP    ES
  2271.     POP    DI
  2272.     POP    SI
  2273.     POP    BP
  2274.     RET            ;Go home
  2275. _svmode    ENDP
  2276.  
  2277. ;****************************
  2278. ;        gvmode             *
  2279. ;****************************
  2280. ; Get video mode.  Returns current video mode number.
  2281.     PUBLIC    _gvmode
  2282. _gvmode    PROC    NEAR
  2283.     MOV    AH,0FH
  2284.     INT    10H
  2285.     XOR    AH,AH        ;Clear hi part of mode number
  2286.     RET
  2287. _gvmode    ENDP
  2288.  
  2289.  
  2290. ;*****************************
  2291. ;     FILE IO ROUTINES       *
  2292. ;*****************************
  2293. ;
  2294. ;*****************************
  2295. ;        ll_open             *
  2296. ;*****************************
  2297. ; Open a file with read/write access.
  2298. ; Call with:
  2299. ;  hand=ll_open(nameptr)
  2300. ; Where:
  2301. ;  nameptr = pointer to file's name (null-terminated)
  2302. ; Returns handle.  If handle<0, indicates error.
  2303.         PUBLIC    _ll_open
  2304. OPENNAMEPTR    equ    [BP+4]
  2305. _ll_open    PROC    NEAR
  2306.         PUSH    BP
  2307.         MOV    BP,SP
  2308.         PUSH    DX
  2309. ;Issue the call
  2310.         MOV    DX,OPENNAMEPTR
  2311.         MOV    AH,3DH
  2312.         MOV    AL,2    ;Read/write
  2313.         INT    21H
  2314.         JC    LLOPZ
  2315. ;Return handle
  2316. LLOPX:
  2317.         POP    DX
  2318.         POP    BP
  2319.         RET
  2320. LLOPZ:        NEG    AX
  2321.         JMP    LLOPX
  2322. _ll_open    ENDP
  2323. ;*****************************
  2324. ;        ll_close            *
  2325. ;*****************************
  2326. ; Close a file.
  2327. ; Call with:
  2328. ;  ll_close(handle)
  2329. ; Where:
  2330. ;  handle = file's handle.
  2331.         PUBLIC    _ll_close
  2332. CLOSEHAND    equ    [BP+4]
  2333. _ll_close    PROC    NEAR
  2334.         PUSH    BP
  2335.         MOV    BP,SP
  2336. ;Get the handle
  2337.         MOV    BX,CLOSEHAND
  2338.         MOV    AH,3EH
  2339.         INT    21H
  2340.         POP    BP
  2341.         RET
  2342. _ll_close    ENDP
  2343.  
  2344. ;*****************************
  2345. ;        ll_create           *
  2346. ;*****************************
  2347. ; Create a file with read/write access.
  2348. ; Call with:
  2349. ;  hand=ll_create(nameptr)
  2350. ; Where:
  2351. ;  nameptr = pointer to file's name (null-terminated)
  2352. ; Returns handle.  If handle<0, indicates error.
  2353.         PUBLIC    _ll_create
  2354. CREATNAMEPTR    equ    [BP+4]
  2355. _ll_create    PROC    NEAR
  2356.         PUSH    BP
  2357.         MOV    BP,SP
  2358. ;Get the file name and create it.
  2359.         MOV    DX,CREATNAMEPTR
  2360.         MOV    AH,3CH
  2361.         XOR    CX,CX
  2362.         INT    21H
  2363.         JC    LLCRZ
  2364. ;Return handle
  2365. LLCRX:        POP    BP
  2366.         RET
  2367. ;Return error
  2368. LLCRZ:        NEG    AX
  2369.         JMP    LLCRX
  2370. _ll_create    ENDP
  2371.  
  2372. ;*****************************
  2373. ;      ll_seekread           *
  2374. ;*****************************
  2375. ; Seek-and-read an open file.
  2376. ; Call with:
  2377. ;  result=ll_seekread(handle,offset,mode,buffer,nbytes)
  2378. ; Where:
  2379. ;  handle = handle of file to read
  2380. ;  offset = byte offset
  2381. ;  mode = offset mode
  2382. ;  buffer = segment of buffer to read into
  2383. ;  nbytes = number of bytes to read
  2384. ; Returns:
  2385. ;  Number of bytes actually read.  If error, result is negative
  2386. ;  and contains error code.
  2387. ; Note: The data is read into the segment starting at offset 0.
  2388.         PUBLIC    _ll_seekread
  2389. SRHANDLE    equ    [BP+4]
  2390. SROFFSETL    equ    [BP+6]
  2391. SROFFSETH    equ    [BP+8]
  2392. SRMODE        equ    [BP+10]
  2393. SRBUFFSEG    equ    [BP+12]
  2394. SRNBYTES    equ    [BP+14]
  2395. _ll_seekread    PROC    NEAR
  2396.         PUSH    BP
  2397.         MOV    BP,SP
  2398.         PUSH    BX
  2399.         PUSH    CX
  2400.         PUSH    DX
  2401.         PUSH    DS
  2402. ;Do the seek first
  2403.         MOV    BX,SRHANDLE    ;Get handle
  2404.         MOV    DX,SROFFSETL    ;Get byte offset
  2405.         MOV    CX,SROFFSETH
  2406.         MOV    AX,SRMODE
  2407.         MOV    AH,42H
  2408.         INT    21H        ;Do the seek
  2409.         JC    SRERR        ;Error if carry set
  2410. ;Now do the read
  2411.         MOV    AX,SRBUFFSEG
  2412.         MOV    DS,AX
  2413.         XOR    DX,DX        ;Set address
  2414.         MOV    CX,SRNBYTES    ;Number of bytes
  2415.         MOV    AH,3FH
  2416.         INT    21H        ;Do the read
  2417.         JC    SRERR
  2418. ;Return bytes actually read
  2419. SRX:
  2420.         POP    DS
  2421.         POP    DX
  2422.         POP    CX
  2423.         POP    BX
  2424.         POP    BP
  2425.         RET
  2426. ;Return error code
  2427. SRERR:        NEG    AX
  2428.         JMP    SRX
  2429. _ll_seekread    ENDP
  2430. ;*****************************
  2431. ;      ll_seekwrite          *
  2432. ;*****************************
  2433. ; Seek-and-write an open file.
  2434. ; Call with:
  2435. ;  result=ll_seekwrite(handle,offset,mode,buffer,nbytes)
  2436. ; Where:
  2437. ;  handle = handle of file to write
  2438. ;  offset = byte offset
  2439. ;  mode = seek mode
  2440. ;  buffer = segment of buffer to write from
  2441. ;  nbytes = number of bytes to write
  2442. ; Returns:
  2443. ;  Number of bytes actually written.  If error, result is negative
  2444. ;  and contains error code.
  2445. ; Note: The data is written from the segment starting at offset 0.
  2446.         PUBLIC    _ll_seekwrite
  2447. SWHANDLE    equ    [BP+4]
  2448. SWOFFSETL    equ    [BP+6]
  2449. SWOFFSETH    equ    [BP+8]
  2450. SWMODE        equ    [BP+10]
  2451. SWBUFFSEG    equ    [BP+12]
  2452. SWNBYTES    equ    [BP+14]
  2453. _ll_seekwrite    PROC    NEAR
  2454.         PUSH    BP
  2455.         MOV    BP,SP
  2456.         PUSH    BX
  2457.         PUSH    CX
  2458.         PUSH    DX
  2459.         PUSH    DS
  2460. ;Do the seek first
  2461.         MOV    BX,SWHANDLE    ;Get handle
  2462.         MOV    DX,SWOFFSETL    ;Get byte offset
  2463.         MOV    CX,SWOFFSETH
  2464.         MOV    AX,SWMODE    ;Seek mode
  2465.         MOV    AH,42H
  2466.         INT    21H        ;Do the seek
  2467.         JC    SWERR        ;Error if carry set
  2468. ;Now do the write
  2469.         MOV    AX,SWBUFFSEG
  2470.         MOV    DS,AX
  2471.         XOR    DX,DX        ;Set address
  2472.         MOV    CX,SWNBYTES    ;Number of bytes
  2473.         MOV    AH,40H
  2474.         INT    21H        ;Do the write
  2475.         JC    SWERR
  2476. ;Return bytes actually write
  2477. SWX:
  2478.         POP    DS
  2479.         POP    DX
  2480.         POP    CX
  2481.         POP    BX
  2482.         POP    BP
  2483.         RET
  2484. ;Return error code
  2485. SWERR:        NEG    AX
  2486.         JMP    SWX
  2487. _ll_seekwrite    ENDP
  2488. ;****************************
  2489. ;          ll_filelen       *
  2490. ;****************************
  2491. ; Return a file's length.
  2492. ;   ulong = ll_filelen(fh)
  2493.         PUBLIC    _ll_filelen
  2494. FLENFH        equ    [BP+4]        ;File handle
  2495. _ll_filelen    PROC    NEAR
  2496.         PUSH    BP
  2497.         MOV    BP,SP
  2498.         PUSH    BX
  2499.         PUSH    CX
  2500.         PUSH    DX
  2501. ;First do a seek on the file
  2502.         MOV    BX,FLENFH    ;Get handle
  2503.         XOR    CX,CX
  2504.         XOR    DX,DX        ;Offset 0
  2505.         MOV    AL,2        ;End of file
  2506.         MOV    AH,42H
  2507.         INT    21H
  2508. ;Return the offset
  2509.         POP    DX
  2510.         POP    CX
  2511.         POP    BX
  2512.         POP    BP
  2513.         RET
  2514. _ll_filelen    ENDP
  2515.         END