Puesto que en ensamblador no se dispone de primitivas para trazar círculos, necesitaba investigar cómo trazarlos usando otras funciones. Desde bachillerato sabía que la ecuación del círculo viene a ser r^2=(sen(a)^2+cos(a)^2), (dado que la hipotenusa al cuadrado es igual que la suma de los cuadrados de los catetos). Si conocer el ángulo es innecesario, solo tenemos que comprobar si las coordenadas de un punto están dentro de la suma de los cuadrados de los catetos.
El primer programa es el prototipo QBASIC del programa CSEMBL que aparece a continuación.
DEFINT A-Z DECLARE FUNCTION insideyingyang% (x%, y%) 'Intento de dibujar el yin/yang mediante cálculo de ra¡z cuadrada. 'Programación: 9/10/95 'Cambio de colores y de sentido (arr-dch>arr-izq,etc): 10/10/95 'El yinyang de la bandera de Corea del Sur es: 'Azul (Arriba-izq),rojo (Abajo-dch), blanco (fondo). pxmin = 100 pxmax = 539 pymin = 100 pymax = 379 centrox = pxmin + (pxmax - pxmin) / 2 centroy = pymin + (pymax - pymin) / 2 radio1 = 100 'radio1 del s¡mbolo radio2 = radio1 / 2 'radio1 de los subc¡rculos radio3 = 10 'radio1 de los c¡rculos conc‚ntricos a ‚stos. subcentrox = centrox - radio1 / 2 subcentroy = centroy fondo = 15 ying = 1 yang = 4 SCREEN 12 FOR f = pymin TO pymax FOR g = pxmin TO pxmax IF (f < centroy - radio1) THEN PSET (g, f), fondo ELSE IF (f > centroy + radio1) THEN PSET (g, f), fondo ELSE IF (g < centrox - radio1) THEN PSET (g, f), fondo ELSE IF (g > centrox + radio1) THEN PSET (g, f), fondo ELSE PSET (g, f), insideyingyang(g, f) END IF END IF END IF END IF NEXT NEXT 'Devuelve el color para un punto dentro de un ying-yang. FUNCTION insideyingyang (x, y) SHARED ying, yang, fondo SHARED centrox, centroy, radio1 SHARED subcentrox, subcentroy, radio2, radio3 cx = x - centrox cy = y - centroy IF (cx * cx) + (cy * cy) > (radio1 * radio1) THEN insideyingyang = fondo: EXIT FUNCTION insideyingyang = 3 colory = 1 cx2 = ABS(subcentrox - x) cy2 = ABS(subcentroy - y) IF cx > 0 THEN cx2 = ABS(subcentrox + radio1 - x) 'Cambiando el mayor_o_igual de ahí abajo por menor_o_igual, 'cambia arriba_dch,abajo_izq por abajo_dch,arriba_izq y viceversa. 'El original necesita un "<=". IF cx <= 0 THEN colory = -colory IF (cx2 * cx2 + cy2 * cy2) > radio2 * radio2 THEN colory = SGN(cy) IF (cx2 * cx2 + cy2 * cy2) < radio3 * radio3 THEN colory = -colory IF colory = -1 THEN insideyingyang = ying ELSE insideyingyang = yang END FUNCTION
Esta es la implementación del programa anterior en CSEMBLER:
;Dibujar yinyang. Usa el método pitag¢rico. ;Idea y programa Basic: 9/10/95 ;Fin de la implementación CSM: 10/10/95 ;NO ES UN PROGRAMA ASSEMBLER, ES PARA CUTRESSEMBLER. ;pxmin=100 mov wo [%pxmin%], 64 ;pxmax=539 mov wo [%pxmax%], 21b ;pymin=100 mov wo [%pymin%], 64 ;pymax=379 mov wo [%pymax%], 17b mov ax,[%pxmax%] sub ax,[%pxmin%] shr ax,1 add ax,[%pxmin%] mov [%centrox%],ax mov ax,[%pymax%] sub ax,[%pymin%] shr ax,1 add ax,[%pymin%] mov [%centroy%],ax ;radio1=100 mov ax,64 mov [%radio1%],ax shr ax,1 mov [%radio2%],ax mov wo [%radio3%],a mov bx,[%centrox%] ;ax contiene radio1/2 sub bx,ax mov [%subcentrox%],bx mov bx,[%centroy%] mov [%subcentroy%],bx mov by [%fondo%],F mov by [%yin%],1 mov by [%yang%],4 ;Inicializar pantalla mov ax,12 int 10 mov ax,[%pymin%] mov [%f%],ax :for_f mov ax,[%pxmin%] mov [%g%],ax :for_g mov ax,[%centroy%] sub ax,[%radio1%] cmp [%f%],ax jl %dibujafondo% mov ax,[%centroy%] add ax,[%radio1%] cmp [%f%],ax jg %dibujafondo% mov ax,[%centrox%] sub ax,[%radio1%] cmp [%g%],ax jl %dibujafondo% mov ax,[%centrox%] add ax,[%radio1%] cmp [%g%],ax jg %dibujafondo% mov ax,[%g%] mov [%x%],ax mov ax,[%f%] mov [%y%],ax call %insideyinyang% :vuelta ;antes de llegar aquí hay que poner color en AL. mov cx,[%g%] mov dx,[%f%] mov ah,0C xor bx,bx int 10 ;next_g inc wo [%g%] mov ax,[%g%] cmp ax,[%pxmax%] jle %for_g% ;next_f inc wo [%f%] mov ax,[%f%] cmp ax,[%pymax%] jle %for_f% mov ax,0 int 16 mov ax,3 int 10 int 20 :dibujafondo mov al,[%fondo%] jmp %vuelta% :insideyinyang ;cx=x-centrox: mov ax,[%x%] sub ax,[%centrox%] mov [%cx%],ax mov ax,[%y%] ;cy=x-centroy: sub ax,[%centroy%] mov [%cy%],ax ;cy*cy+cx*cx... mul ax mov bx,ax mov ax,[%cx%] mul ax add bx,ax mov ax,[%radio1%] mul ax cmp bx,ax jle %inside_sigue% ;si cy*cy+cx*cx>radio1*radio1: mov al,[%fondo%] ret :inside_sigue mov wo [%colory%],1 ;cx2=abs(subcentrox-x): mov ax,[%subcentrox%] sub ax,[%x%] cmp ax,0 jge %inside_xge0% neg ax :inside_xge0 mov [%cx2%],ax ;cy2=abs(subcentroy-y): mov ax,[%subcentroy%] sub ax,[%y%] cmp ax,0 jge %inside_yge0% neg ax :inside_yge0 mov [%cy2%],ax ;IF cx > 0 THEN cx2 = ABS(subcentrox + radio1 - x) cmp wo [%cx%],0 jle %inside_cxle0% mov ax,[%subcentrox%] add ax,[%radio1%] sub ax,[%x%] mov [%cx2%],ax cmp ax,0 jge %inside_cxle0% neg wo [%cx2%] :inside_cxle0 ;Cambiando el signo de lo siguiente se cambia ;la dirección del ying y el yang (izq-arr,dch-aba>izq-aba,dch-arr). ;IF cx <= 0 THEN colory = -colory cmp wo [%cx%],0 jg %inside_cxl0% neg wo [%colory%] :inside_cxl0 ;IF (cx2 * cx2 + cy2 * cy2) > radio2 * radio2 THEN colory = SGN(cy) mov ax,[%cx2%] mul ax mov bx,ax mov ax,[%cy2%] mul ax add bx,ax mov ax,[%radio2%] mul ax mov cx,ax cmp bx,cx jle %IFCIRC2% cmp wo [%cy%],0 jge %sgnisge0% mov wo [%colory%],ffff jmp %IFCIRC2% :sgnisge0 mov wo [%colory%],1 :IFCIRC2 ;IF (cx2 * cx2 + cy2 * cy2) < radio3 * radio3 THEN colory = -colory ;bx ha de ser cx2^2+cy2^2 mov ax,[%radio3%] mul ax mov cx,ax cmp bx,cx jge %finif2% neg wo [%colory%] :finif2 mov al,[%yin%] cmp wo [%colory%],ffff jz %inside_ret% mov al,[%yang%] :inside_ret ret ;db "________PXMIN=" :pxmin dw 0 ;db "________PXMAX=" :pxmax dw 0 ;db "________PYMIN=" :pymin dw 0 ;db "________PYMAX=" :pymax dw 0 ;db "______CENTROX=" :centrox dw 0 ;db "______CENTROY=" :centroy dw 0 ;db "_______RADIO1=" :radio1 dw 0 ;db "_______RADIO2=" :radio2 dw 0 ;db "_______RADIO3=" :radio3 dw 0 ;db "___SUBCENTROX=" :subcentrox dw 0 ;db "___SUBCENTROY=" :subcentroy dw 0 ;db "_________FONDO=" :fondo db 1 ;db "___________YIN=" :yin db 0 ;db "__________YANG=" :yang db F ;db "____________F=" :f dw 0 ;db "____________G=" :g dw 0 ;db "____________X=" :x dw 0 ;db "____________Y=" :y dw 0 ;db "___________CX=" :cx dw 0 ;db "___________CY=" :cy dw 0 ;db "__________CX2=" :cx2 dw 0 ;db "___________CY=" :cy2 dw 0 ;db "_______COLORY=" :colory dw 0 db "YINYANG, programado en CSEMBL. 10-10-1995"
Este listado, por último, genera el mismo patrón en modo texto:
;Dibujar yinyang. Usa el método pitagórico. ;Idea y programa Basic: 9/10/95 ;Fin de la implementación CSM_GRAFICOS: 10/10/95 ;IMPLEMENTACIÓN TEXTO: ;NO ES UN PROGRAMA ASSEMBLER, ES PARA CUTRESSEMBLER. mov wo [%pxmin%], 8 mov wo [%pxmax%], 48 mov wo [%pymin%], 4 mov wo [%pymax%], 2a mov ax,[%pxmax%] sub ax,[%pxmin%] shr ax,1 add ax,[%pxmin%] mov [%centrox%],ax mov ax,[%pymax%] sub ax,[%pymin%] shr ax,1 add ax,[%pymin%] mov [%centroy%],ax mov ax,12 mov [%radio1%],ax shr ax,1 mov [%radio2%],ax mov wo [%radio3%],2 mov bx,[%centrox%] ;ax contiene radio1/2 sub bx,ax mov [%subcentrox%],bx mov bx,[%centroy%] mov [%subcentroy%],bx mov by [%fondo%],F mov by [%yin%],1 mov by [%yang%],4 ;Inicializar pantalla mov ax,3 int 10 mov ax,[%pymin%] mov [%f%],ax :for_f mov ax,[%pxmin%] mov [%g%],ax :for_g mov ax,[%centroy%] sub ax,[%radio1%] cmp [%f%],ax jl %dibujafondo% mov ax,[%centroy%] add ax,[%radio1%] cmp [%f%],ax jg %dibujafondo% mov ax,[%centrox%] sub ax,[%radio1%] cmp [%g%],ax jl %dibujafondo% mov ax,[%centrox%] add ax,[%radio1%] cmp [%g%],ax jg %dibujafondo% mov ax,[%g%] mov [%x%],ax mov ax,[%f%] mov [%y%],ax call %insideyinyang% :vuelta ;antes de llegar aqu¡ hay que poner color en AL. call %puntotexto% ;next_g inc wo [%g%] mov ax,[%g%] cmp ax,[%pxmax%] jle %for_g% ;next_f inc wo [%f%] mov ax,[%f%] cmp ax,[%pymax%] jle %for_f% mov ax,0 int 16 ;mov ax,3 ;int 10 int 20 :dibujafondo mov al,[%fondo%] jmp %vuelta% :insideyinyang ;cx=x-centrox: mov ax,[%x%] sub ax,[%centrox%] mov [%cx%],ax mov ax,[%y%] ;cy=x-centroy: sub ax,[%centroy%] mov [%cy%],ax ;cy*cy+cx*cx... mul ax mov bx,ax mov ax,[%cx%] mul ax add bx,ax mov ax,[%radio1%] mul ax cmp bx,ax jle %inside_sigue% ;si cy*cy+cx*cx>radio1*radio1: mov al,[%fondo%] ret :inside_sigue mov wo [%colory%],1 ;cx2=abs(subcentrox-x): mov ax,[%subcentrox%] sub ax,[%x%] cmp ax,0 jge %inside_xge0% neg ax :inside_xge0 mov [%cx2%],ax ;cy2=abs(subcentroy-y): mov ax,[%subcentroy%] sub ax,[%y%] cmp ax,0 jge %inside_yge0% neg ax :inside_yge0 mov [%cy2%],ax ;IF cx > 0 THEN cx2 = ABS(subcentrox + radio1 - x) cmp wo [%cx%],0 jle %inside_cxle0% mov ax,[%subcentrox%] add ax,[%radio1%] sub ax,[%x%] mov [%cx2%],ax cmp ax,0 jge %inside_cxle0% neg wo [%cx2%] :inside_cxle0 ;Cambiando el signo de lo siguiente se cambia ;la direccion del ying y el yang (izq-arr,dch-aba>izq-aba,dch-arr). ;IF cx <= 0 THEN colory = -colory cmp wo [%cx%],0 jg %inside_cxl0% neg wo [%colory%] :inside_cxl0 ;IF (cx2 * cx2 + cy2 * cy2) > radio2 * radio2 THEN colory = SGN(cy) mov ax,[%cx2%] mul ax mov bx,ax mov ax,[%cy2%] mul ax add bx,ax mov ax,[%radio2%] mul ax mov cx,ax cmp bx,cx jle %IFCIRC2% cmp wo [%cy%],0 jge %sgnisge0% mov wo [%colory%],ffff jmp %IFCIRC2% :sgnisge0 mov wo [%colory%],1 :IFCIRC2 ;IF (cx2 * cx2 + cy2 * cy2) < radio3 * radio3 THEN colory = -colory ;bx ha de ser cx2^2+cy2^2 mov ax,[%radio3%] mul ax mov cx,ax cmp bx,cx jge %finif2% neg wo [%colory%] :finif2 mov al,[%yin%] cmp wo [%colory%],ffff jz %inside_ret% mov al,[%yang%] :inside_ret ret :puntotexto push es push ax mov bx,b800 mov es,bx mov ax,[%f%] push ax ;nos va a interesar luego saber si f (y) es par o impar shr ax,1 mov cx,50 mul cx add ax,[%g%] shl ax,1 mov bx,ax pop cx and cl,1 shl cl,1 shl cl,1 ;borra el atributo que se va a cambiar. ;de otra manera es complicado cambiar solo un atributo. mov ah,F0 rol ah,cl mov al,0 es: and [bx],ax pop ax ;ahora suma el carácter y la parte nueva del atributo a la parte ;del atributo que no ha cambiado. rol al,cl :dfh=1/2cuadro sup. mov ah,df xchg al,ah es: or [bx],ax pop es ret ;db "________PXMIN=" :pxmin dw 0 ;db "________PXMAX=" :pxmax dw 0 ;db "________PYMIN=" :pymin dw 0 ;db "________PYMAX=" :pymax dw 0 ;db "______CENTROX=" :centrox dw 0 ;db "______CENTROY=" :centroy dw 0 ;db "_______RADIO1=" :radio1 dw 0 ;db "_______RADIO2=" :radio2 dw 0 ;db "_______RADIO3=" :radio3 dw 0 ;db "___SUBCENTROX=" :subcentrox dw 0 ;db "___SUBCENTROY=" :subcentroy dw 0 ;db "_________FONDO=" :fondo db 1 ;db "___________YIN=" :yin db 0 ;db "__________YANG=" :yang db F ;db "____________F=" :f dw 0 ;db "____________G=" :g dw 0 ;db "____________X=" :x dw 0 ;db "____________Y=" :y dw 0 ;db "___________CX=" :cx dw 0 ;db "___________CY=" :cy dw 0 ;db "__________CX2=" :cx2 dw 0 ;db "___________CY=" :cy2 dw 0 ;db "_______COLORY=" :colory dw 0 db "YINYANG, programado en CSEMBL. 10-10-1995"