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?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 28-05-2004 01:58 » |
|
поищи алгоритм Брезенхема
|
|
|
Записан
|
|
|
|
raYNor
Гость
|
|
« Ответ #2 : 28-05-2004 05:57 » |
|
Так это ОН и есть, только на С++, а его на Ams перевести надо ))
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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 воспользоваться
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 05-07-2004 09:15 » |
|
ими - долго имхо
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #6 : 05-07-2004 09:22 » |
|
ну - где вы, крутые ассемблеристы ?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 14-07-2004 19:24 » |
|
никто не слышит - тогда попробуем сами разобраться, если тебе ещё энто надо... я попробую переписать макрос в виде подпрограммы (как время появится - но думаю сегодня-завтра) на вход п/п - в регистрах должно подаваться: DX=r (16 бит) CX=yc (16 бит) BX=xc (16 бит) al=color (8 бит) raYNor, но проверить, как оно работает я не смогу - только синтаксис, ты сам запустишь - и скажешь, какие косяки встретились
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #8 : 14-07-2004 21:11 » |
|
Ээээ... А в двух словах - в чем суть? Алексей1153, поясни, пожалуйста, суть.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 15-07-2004 10:28 » |
|
RXL, В смысле - в чём суть? Я, кстати, почти дописал - скоро вывалю на обозрение
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #12 : 16-07-2004 08:46 » |
|
Алексей1153, не бери в голову - я просто невнимательно прочел предыдущее.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #13 : 16-07-2004 09:52 » |
|
RXL, кстати - может и проверишь заодно, работает или нет - а то Рэйнор похоже редко появляется
А вообще - где можно запускать ассемблерные проги - а то в VC вот это
__asm{}
даже в консольном приложении не желает генерировать прерывание 10H и вываливает БСОД...
RXL, посоветуй - что мне юзануть? (Какую среду имеется в виду) и ещё - можно ли дополнительные сегментные регистры (fs, gs, es) использовать в качестве регистров общего назначения, как я это сделал?(на невозможность использования их в командах ADD, SUB, CMP - я забил и заменил на эквиваленты)
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #14 : 18-07-2004 20:27 » |
|
Алексей1153, сервисы BIOS-а для реального режима и не должны быть доступны из win. Собирай каким-нибудь компилятором для DOS и там же запускай. Я раньше пользовался tasm.
Кстати, консольная программа != DOS - не путай мягкое с теплым.
Использовать сегментные регистры таким макаром нерационально - загружать их можно только через MOV с AX и PUSH/POP. Лучше использовать стек, чем такой изврат.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
RXL
|
|
« Ответ #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 можно использовать только в сегменте стека!
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
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
|
|
« Ответ #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
Порядок положения аргументов на стек, а так же, кто будет удалять их со стека, зависит от используемой договоренности.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 19-07-2004 12:27 » |
|
А, понял... Я чего-то про BP как-то из вида упустил - действительно удобнее перепишу, как время снова появится - щас груз... но всё-таки - быстрее будет работать ведь не со стеком?
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #19 : 19-07-2004 12:57 » |
|
Алексей1153, сомнительно - это же спец регистры и обрабатываются они дольше, чем РОН. Потом, это просто не правильно.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
VaLer
Гость
|
|
« Ответ #20 : 29-01-2010 16:12 » |
|
Вот мой вариант этого кода переведенного на ассемблер 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 »
|
Записан
|
|
|
|
|