23.5.09

Código Assembler del algoritmo de Bresenham


 


Revisando (muy) antiguos proyectos encontré este trocito de código en ensamblador (o assembler) que hice (o copié, ya no recuerdo) alrededor de 1992, para el juego Defender, que en realidad es un remake de Command Comander, sólo que no sabíamos que se llamaba así... :P

El código en ensamblador es para procesadores 80286, las famosas PC AT 286. Y pinta el pixel en el modo gráfico #13 de las VGA (320x200 pixeles y 256 colores).
Está preparado para funcionar dentro del código fuente del Turbo Pascal, por eso está declarado como una función, con parámetros de coordenada X/Y de inicio y  fin, el color a pintar y otro parámetro que no sé que es :D
No tengo idea si esto le será de utilidad a alguien, espero que sí.
Procedure LineaASM( x1_,y1_,x2_,y2_:Integer; Color_,Poner_:Byte); assembler;
var
x1,
y1,
x2,
y2,
delp,
delr,
delrx,
delry,
deldx,
deldy,
delre,
delde   :Word;

asm

{ tomar parametros }

          mov   ax,x1_
          mov   x1,ax         { X1 }

          mov   ax,y1_
          mov   y1,ax         { Y1 }

          mov   ax,x2_
          mov   x2,ax         { X2 }

          mov   ax,y2_
          mov   y2,ax         { Y2 }

{ inc de perder todo }
          mov   si,1
          mov   di,1

{ calcular /x2-/y1/ }
         mov    dx,y2_
         sub    dx,y1_
         jge    @almay
         neg    di
         neg    dx
@almay:
         mov    deldy,di

{ calcular /x2-x1/ }
         mov    cx,x2
         sub    cx,x1
         jge    @almax
         neg    si
         neg    cx
@almax:
         mov    deldx,si

{ clasificar /y2-y1/ y /x2-x1/  }
         cmp    cx,dx
         jge    @mover
         mov    si,0
         xchg   cx,dx
         jmp    @alma

@mover:
         mov    di,0

{ almacenar delr,delp,delrx y delry }
@alma:
         mov    delr,cx
         mov    delp,dx
         mov    delrx,si
         mov    delry,di

{ obtener valores iniciales para x e y }
         mov    si,x1
         mov    di,y1

{ calcular valor inicial e incrementos para la funcion de error }
         mov    ax,delp
         sal    ax,1
         mov    delre,ax

         sub    ax,cx
         mov    bx,ax

         sub    ax,cx
         mov    delde,ax

{ ajustar contador }
         inc    cx
{ ------------------------------ }
{ estructura del bucle principal }
{ ------------------------------ }

@bucle:
{ dibujar punto en (x,y) }

         push bx
         push ax
         push cx
         push es


         mov  BX,SI           { si=x }
         mov  AX,DI           { di=y }

{ PQLL:         AX = coordenada y (0-199)
;               BX = coordenada x (399)
;
; Devuelve:     BX = desplazamiento de byte en el buffer
;               ES = segmento del buffer de v¡deo}

               xchg    ah,al           { AX := 256 * y     }
               add     bx,ax           { BX := 256 * y + x }
               shr     ax,1
               shr     ax,1            { AX := 64 * y      }
               add     bx,ax           { BX := 320 * y + x }

               mov     ax, $A000
               mov     es,ax           { ES:BX := direcci¢n de byte del pixel }


         { pone el punto }
               mov     al,Color_      { Color }
               mov     es:[bx],al

         pop   es
         pop   cx
         pop   ax
         pop   bx

         cmp   bx,0
         jge   @diagonal

{ caso linea recta }
@recta:
         add   si,delrx
         add   di,delry
         add   bx,delre
         loop  @bucle
         jmp   @fin

{ caso linea diagonal }
@diagonal:
         add   si,deldx
         add   di,deldy
         add   bx,delde
         loop  @bucle

{ restaurar registros afectados }
@fin:
end;
Relacionado: El algoritmo de Bresenham
Un interesante aporte: Proyectos robóticos
En la web Proyectos robóticos se pueden encontrar programas con ejemplos del Algoritmo de Bresenham para 2D, 3D... hasta 6D. Este algoritmo no sólo sirve para hacer líneas.
En mi caso lo uso para coordinar los movimientos de un simulador de Brazo Robot de 5 grados de libertad (la mano no se cuenta como grado de libertad). Todo el brazo se mueve a la vez para la realización de cualquier trayectorias. En mis simuladores el brazo robot llega a dibujar. Para esta tarea uso los ficheros de extensión ".PLT" (HPGL).
Los ejemplos están escrito en FreeBasic y en este caso compatibles con QBasic. Las variables están declaras en tipo, así que es bien fácil traducirlo a cualquier lenguaje de programación.

3 comentarios:

  1. y cual es la utilidad de esta mierda?

    ResponderEliminar
  2. Pues por ejemplo: Admirar la belleza de un juego escrito en puro ensamblador.

    ResponderEliminar
  3. ley_de_plomo: me gusta esa utilidad :)

    ResponderEliminar