.model    tiny
        .code

        org        100h            ; COM-����.
        .186                    ; ��� ������� shr cx, 3.
start:
        mov        ax, 12h
        int        10h            ; ���������� 640*480.
        mov        ax, 0            ; ���������������� ����.
        int        33h
        mov        ax, 1            ; �������� ������ ����.
        int        33h
        
        mov        ax, 000Ch        ; ���������� ���������� ������� ����.
        mov        cx, 0002h        ; ������� - ������� ����� ������.
        mov        dx, offset handler    ; ES:DX - ����� �����������.
        int        33h
        
        mov        ah, 0            ; �������� ������� ����� �������.
        int        16h
        mov        ax, 000Ch
        mov        cx, 0000h        ; ������� ���������� ������� ����.
        int        33h
        mov        ax, 3            ; �������� �����.
        int        10h
        ret                    ; ����� ���������.

; ���������� ������� ����: ��� ������ ������� ������� ����� �� �����,
; ��� ������ ���������� ������ �������� ������ ����� �� ����������
; ����� � �������.
        
handler:
        push        0A000h
        pop        es            ; ES - ������ �����������.
        push        cs
        pop        ds            ; DS - ������� ���� � ������ ���� ���������.
        push        cx            ; CX (X-����������) � DX(Y-����������)
        push        dx            ; ����������� � �����.
        
        mov        ax, 2            ; �������� ������ ���� ����� ������� �� �����.
        int        33h
        
        cmp        word ptr previous_X, -1; ���� ��� ������ �����,
        je        first_point        ; ������ ������� �����.
        
        call        line_bresenham    ; ����� - �������� ������.                            

exit_handler:
        pop        dx            ; ������������ CX � DX
        pop        cx
        mov        previous_X, cx    ; � ��������� �� ��� ����������
        mov        previous_Y, dx    ; ����������.
        
        mov        ax, 1            ; �������� ������ ����.
        int        33h
        
        retf                    ; ����� �� ����������� - ������� RETF.
        
first_point:        
        call        putpixellb        ; ����� ����� ����� (��� ������ ������).
        jmp        short exit_handler        

; ��������� ��������� ������ ����� � �������������� ��������� ����������.
; ����� CX, DX - X, Y ��������� �����.
; previous_X, previous_Y - X, Y ��������� �����.
        
line_bresenham:
        mov        ax, cx
        sub        ax, previous_X    ; AX = ����� �������� ������ �� ��� X.
        jns        dx_pos        ; ���� AX ������������� -
        neg        ax            ; ������� ��� ����, ������
        mov        word ptr X_increment, 1; ���������� X ��� ������
        jmp        short dx_neg    ; ������ ����� �����.
dx_pos:    mov        word ptr X_increment, -1; ����� - �����������.

dx_neg:    mov        bx, dx
        sub        bx, previous_Y    ; BX = ����� �������� ������ �� ��� Y.
        jns        dy_pos        ; ���� BX ������������� - 
        neg        bx            ; ������� ��� ����, ������
        mov        word ptr Y_increment, 1; ���������� Y ��� ������
        jmp        short dy_neg        ; ������ ����� �����.
dy_pos:    mov        word ptr Y_increment, -1; ����� - �����������.
dy_neg:
        shl        ax, 1            ; ������� �������� ��������,
        shl        bx, 1            ; ����� �������� ������ � ���������� �������.
        
        call        putpixellb        ; ������� ������ ����� (������ �������� ��
                            ; CX, DX � previous_X, previous_Y).
        cmp        ax, bx            ; ���� �������� �� ��� X ������, ��� �� Y,
        jna        dx_le_dy
        mov        di, ax            ; DI ����� ���������, � ����� ������� ��
        shr        di, 1            ; ����������� �� ��������� ������.
        neg        di            ; ����������� ��������� �������� DI:
        add        di, bx            ; DI = 2 * dy - dx
cycle:
        cmp        cx, word ptr previous_X; �������� ���� �����������,
        je        exit_bres        ; ���� X �� ������ ������ previous_X.
        cmp        di, 0            ; ���� DI > 0,
        jl        fractlt0

        add        dx, word ptr Y_increment; ������� � ���������� Y
        sub        di, ax            ; � ��������� DI �� 2 * dx.
fractlt0:
        add        cx, word ptr X_increment; ��������� X (�� ������ ����).
        add        di, bx            ; ��������� �� DI �� 2 * dy.
        call        putpixellb        ; ������� �����.                                                    ;!!!!!
        jmp        short cycle        ; ���������� ����.
        
dx_le_dy:                        ; ���� �������� �� ��� Y ������, ��� �� X.
        mov        di, bx
        shr        di, 1
        neg        di            ; ����������� ��������� �������� DI:
        add        di, ax            ; DI = 2 * dx - dy.
cycle2:
        cmp        dx, word ptr previous_Y; �������� ���� �����������,
        je        exit_bres        ; ���� Y �� ������ ������ previous_Y.
        cmp        di, 0            ; ���� DI > 0,
        jl        fractlt02
        add        cx, word ptr X_increment; ������� � ���������� X
        sub        di, bx            ; � ��������� DI �� 2 * dy,
fractlt02:
        add        dx, word ptr Y_increment; ��������� Y (�� ������ ����).
        add        di, ax            ; ��������� DI �� 2 * dy,
        call        putpixellb        ; ������� �����,
        jmp        short cycle2        ; ���������� ����.
exit_bres:
        ret                    ; ����� ���������.

; ��������� ������ ����� �� ����� � ������, ������������ ���� ��� ���
; �������� ������ �������.
; DX = ������, CX = �������.
; ��� �������� �����������.
        
putpixellb:
	pusha			; ��������� ��������.
	mov ah, 0ch
	mov bh, 0
	mov al, color
	int 10h
	popa			; ������������ ��������.
        ret				; �����.
        
previous_X	dw -1	; ���������� X-����������.
previous_Y	dw -1	; ���������� Y-����������.
Y_increment	dw -1	; ����������� ��������� Y.
X_increment	dw -1	; ����������� ��������� X.
color			db 2		; ���� ������ ������� �����
        end    start