Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Ничего сложного - надо круг нарисовать  (Прочитано 36110 раз)
0 Пользователей и 1 Гость смотрят эту тему.
raYNor
Гость
« : 27-05-2004 19:44 » 

Есть хороший алгоритм прорисовки круга на С++ :

void circle(int xc, int yc, int r, char c)
{
      int x = 0, y = r, d = 2 * (1 - r);
      putpixel(xc + r, yc, c);
      putpixel(xc - r, yc, c);
      while(y > 0)
      {
       putpixel(xc + x, yc + y, c);
       putpixel(xc + x, yc - y, c);
       putpixel(xc - x, yc + y, c);
       putpixel(xc - x, yc - y, c);
       if(d + y > 0)
       {
        y -= 1;
        d -= (2 * y) - 1;
       }
       if(x > d)
       {
        x += 1;
        d += (2 * x) + 1;
       }
      }
}

Надо тоже самое сделать на ассемблере, вот что у меня получилось:
.MODEL tiny     ;Create *.com
;.model   small ;Create *.exe

.DATA
enlargebufferseg        dw 0    ; segment address of the 64*32 enlarge buf.
textureseg              dw 0    ; the segment address of texture to display.
fractalseg              dw 0    ; the segment address of texture to create
               
.CODE

.STARTUP

jmp Start

Screen MACRO col
mov     AH,0BH          ;Must be
mov     BX,col          ;Color
int     10H
ENDM

PutPixel MACRO x,y,color
mov     BX,color        ; Set color
mov     CX,x            ; set column
mov     DX,y            ; set line
mov     AH,0CH          ; Put picxel
mov     AL,BL
int     10H             ; BX, CX, DX are kept
ENDM

Getch MACRO
mov ax,0
int 16h
ENDM

Circle MACRO xc,yc,r,c
  x dw 0
  y dw 0
  d dw 0
  tmpx dw 0
  tmpy dw 0
  mov ax,0
  mov x,ax        ;x=0
  mov ax,r
  mov y,ax        ;y=r
 
   mov bx,2
   sbb bx,r
   sbb bx,r
   mov d,bx        ;d = 2*(1-r)

  PutPixel xc+r,yc,c          ; xc+r,yc
  PutPixel xc-r,yc,c          ; xc-r,yc

  .WHILE y>0
   mov ax,xc
   adc ax,x
   mov tmpx,ax
    mov ax,yc
    adc ax,y
    mov tmpy,ax
   PutPixel tmpx,tmpy,c          ; xc+x,yc+y

    mov bx,yc
    sbb bx,y
    mov tmpy,bx
   PutPixel tmpx,tmpy,c          ; xc+x,yc-y

   mov bx,xc
   sbb bx,x
   mov tmpx,bx
    mov ax,yc
    adc ax,y
    mov tmpy,ax
   PutPixel tmpx,tmpy,c          ; xc-x,yc+y

    mov bx,yc
    sbb bx,y
    mov tmpy,bx
   PutPixel tmpx,tmpy,c          ; xc-x,yc-y

   mov ax,d
   adc ax,y
   .IF ax>0
     mov bx,y
     sbb bx,1
     mov y,bx    ;y = y-1
     mov bx,d
     adc bx,1    
     sbb bx,y
     sbb bx,y
     mov d,bx    ;d = d-(2*y - 1) = d+1-y-y
   .ENDIF
   mov bx,x
   sbb bx,d
   .IF bx>0
      mov ax,x
      adc ax,1
      mov x,ax   ;x = x + 1
      mov bx,d
      adc bx,x
      adc bx,x
      adc bx,1
      mov d,bx   ;d =d + (2 * x) + 1 = d+x+x+1
   .ENDIF  
  .ENDW
ENDM


Init:
push ax
push bx
; 1) Setup ES segment
mov ax,0a000h
mov es,ax
; 2) Allocate RAM
; This is a COM program, so we just set the segments to spare
; space in memory. (well, hopefully spare space Улыбаюсь
push cs
pop ax
add ax,4096     ; textureseg is 64k above our segment
mov textureseg,ax
add ax,4096     ; and fractalseg is 128k above
mov fractalseg,ax
sub ax,4096
sub ax,2048     ; enlargebuffer is 1/2 way through our segment.
mov enlargebufferseg,ax
; 3) Do graphics mode
mov ax,0012h   ;set 640 x 480  16 colors
int 10h
Screen 0       ;clear screen in black
pop bx
pop ax
ret


Shutdown:
push ax
mov ax,0003h
int 10h
pop ax
ret

Start:
call Init
Circle 320,220,50,6
Getch
Breakout:
call Shutdown
mov ah,09h
mov dx,'a'
int 21h
int 20h

END

Т.е. когда вызываю Circle 320,220,50,6
то выполняется макрос Circle, но вместо круга рисуется РОМБ.
Вопрос - что у меня неправильно в макросе Circle?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 28-05-2004 01:58 » 

поищи алгоритм Брезенхема
Записан

raYNor
Гость
« Ответ #2 : 28-05-2004 05:57 » 

Так это ОН и есть, только на С++, а его на Ams перевести надо Улыбаюсь))
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 28-05-2004 14:04 » 

ну вообще-то я не силён в ассемблере (специально не занимался им) и в построении его макросов, но попробую разобраться

 :arrow:
ну, начнём с того, что такие вещи - как подпрограмму имхо делают а не как макрос...

но допустим.

 :arrow:
вот тут :

Цитата

Circle MACRO xc,yc,r,c
x dw 0
y dw 0
d dw 0
tmpx dw 0
tmpy dw 0

mov ax,0
mov x,ax ;x=0
mov ax,r
mov y,ax ;y=r


резервирование ячеек под константы - не знаю как оно сейчас выполняется компилятором, но раньше было так, что они начнут выполняться как команды, если их оставить как есть сейчас и не обойти. После инициализации - это nop-ы, и ничего страшного. Но потом - если там будут данные - то дрова...
Записан

Anonymous
Гость
« Ответ #4 : 04-07-2004 22:14 » 

Люди я не очень понял
может проше sin и cos воспользоваться
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 05-07-2004 09:15 » 

ими - долго имхо
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 05-07-2004 09:22 » 

ну - где вы, крутые ассемблеристы ? Улыбаюсь
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 14-07-2004 19:24 » 

никто не слышит - тогда попробуем сами разобраться, если тебе ещё энто надо...

я попробую переписать макрос в виде подпрограммы (как время появится - но думаю сегодня-завтра)

на вход п/п - в регистрах должно подаваться:

DX=r (16 бит)
CX=yc (16 бит)
BX=xc (16 бит)
al=color (8 бит)

raYNor, но проверить, как оно работает я не смогу - только синтаксис, ты сам запустишь - и скажешь, какие косяки встретились Улыбаюсь
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 14-07-2004 21:11 » 

Ээээ... А в двух словах - в чем суть? Алексей1153, поясни, пожалуйста, суть.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 15-07-2004 10:28 » 

RXL, В смысле - в чём суть?

Я, кстати, почти дописал - скоро вывалю на обозрение Улыбаюсь
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 15-07-2004 16:12 » 

raYNor, - ошибку я твою нашёл

я подогнал сишную прогу под ассемблерные ограничения Ага

сделано ДОПУЩЕНИЕ, что  0 < R <15000, иначе пользоваться старшим битом как знаком не получится.

Код:
void CBrezenhamDlg::OnbnCIRCLE2() 
{
WORD xc=100;
WORD yc=100;
WORD r=50;
WORD c=RGB(0,255,0);

WORD x = 0;
WORD y = r;
WORD d = (~( (r - 1)<<2 ))+1;

putpixel(xc + r, yc, c);
putpixel(xc + (~r)+1, yc, c);

while(y != 0xffff)
{
putpixel(xc + x, yc + y, c);
putpixel(xc + x, yc + (~y)+1, c);
putpixel(xc + (~x)+1, yc + y, c);
putpixel(xc + (~x)+1, yc + (~y)+1, c);
if( !((d + y) & 0x8000) )
{
y --;
d = d + (~(y<<2));

}

if((d & 0x8000) || (!(d & 0x8000) && x>d))

//if(x > d)
{
x ++;
d += (x<<2) + 1;
}
}
}

void CBrezenhamDlg::putpixel(int x, int y, DWORD c)
{
CDC* dc=GetWindowDC();
dc->SetPixel(x,y,c);
ReleaseDC(dc);
}


ошибка тут

Код:
		if((d & 0x8000) || (!(d & 0x8000) && x>d))
//if(x > d)

(x > d) - если это проверять так напрямую, то это выражение всегда == false и получится ромб

а вот если учесть, что x - всегда положителен (15-й бит сброшен), a d - может быть как положительным, так и отрицательным, то проверку делаем так:

if( (d<0) || (d>0 && x>d))
{
}

а вот сама процедура на ассемблере - будет чуть попозже Улыбаюсь
Не успел я её дописать
« Последнее редактирование: 25-11-2007 22:06 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 15-07-2004 19:53 » 

эх, тряхнул стариной Улыбаюсь
вот что у меня вышло

Код:
circle:
;Процедура вывода окружности радиусом R
; с координатами центра (Xc,Yc) и цветом color
;Вход:
;DX=R (0 <= R < 15000) ,
;CX=Yc , BX=Xc , al=color.
;Выход:
;Содержимое регистров: BX,AX,DX,ES,GS,FS меняется
;Содержимое регистров: CX не меняется

     ; инициализация
     push     cx
     mov     es,bx
     ; x=0
     push     0
     pop     gs
     ; y=R
     mov     cx,dx
     ; d=-2*(R-1)
     mov     bx,dx
     dec     bx
     rol     bx,1
     neg     bx

two_points:
     ; подготовка к выводу первых двух точек
     ; сохранение регистров
     xchg     cx,cs:[esp]
     push     dx
     push     dx
     xchg     cx,dx
     ; putpix(Xc+R,Yc,color)
     mov     fs,ax
     mov     ax,es
     add     cx,ax
     mov     ax,fs
     putpixel

     ; putpix(Xc-R,Yc,color)
     pop     cx
     neg     cx
     push     ax
     mov     ax,es
     add     cx,ax
     pop     ax
     putpixel

     ; восстановление регистров
     xchg     cx,dx
     pop     dx
     xchg     cx,cs:[esp]

check_y:
     ; y<0 ?
     cmp     cx,0ffffh
     jz     end_circle     ;переход если y<0

four_points:
     ; подготовка к выводу очередных 4 точек
     ; сохранение регистров
     mov     fs,cx
     xchg     cx,cs:[esp]
     push     bx
     push     dx
     push     cx
     push     cx
     push     es
     push     cx
     xchg     cx,dx

     ; putpix(Xc+X,Yc+Y,color)
     ; (Xc+X) == (cx=es+gs)
     mov     cx,es
     push     ax
     mov     ax,cs
     add     cx,ax
     pop     ax
     ; (Yc+Y) == (dx=dx+fs)
     push     ax
     mov     ax,fs
     add     dx,ax
     pop     ax
     putpixel

     ; putpix(Xc+X,Yc-Y,color)
     pop     dx
     ; (Yc-Y) == (dx=dx-fs)
     push     ax
     mov     ax,fs
     sub     dx,ax
     pop     ax
     putpixel

     ; putpix(Xc-X,Yc-Y,color)
     pop     cx
     ; (Xc-X) == (cx=es-gs)
     push     ax
     mov     ax,gs
     sub     cx,ax
     pop     ax
     putpixel

     ; putpix(Xc-X,Yc+Y,color)
     pop     dx
     ; (Yc+Y) == (dx=dx+fs)
     push     ax
     mov     ax,fs
     add     dx,ax
     pop     ax
     putpixel

     ; восстановление регистров
     pop     cx
     pop     dx
     pop     bx
     xchg     cx,cs:[esp]

     ;проверка d+y>0 ?
     push     bx
     add     bx,cx
     pop     bx
     jc     check_x_m_d     ;переход если d+y>0

     ; y=y-1;
     ; (d=d-2*y-1) == (bx=bx-2*cx-1)
     dec     cx
     push     cx
     rol     cx,2
     not     cx
     add     bx,cx
     pop     cx

check_x_m_d:

     ; проверка x>d ?
     ; сначала смотрим d>0
     bt     bx,15
     jc     check_y     ;переход если d+y>0
     ;затем смотрим x>d

     ; (x>d) == (gs>bx) == (bx>=gs)
     push     ax
     mov     ax,gs
     cmp     bx,ax
     pop     ax          ;pop-не влияет на флаги
     jnc     check_y     ;переход если d+y>0

     ; x=x+1
     push     ax
     mov     ax,gs
     inc     ax
     mov     gs,ax
     ; (d=d+2*x+1) == (bx=bx+(gs<<2)+1)
     rol     ax,1
     inc     ax
     add     bx,ax
     pop     ax
     ;переходим к следующим четырём точкам
     jmp     check_y

     ;окружность выведена
end_circle:
     ;очищаем стек и выходим
     pop     cx
     ret
;-----------------------------------------------
putpixel MACRO
;Макрос вывода пиксела с
;координатами (Xc,Yc) и цветом color
;Вход:
;DX=Y , CX=X , al=color.
;Выход:
;Содержимое регистров: AX,BX,CX,DX,ES,GS,FS не меняется
     push     AX
     mov     AH,0CH      ; Put picxel
     int     10H         ; BX, CX, DX are kept
     pop     AX
     ENDM
;-----------------------------------------------


макрос putpixel я переписал немного, но за основу взял твой. Там и добавлено только push AX  и pop AX

попробуй Улыбаюсь
если не пойдёт - будем дальше разбираться
« Последнее редактирование: 25-11-2007 22:07 от Алексей1153++ » Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 16-07-2004 08:46 » 

Алексей1153, не бери в голову - я просто невнимательно прочел предыдущее.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 16-07-2004 09:52 » 

RXL, кстати - может и проверишь заодно, работает или нет - а то Рэйнор похоже редко появляется

А вообще - где можно запускать ассемблерные проги - а то в VC вот это

__asm{}

даже в консольном приложении не желает генерировать прерывание 10H и вываливает БСОД...

RXL, посоветуй - что мне юзануть? (Какую среду имеется в виду)
 
и ещё - можно ли дополнительные сегментные регистры (fs, gs, es) использовать в  качестве регистров общего назначения, как я это сделал?(на невозможность использования их в командах ADD, SUB, CMP - я забил и заменил на эквиваленты)
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 18-07-2004 20:27 » 

Алексей1153, сервисы BIOS-а для реального режима и не должны быть доступны из win. Собирай каким-нибудь компилятором для DOS и там же запускай.
Я раньше пользовался tasm.

Кстати, консольная программа != DOS - не путай мягкое с теплым.

Использовать сегментные регистры таким макаром нерационально - загружать их можно только через MOV с AX и PUSH/POP. Лучше использовать стек, чем такой изврат.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 18-07-2004 20:51 » 

Попробовал.
Во-первых, esp в реальном режиме не нужен - заменил на sp.

Вот первые результаты:
Код:
Assembling file{   t1.asm
**Error** t1.asm)59: Illegal indexing mode
**Error** t1.asm)77: Forward reference needs override
**Error** t1.asm)82: Illegal indexing mode
**Error** t1.asm)84: Symbol redefined or moved between passes{ check_y
**Error** t1.asm)87: Forward reference needs override
**Error** t1.asm)93: Illegal indexing mode
**Error** t1.asm)123: Forward reference needs override
**Error** t1.asm)132: Forward reference needs override
**Error** t1.asm)141: Forward reference needs override
**Error** t1.asm)147: Illegal indexing mode
**Error** t1.asm)153: Forward reference needs override
*Warning* t1.asm)217: Module is pass dependent - compatibility pass was done
Error messages{    11
Warning messages{  1
Passes{            2

Выписка:
59:      xchg     cx,cs:[sp]
77:     putpixel
82:     xchg     cx,cs:[sp]
84:check_y:
87:     jz     end_circle
93:     xchg     cx,cs:[sp]
123:     putpixel
132:     putpixel
141:     putpixel
147:     xchg     cx,cs:[sp]
153:     jc     check_x_m_d
217:end start

Макро надо объявлять до его использования! (после переноса остались только ошибки с cs:[sp])
SP можно использовать только в сегменте стека!
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #16 : 19-07-2004 04:15 » 

Цитата

Во-первых, esp в реальном режиме не нужен - заменил на sp


я ведь синтаксис в VC проверял - он sp не пропустил (он-то в защищённом)...

 :arrow:
Цитата

SP можно использовать только в сегменте стека!


тогда
xchg cx,cs:[sp]

заменяем везде на

mov   fs,cx
pop   cx
push   fs

- везде должно прокатить

 :arrow:
Цитата

только через MOV с AX и PUSH/POP. Лучше использовать стек, чем такой изврат.


так со стеком ещё больший изврат выходит - и времени больше уйдёт, мне кажется (а кроме того - вершина стека у меня постоянно занята , причём этим числом я постоянно пользуюсь, и если я начну сохранять в стек то, что лежит в сегментных - такая каша выйдет...)



PS RXL, большое человеческое спасибо Улыбаюсь
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 19-07-2004 08:57 » 

Алексей1153, для того, чтобы работать с переменными на стеке, существует регистер BP (EBP) - он адресует в сегменте стека.
Типовое применение:
1) на входе в подпрограмму
PUSH BP
MOV BP,SP
SUB SP,nnn ; резервируем на стеке место под локальные переменные

2) применение
MOV AX,[BP-2] ; читаем первое слово в блоке переменных на стеке
MOV AX,[BP+4] ; читаем входной параметер на стеке
; на [BP+0] находится сохраненный BP
; на [BP+2] находится адрес возврата.

3) выход из подпрограммы
ADD SP,nnn ; уничтожаем локальные переменные
POP BP
RET

4) вызов подпрограммы
PUSH argL
PUSH argN
PUSH argM
CALL func
ADD SP,6

Порядок положения аргументов на стек, а так же, кто будет удалять их со стека, зависит от используемой договоренности.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 19-07-2004 12:27 » 

А, понял...
Я чего-то про BP как-то из вида упустил - действительно удобнее Улыбаюсь

перепишу, как время снова появится - щас груз...

но всё-таки - быстрее будет работать ведь не со стеком?
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 19-07-2004 12:57 » 

Алексей1153, сомнительно - это же спец регистры и обрабатываются они дольше, чем РОН. Потом, это просто не правильно.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
VaLer
Гость
« Ответ #20 : 29-01-2010 16:12 » new

Вот мой вариант этого кода  переведенного на ассемблер 100% работает.
Код:
;masm 6

p segment
assume cs:p
org 100h
s:
mov ax,0012h
int 10h
;
mov ax,r
mov y,ax
mov ax,r
neg ax
add ax,1
shl ax,1
mov d,ax
;
mov cx,xc
add cx,r
mov dx,yc
mov ax,cc
call pix
mov cx,xc
sub cx,r
mov dx,yc
mov ax,cc
call pix
mov cx,y
m22:
call pr1
call pr2
call pr3

mov cx,y
inc cx
loop m22



;
xor ax,ax
int 16h
int 20h



;

x dw 0
y dw 0
d dw 0
xc dw 250
yc dw 250
r  dw 180
cc  dw 4
rcx dw 0
pix proc
mov ah,12
int 10h
ret
pix endp
pr1 proc
mov cx,xc
add cx,x
mov dx,yc
add dx,y
mov ax,cc
call pix
mov cx,xc
add cx,x
mov dx,yc
sub dx,y
mov ax,cc
call pix

mov cx,xc
sub cx,x
mov dx,yc
add dx,y
mov ax,cc
call pix

mov cx,xc
sub cx,x
mov dx,yc
sub dx,y
mov ax,cc
call pix

ret
pr1 endp
pr2 proc
mov ax,d
add ax,y
cmp ax,0
jl po2
dec y
mov ax,y
shl ax,1
dec ax
sub d,ax
po2:
ret
pr2 endp
pr3 proc
mov ax,x
cmp ax,d
jl po3
inc x
mov ax,x
shl ax,1
inc ax
add d,ax
po3:
ret
pr3 endp

p ends
end s
« Последнее редактирование: 29-01-2010 17:44 от Finch » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines