.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