home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / PRIMES14.ZIP / PRIMES14.ASM next >
Encoding:
Assembly Source File  |  1991-10-29  |  15.9 KB  |  543 lines

  1. ;-----------------------------------------------------------------------
  2.         TITLE   PRIMES
  3. ;        (c) 1991 W.C. Parke
  4. ;-----------------------------------------------------------------------
  5. CR      EQU     13
  6. LF      EQU     10
  7. ;-----------------------------------------------------------------------
  8. START   SEGMENT
  9.         ASSUME  CS:START,DS:START,ES:START,SS:START
  10.         ORG     100H
  11. PUBLIC  FIRST,BEGIN
  12. FIRST:  JMP     BEGIN
  13. CPWP    DB      'Primes V1.4 (c) W.C. Parke, 1991$',1AH
  14.         EVEN
  15. PUBLIC NPRINT1,NPRINT2,NLINE,NPRIME,NPRIME2,TLINE,PBUF,EXTRA,NPS,NP$
  16. PUBLIC CRLF,NUMBUF
  17. NPRINT1 DW      1
  18. NPRINT12 DW     0
  19. NPRINT2 DW      0
  20. NPRINT22 DW     0
  21. NLINE   DW      8
  22. NPRIME  DW      0
  23. NPRIME2 DW      0
  24. TLINE   DW      9
  25. PBUF    DW      0
  26. EXTRA   DB      0
  27. NPS     DB      CR,LF,'The number of primes was '
  28. NP$     DB      '0000000000$'
  29. ERROR   DB      CR,LF,'Error in '
  30. DHELP   DB      'Syntax:   PRIMES n1 n2'
  31.         DB      CR,LF,CR,LF,'  where 0 < n1 < n2 < 1048576'
  32. CRLF    DB       CR,LF,'$'
  33. STSI    DW      0
  34. LSTB    DW      0
  35. INIM    DB      0
  36. ERIN    DB      0
  37. FLG     DB      0
  38. ;-----------------------------------------------------------------------
  39. PUBLIC EXIT
  40. ; Process error message and exit
  41. EXITE:  MOV     DX,OFFSET ERROR
  42. EXITH:  MOV     AH,9
  43.         INT     21H
  44.         MOV     AX,4C00H
  45.         INT     21H
  46. EXIT:   PUSH    CS
  47.         POP     ES
  48.         MOV     AL,ERIN
  49.         AND     AL,AL
  50.         JNZ     EXITE
  51.         MOV     AX,NPRIME
  52.         MOV     DX,NPRIME2
  53.         MOV     DI,OFFSET NP$
  54.         PUSH    DI
  55.         CALL    BINDEC32
  56.         POP     SI
  57.         CMP     BYTE PTR NP$+9,' '
  58.         JNZ     EXIT1
  59.         MOV     BYTE PTR NP$+9,'0'
  60. EXIT1:  MOV     DX,OFFSET NPS
  61.         MOV     AH,9
  62.         INT     21H
  63.         CALL    SCRLF
  64.         MOV     AL,0
  65.         MOV     AH,4CH
  66.         INT     21H
  67. HELP:   CALL    SCRLF
  68.         MOV     DX,OFFSET DHELP
  69.         JMP     EXITH
  70. ;-----------------------------------------------------------------------
  71. PUBLIC BEGIN
  72. ; Begin by getting command line numbers
  73. BEGIN:
  74.         CALL    SCRLF
  75.         MOV     DX,OFFSET CPWP
  76.         MOV     AH,9
  77.         INT     21H
  78.         CALL    SCRLF
  79.         MOV     SI,OFFSET 81H
  80.         MOV     DI,OFFSET NUMBUF
  81.         CALL    GETNUM
  82.         JNC     BEG1
  83.         MOV     ERIN,1
  84.         JMP     EXIT
  85. BEG1:   JCXZ    BEG2
  86.         PUSH    SI
  87.         MOV     SI,OFFSET NUMBUF
  88.         MOV     DI,OFFSET NPRINT1
  89.         CALL    DECBIN32
  90.         POP     SI
  91.         MOV     DI,OFFSET NUMBUF
  92.         CALL    GETNUM
  93. BEG2:   JCXZ    BEG3
  94.         MOV     SI,OFFSET NUMBUF
  95.         MOV     DI,OFFSET NPRINT2
  96.         CALL    DECBIN32
  97. BEG3:
  98.         MOV     CX,NPRINT2
  99.         MOV     DX,NPRINT2+2    ; dx:cx = second number
  100.         MOV     SI,NPRINT1
  101.         MOV     AX,NPRINT1+2    ; ax:si = first number
  102.         MOV     BX,SI           ;  table index = 16*si + 2*b + 1
  103.         OR      BX,AX
  104.         JZ      HELP
  105.         MOV     BX,CX
  106.         OR      BX,DX
  107.         JZ      HELP
  108.         TEST    DX,0FFF0H
  109.         JNZ     BEG4
  110.         TEST    AX,0FFF0H
  111.         JNZ     BEG4
  112.         AND     AX,AX
  113.         JNZ     BEG31
  114.         CMP     SI,3
  115.         JNC     BEG31
  116.         MOV     SI,1
  117.         MOV     FLG,1
  118. BEG31:  MOV     DI,DX           ; nprint22
  119.         MOV     BX,CX           ; nprint2
  120.         SUB     BX,SI           ; nprint2-nprint1
  121.         SBB     DI,AX           ; nprint22-nprint12-c
  122.         JNC     BEG5
  123. BEG4:   MOV     ERIN,1
  124.         JMP     EXIT
  125. BEG5:   OR      BX,DI
  126.         JZ      BEG4
  127.         OR      SI,1            ; make nprint1 odd
  128.         TEST    CX,1
  129.         JNZ     BEG6            ; odd already
  130.         SUB     CX,1
  131.         SBB     DX,0            ; get next lower odd
  132.  
  133. BEG6:   MOV     BX,SI           ; nprint1
  134.         AND     BX,0FH          ; start to print after div by 16
  135.         SHR     BX,1            ; get bit index for starting number
  136.  
  137.         SHR     AX,1            ; divide first number by 16
  138.         RCR     SI,1
  139.         SHR     AX,1
  140.         RCR     SI,1
  141.         SHR     AX,1
  142.         RCR     SI,1
  143.         SHR     AX,1
  144.         RCR     SI,1            ; si now has [#/16]
  145.         MOV     STSI,SI
  146.  
  147.         MOV     AX,CX           ; nprint2
  148.         AND     AX,0FH          ; extra to print
  149.         SHR     AX,1            ; but only odds
  150.         MOV     EXTRA,AL
  151.  
  152.         SHR     DX,1            ; divide second number by 16
  153.         RCR     CX,1
  154.         SHR     DX,1
  155.         RCR     CX,1
  156.         SHR     DX,1
  157.         RCR     CX,1
  158.         SHR     DX,1
  159.         RCR     CX,1
  160.         MOV     DX,CX           ; save index of last byte-mask to print
  161.         MOV     LSTB,DX         ; last byte ptr
  162.  
  163. ; Extimate square root of last byte using
  164. ;  2**(k-1) + #/2**(k+1)
  165. ;  where k is largest integer for which # ~ 2**2k
  166.  
  167.         MOV     AX,CX
  168.         MOV     CX,16
  169. BEG7:   SHL     AX,1
  170.         JC      BEG8
  171.         LOOP    BEG7
  172. BEG8:   SHR     CX,1            ; k
  173.         MOV     AX,1
  174.         SHL     AX,CL           ; 2**k
  175.         INC     CX              ; k+1
  176.         SHR     DX,CL           ; #/2**(k+1)
  177.         SHR     AX,1            ; 2**(k-1)
  178.         ADD     DX,AX
  179.         INC     DX
  180.  
  181.         MOV     BP,DX           ; save for later comparison
  182.  
  183.         MOV     CX,BX
  184.         AND     CL,7
  185.         MOV     AL,1
  186.         SHL     AL,CL           ; get initial mask
  187.         MOV     INIM,AL
  188.  
  189.         MOV     AX,OFFSET STK
  190.         MOV     SP,AX           ; set up our stack
  191.         MOV     BX,OFFSET BUF
  192.         PUSH    DS
  193.         POP     AX
  194.         ADD     BX,15
  195.         SHR     BX,1
  196.         SHR     BX,1
  197.         SHR     BX,1
  198.         SHR     BX,1
  199.         ADD     AX,BX
  200.         MOV     PBUF,AX         ; the prime bit buffer
  201.         ASSUME  ES:NOTHING,DS:NOTHING
  202.         MOV     ES,AX
  203.         MOV     DS,AX
  204.         XOR     AX,AX
  205.         MOV     SI,AX
  206.         MOV     DI,AX
  207.         MOV     CX,32768
  208.         REP     STOSW           ; zero 64K buffer
  209.         MOV     BX,1            ; bit tester register will be BL
  210.         MOV     CH,8            ; CH=8, CL bit pointer
  211.         PUSH    CX
  212.         PUSH    SI              ; address in buffer
  213. ;-----------------------------------------------------------------------
  214. PUBLIC NEXTP
  215. ; Start Eratosthenes sieve
  216. NEXTP:  POP     SI              ; byte pointer
  217.         POP     CX              ; bit counter
  218. NEXTP1: INC     CL              ; pointer in 8 bits
  219.         ROL     BL,1            ; bit mask, 8 bit roll and set C
  220.         JNC     NEXTP2          ;  not yet finished with byte
  221.         XOR     CL,CL           ; reset bit pointer
  222.         INC     SI              ; point to next byte in buffer
  223.         CMP     SI,BP           ; are we finished?
  224.         JNC     FINS2           ; yes
  225. PUBLIC NEXTP2
  226. NEXTP2: MOV     AL,[SI]         ; get byte
  227.         AND     AL,BL           ; is it a prime, i.e. still a zero bit ?
  228.         JNZ     NEXTP1          ; no, its bit is set to 1, its not prime
  229.         PUSH    CX              ; save bit counter
  230.         PUSH    SI              ; save byte pointer
  231.         MOV     DI,SI           ; put prime byte index in di
  232.         MOV     DL,CL           ; put prime  bit index in dl
  233.         SHL     DI,1            ; since we are doing only odds, double first
  234.         JC      NEXTP           ; more than half done
  235.         SHL     DL,1            ;  double bit index also
  236.         INC     DL              ;   and add 1 to make 2*i+1
  237.         CMP     DL,CH           ; bigger than 8 ?
  238.         JC      DELN            ; no
  239.         SUB     DL,CH           ; reset bit index: DL - 8
  240.         INC     DI              ; point to next byte index
  241.         JZ      NEXTP
  242. DELN:   ADD     SI,DI           ; point to next non-prime byte
  243.         JC      NEXTP
  244.         ADD     CL,DL           ; point to next non-prime bit in byte
  245.         CMP     CL,CH
  246.         JC      DELN1
  247.         SUB     CL,CH
  248.         INC     SI
  249.         JZ      NEXTP
  250. DELN1:  MOV     AL,1
  251.         SHL     AL,CL
  252.         OR      [SI],AL         ; mask this bit to show non-prime
  253.         JMP     SHORT DELN
  254. ;-----------------------------------------------------------------------
  255. PUBLIC FINS2
  256. ; Now print all flagged (prime) bits up to requested number
  257. FINS2:
  258.         PUSH    CS
  259.         POP     DS
  260.         ASSUME  DS:START
  261.         MOV     DI,OFFSET NP$
  262.  
  263.         MOV     CX,LSTB         ; last byte pointer
  264.         MOV     SI,STSI         ; initial byte pointer
  265.         MOV     AL,INIM         ; initial mask
  266.         TEST    FLG,1
  267.         JZ      FINS21
  268.         DEC     TLINE
  269.         MOV     AX,2
  270.         XOR     DX,DX
  271.         MOV     BP,AX
  272.         CALL    PRT3
  273.         MOV     AX,BP
  274. FINS21: CMP     CX,SI
  275.         JZ      FINS5
  276. FINS3:  MOV     AH,AL
  277.         AND     AH,ES:[SI]
  278.         MOV     BP,AX
  279.         JNZ     FINS4
  280.         CALL    PRINT
  281. FINS4:  MOV     AX,BP
  282.         ROL     AL,1
  283.         JNC     FINS3
  284.         INC     SI
  285.         CMP     SI,CX
  286.         JC      FINS3
  287.         JZ      FINS5
  288.         MOV     ERIN,0
  289.         JMP     EXIT
  290. FINS5:  XOR     CX,CX
  291.         MOV     CL,EXTRA
  292.         JCXZ    FINS9
  293.         MOV     CH,1
  294.         SHL     CH,CL
  295.         MOV     CL,CH
  296.         ROL     CL,1
  297. FINS6:  MOV     AH,AL
  298.         AND     AH,ES:[SI]
  299.         MOV     BP,AX
  300.         JNZ     FINS8
  301.         CALL    PRINT
  302. FINS8:  MOV     AX,BP
  303.         ROL     AL,1
  304.         CMP     AL,CL
  305.         JNZ     FINS6
  306. FINS9:  MOV     ERIN,0
  307.         JMP     EXIT
  308. PUBLIC PRINT
  309. PRINT:  DEC     TLINE             ; # on line
  310.         JNZ     PRT1
  311.         CALL    PRTCR
  312. PRT1:   MOV     BH,AL
  313.         XOR     DX,DX
  314.         MOV     AX,SI
  315.         SHL     AX,1
  316.         RCL     DX,1
  317.         SHL     AX,1
  318.         RCL     DX,1
  319.         SHL     AX,1
  320.         RCL     DX,1
  321.         SHL     AX,1
  322.         RCL     DX,1
  323.         MOV     BL,0
  324. PRT2:   INC     BL
  325.         ROR     BH,1
  326.         JNC     PRT2
  327.         XOR     BH,BH
  328.         SHL     BX,1
  329.         DEC     BX
  330.         ADD     AX,BX
  331.         ADC     DX,0
  332. PRT3:   ADD     WORD PTR NPRIME,1
  333.         ADC     WORD PTR NPRIME2,0
  334. ;-----------------------------------------------------------------------
  335. PUBLIC OUTDEC
  336. ; Output a decimal number
  337. OUTDEC:
  338.         PUSH    AX
  339.         PUSH    CX
  340.         PUSH    DI
  341.         PUSH    DX
  342.         PUSH    ES
  343.         PUSH    CS
  344.         POP     ES
  345.         MOV     DI,OFFSET NP$
  346.         CALL    BINDEC32
  347.         XCHG    SI,DI
  348.         ADD     SI,2
  349.         MOV     AH,2
  350.         MOV     CX,8
  351. OUTDS:  LODSB
  352.         MOV     DL,AL
  353.         INT     21H
  354.         LOOP    OUTDS
  355.         XCHG    SI,DI
  356.         POP     ES
  357.         POP     DX
  358.         POP     DI
  359.         POP     CX
  360.         POP     AX
  361.         RET
  362. ;-----------------------------------------------------------------------
  363. PUBLIC PRTCR
  364. ; Print a carriage return and line feed and reset number/line count
  365. PRTCR:
  366.         PUSH    AX
  367.         CALL    SCRLF
  368.         MOV     AX,NLINE
  369.         MOV     TLINE,AX
  370.         POP     AX
  371.         RET
  372. ;-----------------------------------------------------------------------
  373. PUBLIC CKNUM
  374. ; Check if character is a number
  375. CKNUM:
  376.         CMP     AL,':'
  377.         CMC
  378.         JC      CKNE
  379.         CMP     AL,'0'
  380. CKNE:   RET
  381. ;-----------------------------------------------------------------------
  382. PUBLIC GETNUM
  383. ; Get an ASCII number
  384. GETNUM:
  385.         CALL    SKIPS
  386.         XOR     CX,CX
  387. GETN1:  LODSB
  388.         CMP     AL,CR
  389.         JZ      GETNE
  390.         CMP     AL,' '
  391.         JZ      GETNE
  392.         CALL    CKNUM
  393.         JC      GETNC
  394.         INC     CX
  395.         STOSB
  396.         JMP     SHORT GETN1
  397. GETNC:  RET
  398. GETNE:  CMP     CX,8
  399.         CMC
  400.         RET
  401. ;-----------------------------------------------------------------------
  402. PUBLIC DECBIN32
  403. ; Convert a decimal number to 32 bit binary number
  404. DECBIN32:
  405.         PUSH    DI
  406.         PUSH    BP
  407.     PUSH    BX
  408.         XOR     AX,AX           ; zero initial
  409.     MOV    DX,AX        ;  binary double word
  410.     MOV    BX,AX        ; and our decimal digit holder
  411.         MOV     BP,10           ; multiplier
  412.     JMP    DECBS        ; skip first multiplication
  413. DECBL:    XCHG    DI,AX        ; save current low word
  414.     MOV    AX,DX        ; get high word
  415.     MUL    BP        ; mult high word by 10
  416.     XCHG    DI,AX        ; save and get low word
  417.     MUL    BP        ; mult low word by 10
  418.     ADD    DX,DI        ; add 10*hi to overflow of 10*lo
  419. DECBS:    MOV    BL,[SI]        ; get next decimal
  420.     INC    SI        ; bump buffer pointer
  421.     SUB    BL,30H        ; drop ascii bias
  422.     ADD    AX,BX        ; add next decimal to low word
  423.     ADC    DX,0        ;  and carry to high word
  424.     LOOP    DECBL        ; continue for 10 digits
  425.     POP    BX
  426.     POP    BP
  427.         POP     DI
  428.         STOSW
  429.         MOV     AX,DX
  430.         STOSW
  431.         RET
  432. ;-----------------------------------------------------------------------
  433. PUBLIC SKIPS
  434. ; Skip space characters in a string
  435. SKIPS:
  436.         CMP     BYTE PTR [SI],' '
  437.         JNZ     SKIPE
  438.         INC     SI
  439.         JMP     SHORT SKIPS
  440. SKIPE:  RET
  441. ;-----------------------------------------------------------------------
  442. PUBLIC SCRLF
  443. ; Send a carriage return and line feed
  444. SCRLF:
  445.         PUSH    DX
  446.         MOV     DX,OFFSET CRLF
  447.         MOV     AH,9
  448.         INT     21H
  449.         POP     DX
  450.         RET
  451. ;-----------------------------------------------------------------------
  452. PUBLIC BINDEC32
  453. ; Convert 32 bit binary to decimal
  454. BINDEC32:                ; Convert 32 bit number to decimal
  455.     PUSH    BX            ; save bx
  456.     PUSH    CX            ; save cx
  457.     PUSH    SI            ; save si
  458.     PUSH    DI            ; save buffer pointer
  459.     MOV    DI,DX            ; save binary double word
  460.     MOV    SI,AX            ; in DI,SI
  461.     XOR    AX,AX            ; zero high decimal accumulator
  462.     MOV    BX,AX            ; BX will hold high packed BCD
  463.     MOV    DX,AX            ; DX will hold low packed BCD
  464.     MOV    CX,32            ; use all 32 bits of double word
  465. BIND1:    SHL    SI,1            ; shift low word left
  466.     RCL    DI,1            ; rotate hi word left through carry
  467.     XCHG    DX,AX            ; use DX low 4 digits first
  468.     ADC    AL,AL            ; add al to al with carry bit
  469.     DAA                ; decimal adj al
  470.     XCHG    AL,AH            ; now do the same with ah
  471.     ADC    AL,AL            ; double and add carry
  472.     DAA                ; decimal adj
  473.     XCHG    AL,AH            ; restore ax order
  474.     XCHG    DX,AX            ; save resultant low BCD quartet
  475.     XCHG    BX,AX            ; now use BX high 4 digits
  476.     ADC    AL,AL            ; add al to al with carry bit
  477.     DAA                ; decimal adj al
  478.     XCHG    AL,AH            ; now do the same with ah
  479.     ADC    AL,AL            ; double and add carry
  480.     DAA                ; decimal adj
  481.     XCHG    AL,AH            ; restore ax order
  482.     XCHG    BX,AX            ; save resultant high BCD quartet
  483.     ADC    AL,AL            ; accum highest digits in AL
  484.     DAA                ;  as a pair of BCDs
  485.     LOOP    BIND1            ; do all 32 bits
  486.     MOV    SI,OFFSET TMPBUF    ; our temporary buffer for packed BCD
  487.     POP    DI            ; get buffer pointer
  488.     PUSH    DI            ; save again
  489.     MOV    [SI],BX            ; middle word
  490.     MOV    [SI+2],DX        ; low word
  491.     MOV    CX,1            ; local count
  492.     MOV    DX,3            ; anticipate two more words to unpack
  493.     MOV    AH,AL            ; save nibble pair
  494.     JMP    SHORT UNPL        ; start with first nibble pair
  495. BINDU:                    ; expand packed BCD to ascii string
  496.     XCHG    DX,CX            ; save external count
  497.     LODSW                ; get packed BCD word
  498.     MOV    CX,2            ; local count
  499.     MOV    BX,AX            ; save ax
  500.     MOV    AL,AH            ; start with ah
  501. UNPL:    SHR    AL,1            ; shift hi nibble
  502.     SHR    AL,1            ; note that four 1 bit shifts are
  503.     SHR    AL,1            ;  8 clock cycles, while shr al,cl(4)
  504.     SHR    AL,1            ;  takes 24 clock cycles
  505.     OR    AL,30H            ; add ascii bias
  506.     STOSB                ; save
  507.     MOV    AL,AH            ; get back ah
  508.     AND    AL,0FH            ; mask lo nibble
  509.     OR    AL,30H            ; add ascii bias
  510.     STOSB                ; save
  511.     MOV    AX,BX            ; get back word
  512.     MOV    AH,AL            ; save low byte
  513.     LOOP    UNPL            ; local loop
  514.     XCHG    CX,DX            ; restore external count
  515.     LOOP    BINDU            ; finish all packed BCDs
  516.     POP    DI            ; recover buffer pointer
  517.     POP    SI            ; old saved si
  518.     POP    CX
  519.     POP    BX
  520. ;-----------------------------------------------------------------------
  521. PUBLIC BLANK
  522. ; Replace leading zeros by space
  523. BLANK:
  524.         PUSH    DI
  525. BLANKL: CMP     BYTE PTR [DI],'0'
  526.         JNZ     BLANKE
  527.         MOV     BYTE PTR [DI],' '
  528.         INC     DI
  529.         JMP     SHORT BLANKL
  530. BLANKE: POP     DI
  531.         RET
  532.  
  533. TMPBUF  DW      2 DUP(0)
  534.  
  535.         EVEN
  536. STK     EQU     $+256
  537. BUF     EQU     STK+4
  538. NUMBUF  EQU     BUF
  539. START   ENDS
  540.         END     FIRST
  541. ;-----------------------------------------------------------------------
  542. 
  543.