1. Получи 30.000 рублей. Для получения денег необходимо принять участие в конкурсе авторов codeby. С условиями и призами можно ознакомиться на этой странице ...

    Внимание! Регистрация авторов на конкурс закрыта.

    Скрыть объявление
  2. Требуются разработчики и тестеры для проекта codebyOS. Требования для участия в проекте: Знание принципов работы ОС на базе Linux; Знание Bash; Крайне желательное знание CPP, Python, Lua; Навыки системного администрирования. Подробнее ...

    Скрыть объявление

работа с мышкой

Тема в разделе "Остальные языки программирования", создана пользователем A, 23 ноя 2010.

  1. A

    A Гость

    Репутация:
    0
    Помогите пожалуйста переделать, чтобы каждый раз линии рисовались новым цветом.
    Код:
    ; 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
     
  2. A

    A Гость

    Репутация:
    0
    все. я разобрался. вот, если кому нужно.
    Код:
    ; 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:
    inc color
    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		; Вывод одной точки (при первом вызове).
    mov 		ah, 2
    mov 		dl, 07h			
    int 		21h
    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:
    mov 		ah, 2
    mov 		dl, 07h			
    int 		21h
    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 10
    some_label:						; Метка, используемая для переопределения
    ; сегмента-источника для lods с DS на ES.
    end	start
     
Загрузка...

Поделиться этой страницей