Рисование линии - Assembler
Формулировка задачи:
Здравствуйте, прошу оказать помощь в выполнении задания. Требуется нарисовать линию: первая точка имеет координаты нажатия левой кнопки мыши, а вторая – правой. Нашел два кода для рисования линии, любой из них переделать бы (добавить вторую координату при нажатии правой кнопки мыши):
1) Здесь используется алгоритм Брезенхема, но здесь координата второй точки служит началом следующей линии.
2) А здесь все линии начинаются с центра.
.model tiny .code org 100h .186 start: mov ax, 12h ;X 12h+80h X ;включение видеорежима int 10h mov ax, 0 ; проверка драйверов мыши int 33h mov ax, 1 ;вывод курсора int 33h mov ax, 000Ch ; создание обработчика события mov cx, 0002h ; нажатие на левую кнопку мыши mov dx, offset handler int 33h mov ah, 0 int 16h mov ax, 000Ch ;удаляем mov cx, 0000h ;обработчик int 33h ; событий mov ax, 83h int 10h ret ; Обработчик событий от мыши handler: push 0A000h pop es push cs pop ds push cx push dx mov ax, 2 int 33h cmp word ptr previous_X, -1 je first_point call line_bresenham exit_handler: pop dx pop cx mov previous_X, cx mov previous_Y, dx mov ax, 1 int 33h retf first_point: call putpixel1b jmp short exit_handler ;Процедура рисования прямой линии line_bresenham: mov ax, cx sub ax, previous_X jns dx_pos neg ax mov word ptr X_increment, 1 jmp short dx_neg dx_pos: mov word ptr X_increment, -1 dx_neg: mov bx, dx sub bx, previous_Y jns dy_pos neg bx mov word ptr Y_increment, 1 jmp short dy_neg dy_pos: mov word ptr Y_increment, -1 dy_neg: shl ax, 1 shl bx, 1 call putpixel1b cmp ax, bx jna dx_le_dy mov di, ax shr di, 1 neg di add di, bx cycle: cmp cx, word ptr previous_X je exit_bres cmp di, 0 jl fractlt0 add dx, word ptr Y_increment sub di, ax fractlt0: add cx, word ptr X_increment add di, bx call putpixel1b jmp short cycle dx_le_dy: mov di, bx shr di, 1 neg di add di, ax cycle2: cmp dx, word ptr previous_Y je exit_bres cmp di, 0 jl fractlt02 add cx, word ptr X_increment sub di, bx fractlt02: add dx, word ptr Y_increment add di, ax call putpixel1b jmp short cycle2 exit_bres: ret ; Процедура вывода точки на экран putpixel1b: pusha xor bx, bx mov ax, dx imul ax, ax, 80 push cx shr cx, 3 add ax, cx mov di, ax mov si, di pop cx mov bx, 0080h and cx, 07h shr bx, cl lods es:byte ptr some_label or ax, bx stosb popa ret previous_X dw -1 previous_Y dw -1 Y_increment dw -1 X_increment dw -1 some_label: end start
.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
Не актуально.
Решение задачи: «Рисование линии»
textual
Листинг программы
draw.line: ;рисование точки ;stdcall draw.add_op (x1:DWORD, y1:DWORD, x2:DWORD, y2:DWORD) draw.line.x1 equ [ebp+4*4-4] draw.line.y1 equ [ebp+4*4-8] draw.line.x2 equ [ebp+4*4-12] draw.line.y2 equ [ebp+4*4-16] push ebp lea ebp,[esp+8] pusha mov eax,draw.line.x2 cmp eax,draw.line.x1 ;прямые, параллельные Ox или Oy jne draw.line.not_vert ;рисуем вертикальную линию mov edx,draw.XRes shl edx,2 mov eax,draw.line.y1 cmp eax,draw.line.y2 jc @f xchg eax,draw.line.y2 mov draw.line.y1,eax @@: mov edi,draw.XRes imul edi,draw.line.y1 add edi,draw.line.x1 shl edi,2 add edi,[draw.buff] mov eax,[draw.color] mov ecx,draw.line.y2 sub ecx,draw.line.y1 test ecx,80000000h jz @f neg ecx @@: mov [edi],eax add edi,edx dec ecx jnz @b jmp draw.line.exit draw.line.not_vert: mov eax,draw.line.y2 cmp eax,draw.line.y1 jne draw.line.not_hor ;рисуем горизонтальную линию mov eax,draw.line.x1 cmp eax,draw.line.x2 jc @f xchg eax,draw.line.x2 mov draw.line.x1,eax @@: mov edi,draw.XRes imul edi,draw.line.y1 add edi,draw.line.x1 shl edi,2 add edi,[draw.buff] mov eax,[draw.color] mov ecx,draw.line.x2 sub ecx,draw.line.x1 rep stosd jmp draw.line.exit draw.line.not_hor: ;с наклоном 45 градусов sub eax,draw.line.y1 test eax,80000000h jz @f neg eax @@: mov ebx,draw.line.x2 sub ebx,draw.line.x1 test ebx,80000000h jz @f neg ebx @@: cmp ebx,eax jne draw.line.not_45 mov eax,draw.line.x1 cmp eax,draw.line.x2 jc @f xchg eax,draw.line.x2 mov draw.line.x1,eax @@: mov ecx,ebx mov eax,draw.line.y2 sub eax,draw.line.y1 mov edx,01h test eax,80000000h jz @f neg edx @@: imul edx,draw.XRes inc edx shl edx,2 mov edi,draw.XRes imul edi,draw.line.y1 add edi,draw.line.x1 shl edi,2 add edi,[draw.buff] mov eax,[draw.color] @@: mov [edi],eax add edi,edx dec ecx jnz @b jmp draw.line.exit draw.line.not_45: ;все остальные mov edi,draw.line.y1 mov edx,draw.XRes*4 mov ebx,draw.line.y2 sub ebx,draw.line.y1 jnc @f mov edx,-draw.XRes*4 neg ebx @@: imul edi,draw.XRes add edi,draw.line.x1 shl edi,2 add edi,[draw.buff] mov eax,draw.line.x2 sub eax,draw.line.x1 mov ebp,4 jnc @f mov ebp,-4 neg eax @@: mov esi,[draw.color] mov [draw.line.counter],00h cmp eax,ebx jc draw.line.Y draw.line.X: mov ecx,eax draw.line.X.loop: mov [edi],esi add edi,ebp add [draw.line.counter],ebx cmp [draw.line.counter],eax jc @f add edi,edx sub [draw.line.counter],eax @@: dec ecx jnz draw.line.X.loop jmp draw.line.exit draw.line.Y: mov ecx,ebx draw.line.Y.loop: mov [edi],esi add edi,edx add [draw.line.counter],eax cmp [draw.line.counter],ebx jc @f add edi,ebp sub [draw.line.counter],ebx @@: dec ecx jnz draw.line.Y.loop jmp draw.line.exit draw.line.dx dd 0 draw.line.dy dd 0 draw.line.counter dd 0 draw.line.exit: popa ;возват из процедуры pop ebp pop eax add esp,4*4 ;общий размер передаваемых операндов push eax mov eax,00h ret