79-byte Copper bar x 3Assembler/80386

This is a small program that displays 3 copper bars at the same time. The program is richly commented and should be quite easy to understand.
The source and a compiled version is available for download (1917 bytes).

;---------------------------------------------------------------------
; COPPER3 - 3 simultaneous copper bars, 79 bytes! - final version by
; Tylisha C. Andersen - notable contributions by T.Remmel and J.Neil
;---------------------------------------------------------------------

b       equ     
w       equ     

.model  tiny
.code
org     100h

;---------------------------------------------------------------------

main:   pop     bx              ; zero bx by popping the return address
                                ;
m_1:    push    bx              ; write 3 positions and increments
        inc     bx              ; the jpo instruction jumps when there are
        push    bx              ; an odd number of set bits in the lower 8
        jpo     m_1             ; bits of the result;  this is true for
                                ; 1 (01b) and 2 (10b), but false for 3 (11b)

m_2:    cli                     ; disable interrupts
        mov     ah,8            ; ah = 8 for vertical retrace
        mov     cx,390          ; for each of 390 scanlines:
                                ;
m_3:    mov     dx,03DAh        ; dx = IS1 port, wait for retrace
m_4:    in      al,dx           ; retrace could be vertical or horizontal
        and     al,ah           ; due to the design of the VGA this ends in
        jnz     m_4             ; the horizontal retrace if ah = 01h, but in
m_5:    in      al,dx           ; the active vertical period if ah = 08h,
        and     al,ah           ; which is exactly what we need
        jz      m_5
        mov     dl,0C8h         ; dx = DAC write select port
        xchg    ax,bx           ; al = 0, select DAC register 0
        out     dx,al
        inc     dx

        mov     si,sp           ; si = ptr. to position data list
        mov     bl,3            ; for each of 3 colors:

m_6:    lodsw                   ; ax = increment - tricky use of loop,
        loop    m_7             ; jumps when cx <> 1 to test for last line
                                ; if on last scanline, then
        sub     [si],ax         ; add increment to position, if this puts it
        cmp     w [si],-263     ; out of range, then bounce
        ja      m_7             ; 263 is the max. position of the top of a
        neg     w [si-2]        ; bar without it going off the screen

m_7:    inc     cx              ; restore cx (it was decremented by 'loop')
        lodsw                   ; ax = position, si now = next color
        add     ax,cx           ; ax = line + position
        cmp     ax,127          ; if it's not inside the bar, then set the
        jbe     m_8             ; color to 0 (xor al,al);  otherwise...
        xor     al,al
m_8:    cmp     al,64           ; if it's greater than 64, this means it's
        jb      m_9             ; on the top part where it is fading out, so
        not     al              ; we negate it (the top 2 bits are ignored)

m_9:    out     dx,al           ; set color intensity, and loop (remember,
        dec     bx              ; parity is only on the lower 8 bits, so it
        jpo     m_6             ; doesn't matter what bh contains)

        mov     ah,1            ; ah = 01h for horiz. retrace, key check
        loop    m_3             ; loop
        int     16h             ; check for key press (enables interrupts)
        jz      m_2             ; loop while no key pressed
        int     20h             ; return to DOS

end     main
Gem writers: Tylisha C. Andersen
Tenie Remmel
Jim Neil
last updated: 1998-06-07