Форум программистов, компьютерный форум, киберфорум
Assembler: DOS/Real Mode/16-bits
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.89/27: Рейтинг темы: голосов - 27, средняя оценка - 4.89
1 / 1 / 0
Регистрация: 27.02.2009
Сообщений: 24
TASM

Рисование на экране прямых линий, оканчивающиеся в позициях, которые указываются мышью

21.11.2010, 00:36. Показов 5890. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Программа должна рисовать на экране прямые линии, оканчивающиеся в позициях, которые указываются мышью. Набрал текст из учебника: Зубков - "Assembler dlya DOS, Windows i UNIX" и сверил его много раз, вроде все правильно. Запускаю программу, можно перемещать курсор, но когда нажимаю левую кнопку, программа повисает. Помогите разобраться в чем проблема.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
; 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        putpixel1b          ; Вывод одной точки (при первом вызове).
        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        putpixel1b          ; Вывести первую точку (прямая рисуется от
                                ; 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        putpixel1b          ; Вывести точку.                                                        ;!!!!!
        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        putpixel1b          ; вывести точку,
        jmp     short cycle2            ; продолжить цикл.
exit_bres:
        ret                     ; Конец процедуры.
 
; Процедура вывода точки на экран в режиме, использующем один бит для
; хранения одного пикселя.
; DX = строка, CX = столбец.
; Все регистры сохраняются.
        
putpixel1b:
        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
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.11.2010, 00:36
Ответы с готовыми решениями:

Могут ли на экране высвечиваться одновременно отрезки прямых линий разных цветов?
Могут ли на экране высвечиваться одновременно отрезки прямых линий разных цветов?

Дан набор прямых линий на плоскости. Найти количество областей, на которые они разбивают плоскость
Здравствуйте уважаемые форумчане. Помогите пожалуйста с задачкой: Дан набор прямых линий на плоскости, которые могут пересекаться. Найти...

Рисование непересекающихся линий, которые задаются кликом мыши
Доброго времени суток всем! Очень нужна помощь новичку в C#. Задача: Рисование линий по двум точкам, которые выбирает...

7
4190 / 1838 / 221
Регистрация: 06.10.2010
Сообщений: 4,124
21.11.2010, 07:46
Функция line использует соглашение stdcall.
Прототип:
C
1
void line(WORD x1, WORD y1, WORD x2, WORD y2)
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
.model tiny
.486
.code
org 100h
start:
mov ax,13h
int 10h
 
xor ax,ax
int 33h
mov ax,1
int 33h
 
mov ax,12
mov cx,2
mov dx,offset handler
int 33h
 
xor ax,ax
int 16h
ret
 
handler:
  mov  ax,2
  int  33h
  push dx
  shr  cx,1
  push cx
  push 100
  push 160
  call line
  mov  ax,1
  int  33h
retf
 
 
line:
  push bp
  mov  bp,sp
  imul di,ss:[bp+6],320
  add  di,ss:[bp+4]
 
  mov  ax,ss:[bp+8]
  sub  ax,ss:[bp+4]
  sbb  bx,bx
  mov  dx,ss:[bp+10]
  sub  dx,ss:[bp+6]
  sbb  cx,cx
 
  mov  si,ax
  or   si,dx
  je   quit
 
  xor  ax,bx
  sub  ax,bx
  xor  dx,cx
  sub  dx,cx
 
  or   bx,1
  mov  si,cx
  xor  cx,320
  sub  cx,si
 
  cmp  ax,dx
  ja a
      xchg ax,dx
      xchg bx,cx
  a:
 
  push 0A000h
  pop  es
 
  mov  si,ax
  mov  bp,ax
  b:mov byte ptr es:[di],2
    sub si,dx
    jnl next
      add si,ax
      add di,cx
    next:
    add di,bx
    dec bp
  jne b
 
  quit:
  mov byte ptr es:[di],2
  pop bp
ret 8
 
end start
3
1 / 1 / 0
Регистрация: 27.02.2009
Сообщений: 24
21.11.2010, 11:03  [ТС]
Почему-то тоже самое. Запускаю, бегает курсор, нажимаю левую кнопку и курсор больше не двигается.
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
21.11.2010, 13:10
Как компилируете ?
0
1 / 1 / 0
Регистрация: 27.02.2009
Сообщений: 24
21.11.2010, 13:25  [ТС]
Запускаю командную строку, перехожу в папку с tasm (cd c:\tasm).
набираю tasm mouse, потом tlink mouse, mouse.
0
 Аватар для Goodwin98
2537 / 833 / 10
Регистрация: 31.05.2009
Сообщений: 1,668
21.11.2010, 13:33
Это com программы, а вы их линкуете как exe.

Code
1
tlink /t mouse
1
1 / 1 / 0
Регистрация: 27.02.2009
Сообщений: 24
21.11.2010, 15:56  [ТС]
Спасибо Goodwin98. Теперь ничего не зависает. Программа murderer работает отлично. Но программа из учебника не рисует линии почему-то. А можно как-то исправить код который я из учебника набирал? Просто там все коментарии есть, а мне эту прогу сдавать надо.. Пожалуйста, если можете помогите. буду очень благодарен.

Добавлено через 6 минут
Все разобрался. все рисуется)) Нужно было исправить в putpixel1b на putpixellb

Добавлено через 1 час 48 минут
Последний вопрос, помогите пожалуйста!!! с выводом сигнала при нажатии кнопки мыши
0
1 / 1 / 0
Регистрация: 27.02.2009
Сообщений: 24
01.12.2010, 19:36  [ТС]
все, разобрался, вот это добавить нужно было:
Assembler
1
2
3
mov ah, 2
mov dl, 07h; функция вывода сигнала
int 21h
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
01.12.2010, 19:36
Помогаю со студенческими работами здесь

Переписать из таблицы f в таблицу g коэффициенты тех прямых, которые: параллельны первой из прямых
Прямая на плоскости задается уравнением ax+by+c=0 , где a и b од-новременно не равны нулю. Будем рассматривать только прямые, для которых...

Переписать из файла f в файл g коэффициенты прямых, которые пересекают первую из прямых, заданных в файле f
С# Прямая на плоскости задается уравнением ax+by+c=0, где a и b одновременно не равны нулю. Будем рассматривать только прямые, для...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru