Поиск:

Ответ в темуСоздание новой темы Создание опроса
> работа с мышкой 
:(
    Опции темы
Aндрей
Дата 23.11.2010, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 15.2.2009

Репутация: нет
Всего: нет



Помогите пожалуйста переделать, чтобы каждый раз линии рисовались новым цветом.
Код

 ; 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


PM MAIL   Вверх
Aндрей
Дата 1.12.2010, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 15.2.2009

Репутация: нет
Всего: нет



все. я разобрался. вот:
Код

; 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

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Asm для начинающих"
MAKCim
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой КОД.
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, MAKCim.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Asm для начинающих | Следующая тема »


 




[ Время генерации скрипта: 0.0462 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.