home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / C-ASM_VI.ARJ / PROGASM.ZIP / PROG086.ASM < prev    next >
Assembly Source File  |  1988-04-10  |  12KB  |  329 lines

  1.  
  2. ;************************************************************************
  3. ; Line (x0, y0, x1, y1,c ): draw line from (x0,y0) to (x1,y1)           *
  4. ;               with a color (c).                                       *
  5. ;               This routine is divided into three parts. Horizontal    *
  6. ;               lines are done in the first part, vertical lines in     *
  7. ;               second part, and rest in the third part.  The lines     *
  8. ;               in the third part are done using the Bresenhams         *
  9. ;               algorithm.                                              *
  10. ; entry : sp + 2 = x0                                                   *
  11. ;         sp + 4 = y0                                                   *
  12. ;         sp + 6 = x1                                                   *
  13. ;         sp + 8 = y1                                                   *
  14. ;         sp + 10= color                                                *
  15. ;************************************************************************
  16.  
  17. X0      EQU     [BP+4]
  18. Y0      EQU     [BP+6]
  19. X1      EQU     [BP+8]
  20. Y1      EQU     [BP+10]
  21. Color   EQU     [BP+12]
  22.  
  23.         PUBLIC  _Line
  24.  
  25. _Line   PROC    NEAR
  26.         PUSH    BP
  27.         MOV     BP,SP
  28.         SUB     SP,6                    ;Declare three local variables
  29.  
  30.         PUSH    DI
  31.         PUSH    SI
  32.         PUSH    DS
  33.         PUSH    ES
  34.  
  35.         MOV     AX,X0                   ; make sure that x1 >= x0
  36.         MOV     CX,X1
  37.         CMP     CX,AX
  38.         JGE     Get_Offset
  39.         MOV     BX,Y0
  40.         MOV     DX,Y1
  41.         MOV     X0,CX
  42.         MOV     Y0,DX
  43.         MOV     X1,AX
  44.         MOV     Y1,BX
  45.  
  46. ;-------COMPUTE ADDRESS AND MASK FOR FIRST PIXEL -------------
  47. Get_Offset:
  48.         ;--- Compute offset and save on stack
  49.         MOV     CL,4                    ; offset = 80 * y + x/8
  50.         MOV     AX,Y0
  51.         SHL     AX,CL
  52.         MOV     BX,AX
  53.         SHL     AX,1
  54.         SHL     AX,1
  55.         ADD     AX,BX
  56.         MOV     BX,X0                   ; + x/8
  57.         MOV     CL,3
  58.         SHR     BX,CL
  59.         ADD     AX,BX
  60.         PUSH    AX                      ; save offset on stack, later pop to DI
  61.  
  62.         ;--- Compute mask and save on the stack
  63.  
  64.         MOV     CX,X0                   ; compute which bit (x mod 8) to modify
  65.         AND     CL,7
  66.         MOV     BX,80h
  67.         SHR     BX,CL
  68.         PUSH    BX                      ; save mask on stack, later pop to SI
  69.         MOV     DX,03CEh                ; enable only the bit(within a byte)
  70.         MOV     AL,08H                  ; to be changed
  71.         OUT     DX,AL
  72.         INC     DX
  73.         MOV     AL,BL                   ; ... reg-bx has the correct bit
  74.         OUT     DX,AL
  75.  
  76.         ;--- Load set/reset registers with current color
  77.  
  78.         MOV     DX,03CEh                ; move color into reset register
  79.         XOR     AL,AL
  80.         OUT     DX,AL
  81.         INC     DX
  82.         MOV     AX,Color
  83.         OUT     DX,AL
  84.         DEC     DX                      ; enable use of reset register
  85.         MOV     AL,1
  86.         OUT     DX,AL
  87.         INC     DX
  88.         MOV     AL,0FH
  89.         OUT     DX,AL
  90.         MOV     DX,03C4h                ; enable all four planes for writting
  91.         MOV     AL,2
  92.         OUT     DX,AL
  93.         INC     DX
  94.         MOV     AL,0FH
  95.         OUT     DX,AL
  96.  
  97.         ;--- Load segment register
  98.  
  99.         MOV     DX,0A000h
  100.         MOV     DS,DX
  101.         MOV     ES,DX
  102.  
  103. ;-------COMPUTE  DX AND DY ----------------------------------------
  104. ;       DETERMINE IF HORIZONTAL, VERTICAL OR DIAGONNAL LINE
  105.  
  106.         MOV     AX,80                   ; set raster increment
  107.         MOV     [bp-6],AX
  108.         MOV     SI,X1                   ; compute dx           reg-si
  109.         SUB     SI,X0
  110.         MOV     DI,Y1                   ; compute dy           reg-di
  111.         SUB     DI,Y0
  112.         JGE     DyIsPos
  113.         NEG     AX
  114.         MOV     [bp-6],AX
  115.         NEG     DI
  116. DyIsPos:
  117.         CMP     SI,0                    ; jump according to type of line
  118.         JZ      Vert
  119.         CMP     DI,0
  120.         JZ      Horiz
  121.         JMP     Diag
  122.  
  123. ;-------GENERATE A VERTICAL LINE -----------------
  124.  
  125. Vert:   MOV     cx,di                   ; set up counter
  126.         INC     cx
  127.         MOV     bx,[bp-6]
  128.  
  129.         POP     SI                      ; fetch mask
  130.         MOV     DX,03CEh                ; set mask
  131.         MOV     AL,08h
  132.         OUT     DX,AL
  133.         INC     DX
  134.         MOV     AX,SI
  135.         OUT     DX,AL
  136.  
  137.         POP     DI                      ; fetch offset
  138. LoopVert:
  139.         MOV     AL,[DI]                 ; latch data(to preserve other 7 bits i
  140.         MOV     [DI],AL                 ; write new data (only one bit will be
  141.         ADD     DI,BX                   ; update offset
  142.         LOOP    LoopVert
  143.         JMP     LineDone
  144.  
  145. ;-------GENERATE A HORIZONTAL LINE ---------------
  146.  
  147. Horiz:  MOV     CX,SI                   ; set counter of pixels
  148.         POP     SI                      ; fetch mask
  149.         POP     DI                      ; fetch offset
  150.  
  151.         ;---    draw pixels from the leading partial byte
  152.  
  153.         MOV     AX,X0
  154.         AND     AX,07h                  ; check for partial byte
  155.         JZ      FullBytes
  156.         MOV     BX,0FFh                 ; compute the mask
  157.         PUSH    CX
  158.         MOV     CX,AX
  159.         SHR     BX,CL
  160.         POP     CX
  161.         ADD     CX,AX                   ; update counter
  162.         SUB     CX,08h
  163.         JGE     MaskSet                 ; modify mask if only one byte
  164.         NEG     CX
  165.         SHR     BX,CL
  166.         SHL     BX,CL
  167.         XOR     CX,CX                   ; restore counter
  168. MaskSet:
  169.         MOV     DX,03CEh                ; set the mask
  170.         MOV     AL,08h
  171.         OUT     DX,AL
  172.         INC     DX
  173.         MOV     AL,BL
  174.         OUT     DX,AL
  175.         MOV     AH,[DI]                 ; latch data
  176.         MOV     [DI],AL                 ; write new data
  177.         INC     DI                      ; update offset
  178.  
  179.         ;---    draw pixels from the middle complete bytes
  180. FullBytes:                              ;
  181.         MOV     BX,CX                   ; check if any bytes to set
  182.         CMP     DX,8
  183.         JL      TrailBytes
  184.         SHR     CX,1                    ; compute count
  185.         SHR     CX,1
  186.         SHR     CX,1
  187.         MOV     DX,03CEh                ; set the mask
  188.         MOV     AL,08h
  189.         OUT     DX,AL
  190.         INC     DX
  191.         MOV     AL,0FFh
  192.         OUT     DX,AL
  193.  
  194.         REP     STOSB                   ; fill complete bytes
  195.  
  196.         ;---    draw pixels from the trailing partial byte
  197. TrailBytes:
  198.         AND     BX,07h
  199.         JZ      HorizDone
  200.         MOV     AX,0FFFFh                ; compute mask
  201.         MOV     CX,BX
  202.         SHR     AX,CL
  203.         XOR     AH,0FFh                  ; set the mask
  204.         MOV     DX,03CEh
  205.         MOV     AL,08h
  206.         OUT     DX,AL
  207.         INC     DX
  208.         MOV     AL,AH
  209.         OUT     DX,AL
  210.         MOV     AL,[DI]                  ; latch data
  211.         MOV     [DI],AL                  ; set new data
  212. HorizDone:
  213.         JMP     LineDone
  214.  
  215. ;----------------------- GENERATE A DIAGONAL LINE -----------------
  216.  
  217.         ;--- figure out which quarter does the line lie in
  218.  
  219. Diag:   CMP     SI,DI                   ; Is dy > dx
  220.         JLE     oct12                   ; ...Yes, do processing in octants
  221.                                         ;    1 and 2
  222.         ; Compute constants for octant zero and three
  223.         ; This is where x is the major direction and y is minor
  224.  
  225. oct03:  MOV     CX,SI                   ; set counter to dx+1
  226.         INC     CX
  227.         SAL     DI,1                    ; d1 = dy*2             reg-di
  228.         MOV     BX,DI                   ; d  = dy*2-dx          reg-bx
  229.         SUB     BX,SI
  230.         NEG     SI                      ; d2 = dy*2-dx-dx       reg-si
  231.         ADD     SI,BX
  232.  
  233.         MOV     [bp-2],di               ; save d1
  234.         MOV     [bp-4],si               ; save d2
  235.         MOV     DX,03CEh                ; select BIT MASK register
  236.         MOV     AL,08h
  237.         OUT     DX,AL
  238.         INC     DX
  239.         POP     AX                      ; fetch mask
  240.         POP     DI                      ; fetch address
  241.  
  242.         ;-------------- GENERATE LINE IN THE OCTANT ZERO AND THREE ------
  243.  
  244. next0:  OUT     DX,AL                   ; enable a bit in a byte
  245.         MOV     AH,[DI]                 ; latch old data
  246.         MOV     [DI],AH                 ; modify (enabled bits)
  247.  
  248.         ROR     AL,1                    ; update mask
  249.         ADC     DI,0                    ; update byte address
  250.  
  251.         TEST    BX,8000H                ; if d >= 0 then ...
  252.         JNZ     dneg0
  253.         ADD     BX,[BP-4]               ; ... d = d + d2
  254.         ADD     DI,[BP-6]               ; update offset to next scan line
  255.         LOOP    next0
  256.         JMP     LineDone
  257.  
  258. dneg0:  ADD     BX,[BP-2]               ; if d < 0 then d = d + d1
  259.         LOOP    next0
  260.         JMP     LineDone
  261.  
  262.         ;----------------------------------------------------------------
  263.  
  264.         ;---    Compute constants for octant one and two
  265.  
  266. oct12:  MOV     CX,DI                   ; set counter to dy+1
  267.         INC     CX
  268.         SAL     SI,1                    ; d1 = dx * 2
  269.         MOV     BX,SI                   ; d  = dx * 2 - dy
  270.         SUB     BX,DI
  271.         NEG     DI                      ; d2 = -dy + dx * 2 - dy
  272.         ADD     DI,BX
  273.  
  274.         MOV     [BP-4],DI               ; save d2
  275.         MOV     [BP-2],SI               ; save d1
  276.         MOV     dx,03CEh                ; select BIT MASK register
  277.         MOV     al,08h
  278.         OUT     DX,AL
  279.         INC     DX
  280.         POP     AX                      ; fetch mask
  281.         POP     DI                      ; fetch address
  282.         OUT     DX,AL                   ; enable a bit in a byte
  283.  
  284.         ;-----GENERATE A LINE IN THE OCTANT ONE AND TWO -----------------
  285.  
  286. next1:  MOV     AH,[DI]                 ; latch old data
  287.         MOV     [DI],AH                 ; modify (enabled bits)
  288.  
  289.         ADD     DI,[BP-6]               ; update offset (y = y+1)
  290.  
  291.         TEST    BX,8000H                ; if d >= 0 then ...
  292.         JNZ     dneg1
  293.  
  294.         ADD     BX,[BP-4]               ; ... d = d + d2
  295.         ROR     AL,1                    ; ... update mask (x = x+1)
  296.         ADC     DI,0                    ; ... update offset
  297.         OUT     DX,AL                   ; Enable next bit within a byte
  298.         LOOP    next1
  299.         JMP     LineDone
  300.  
  301. dneg1:  ADD     BX,[BP-2]               ; if d < 0 then d = d + d1
  302.         LOOP    next1
  303.  
  304.         ;----------------------------------------------------------------
  305.         ;--- Restore PLANE ENABLE and BIT MASK registers
  306. LineDone:
  307.         MOV     DX,03CEh                ; Enable all 8-bits in a byte for write
  308.         MOV     AL,08h                  ; by setting BIT MASK register to Fhex
  309.         OUT     DX,AL
  310.         INC     DX
  311.         MOV     AL,0FFh
  312.         OUT     DX,AL
  313.  
  314.         DEC     DX                      ; Disable SET/RESET function
  315.         MOV     AL,1
  316.         OUT     DX,AL
  317.         INC     DX
  318.         XOR     AX,AX
  319.         OUT     DX,AL
  320.  
  321.         POP     ES
  322.         POP     DS
  323.         POP     SI
  324.         POP     DI
  325.         MOV     SP,BP
  326.         POP     BP
  327.         RET
  328. _Line   ENDP
  329.