nasm - What is the easiest way to draw a perfectly filled circle(disc) in assembly? -
i'd draw filled* circle(disc) in assembly in 320x200 mode 100 pixel radius. what's quickest/easiest way?
(*: mean disc filled when color e.g. constant white , has no black pixels in it.)
if quickest mean quickest write, here simple solution dos.
it doesn't use dos service exit one.
meant generate com file (raw output nasm fine, rename com extension).
bits 16 org 100h push 0a000h ;video memory graphics segment pop es mov ax, 0013h ;320x200@8bpp int 10h push 09h ;blue push 159 ;cx push 99 ;cy push 60 ;radius call drawfilledcircle ;wait key xor ah, ah int 16h ;restore text mode mov ax, 0003h int 10h ;return mov ax, 4c00h int 21h ;color ;cx ;cy ;r drawfilledcircle: push bp mov bp, sp sub sp, 02h mov cx, word [bp+04h] ;r mov ax, cx mul ax ;ax = r^2 mov word [bp-02h], ax ;[bp-02h] = r^2 mov ax, word [bp+06h] sub ax, cx ;i = cy-r mov bx, word [bp+08h] sub bx, cx ;j = cx-r shl cx, 1 mov dx, cx ;dx = copy of 2r .advance_v: push cx push bx mov cx, dx .advance_h: ;save values push bx push ax push dx ;compute (i-y) , (j-x) sub ax, word [bp+06h] sub bx, word [bp+08h] mul ax ;compute (i-y)^2 push ax mov ax, bx mul ax pop bx ;compute (j-x)^2 in ax, (i-y)^2 in bx add ax, bx ;(j-x)^2 + (i-y)^2 cmp ax, word [bp-02h] ;;(j-x)^2 + (i-y)^2 <= r^2 ;restore values before jump pop dx pop ax pop bx ja .continue ;skip pixel if (j-x)^2 + (i-y)^2 > r^2 ;write pixel push word [bp+0ah] push bx push ax call writepx .continue: ;advance j inc bx loop .advance_h ;advance inc ax pop bx ;restore j pop cx ;restore counter loop .advance_v add sp, 02h pop bp ret 08h ;color ;x ;y writepx: push bp mov bp, sp push ax push bx mov bx, word [bp+04h] mov ax, bx shl bx, 6 shl ax, 8 add bx, ax ;320 = 256 + 64 add bx, word [bp+06h] mov ax, word [bp+08h] ;todo: clip mov byte [es:bx], al pop bx pop ax pop bp ret 06h
it common technique writing plane figures given parameters, it's called rasterization.
given center c(x, y) , radius r of circle, algorithm follow
1. = y-r y+r 1.1 j = x-r x+r 1.1.1 if (i-y)^2 + (j-x)^2 <= r^2 1.1.1.1 drawpixel(j, i) 1.1.1 end if 1.1 end 1. end
this not optimized speed, @ all!
indeed create multiple routine sake of clarity. use stack lot.
note writepx
not clip coordinates!
if want speed things need more specific on requirement.
example radius fixed? if yes can use block of memory encode quarter of circle, this
0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 0 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
where each digits may bit or byte depending on speed vs memory constraints.
can copy block directly video memory or use template (kind of chroma key technique).
printing other 3 quarters of circle simple play counters.
if radius not fixed can boost code above by
- inlining functions call
- avoid use of stack as possible
- don't compute distance @ every cycle compute previous value using basic calculus.
- compute more 1 pixel @ time , combine writings.
Comments
Post a Comment