; mousedr.asm
;Рисует на экране прямые линии, оканчивающиеся в позициях, которые указываются мышью.
;
.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 ; Сохранить регистры.
xor bx, bx
mov ax, dx ; AX = номер строки.
imul ax, ax, 80 ; AX = номер строки x число байтов в строке.
push cx
shr cx, 3 ; CX = номер байта в строке.
add ax, cx ; AX = номер байта в видеопамяти.
mov di, ax ; Поместить его в SI и DI для команд
mov si, di ; строковой обработки.
pop cx ; CX снова содержит номер столбца.
mov bx, 0080h
and cx, 07h ; Последние три бита CX =
; остаток от деления на 8 = номер бита в байте
; считая справа налево.
shr bx, cl ; Теперь в BL установлен в 1 нужный бит.
lods es: byte ptr some_label ; AL = байт из видеопамяти.
;or ax, bx ; Установить выводимый бит в 1,
; Чтобы стереть пиксел с экрана, эту команду OR можно заменить на
not bx
and ax, bx
; или лучше инициализировать BX не числом 0080h, а числом FF7Fh и использовать
; только and
stosb ; И вернуть байт на место.
popa ; Восстановить регистры.
ret ; Конец.
previous_X dw -1 ; Предыдущая X-координата.
previous_Y dw -1 ; Предыдущая Y-координата.
Y_increment dw -1 ; Направление изменения Y.
X_increment dw -1 ; Направление изменения X.
some_label: ; Метка, используемая для переопределения
; сегмента-источника для lods с DS на ES.
end start
pusha ; Сохранить регистры.
xor bx, bx
mov ax, dx ; AX = номер строки.
imul ax, ax, 80 ; AX = номер строки x число байтов в строке.
push cx
shr cx, 3 ; CX = номер байта в строке.
add ax, cx ; AX = номер байта в видеопамяти.
mov di, ax ; Поместить его в SI и DI для команд
mov si, di ; строковой обработки.
pop cx ; CX снова содержит номер столбца.
mov bx, 0080h
and cx, 07h ; Последние три бита CX =
; остаток от деления на 8 = номер бита в байте
; считая справа налево.
shr bx, cl ; Теперь в BL установлен в 1 нужный бит.
lods es: byte ptr some_label ; AL = байт из видеопамяти.
;or ax, bx ; Установить выводимый бит в 1,
; Чтобы стереть пиксел с экрана, эту команду OR можно заменить на
not bx
and ax, bx
; или лучше инициализировать BX не числом 0080h, а числом FF7Fh и использовать
; только and
stosb ; И вернуть байт на место.
popa ; Восстановить регистры.
ret ; Конец.
previous_X dw -1 ; Предыдущая X-координата.
previous_Y dw -1 ; Предыдущая Y-координата.
Y_increment dw -1 ; Направление изменения Y.
X_increment dw -1 ; Направление изменения X.
some_label: ; Метка, используемая для переопределения
; сегмента-источника для lods с DS на ES.
end start
вывод какого сигнала ? куда выводить ?
Просто чтобы при нажатии левой кнопки мыши звучал какой-нибудь один звук..
Код:
mov al,10110110b
out 43h,al
mov al,0dh
out 42h,al
mov al,11h
out 42h,al
in al,61h
or al,00000011b
out 61h,al
out 43h,al
mov al,0dh
out 42h,al
mov al,11h
out 42h,al
in al,61h
or al,00000011b
out 61h,al
выключение динамика:
Код:
in al,61h
and al,11111100b
out 61h,al
and al,11111100b
out 61h,al
ваша программа очень корявая . отрисовку на экран в обработчике прерывания никто не делает . обработчик прерывания должен выпольнять минимальные действия с источником прерывания , а обработка данных производится в основном цикле программы .
Код:
mov ah, 2
mov dl, 07h; функция вывода сигнала
int 21h
mov dl, 07h; функция вывода сигнала
int 21h
Объясните пожалуйста вот это место в программе.
Код:
previous_X dw -1 ; Предыдущая X-координата.
previous_Y dw -1 ; Предыдущая Y-координата.
Y_increment dw -1 ; Направление изменения Y.
X_increment dw -1 ; Направление изменения X.
some_label: ; Метка, используемая для переопределения
; сегмента-источника для lods с DS на ES.
previous_Y dw -1 ; Предыдущая Y-координата.
Y_increment dw -1 ; Направление изменения Y.
X_increment dw -1 ; Направление изменения X.
some_label: ; Метка, используемая для переопределения
; сегмента-источника для lods с DS на ES.
код в проге объявляет четыре двухбайтовых переменных с начальным значением =0xFFFF
а метка - она и в африке метка )
А "-1" это просто типо первоначальные значения?
да, начальное