High-Level Assembly

Contributed by Chris Rathman

Shape Interface (Shape.hhf)

type Shape:class
   var x:int32;
   var y:int32;
   procedure create; @returns("esi"); @external;
   procedure getX; @returns("eax"); @external;
   procedure getY; @returns("eax"); @external;
   method setX(newx:int32); @external;
   method setY(newy:int32); @external;
   method moveTo(newx:int32; newy:int32); @external;
   method rMoveTo(deltax:int32; deltay:int32); @external;
   method draw; @abstract;
endclass;

Shape Implementation (Shape.hla)

unit Shapes;
#include("stdlib.hhf");
#includeonce("Shape.hhf");

static vmt(Shape);

// constructor
procedure Shape.create;
begin create;
   if (esi = 0) then
      mov(malloc(@size(Shape)), esi);
   endif;
   mov(&Shape._VMT_, this._pVMT_);
   this.setX(0);
   this.setY(0);
   push(esi);
end create;

// accessors for x & y
procedure Shape.getX;
begin getX;
   mov(this.x, eax);
   push(eax);
end getX;

procedure Shape.getY;
begin getY;
   mov(this.y, eax);
   push(eax);
end getY;

method Shape.setX(newx:int32);
begin setX;
   mov(newx, this.x);
end setX;

method Shape.setY(newy:int32);
begin setY;
   mov(newy, this.y);
end setY;

// move the shape position
method Shape.moveTo(newx:int32; newy:int32);
begin moveTo;
   this.setX(newx);
   this.setY(newy);
end moveTo;

method Shape.rMoveTo(deltax:int32; deltay:int32);
begin rMoveTo;
   push(eax);
   push(ebx);
   mov(this.x, eax);
   add(deltax, eax);
   mov(this.y, ebx);
   add(deltay, ebx);
   this.moveTo(eax, ebx);
   pop(ebx);
   pop(eax);
end rMoveTo;

end Shapes;

Rectangle Interface (Rectangle.hhf)

type Rectangle:class inherits(Shape)
   var width:int32;
   var height:int32;
   override procedure create; @external;
   procedure getWidth; @returns("eax"); @external;
   procedure getHeight; @returns("eax"); @external;
   method setWidth(newwidth:int32); @external;
   method setHeight(newheight:int32); @external;
   override method draw; @external;
endclass;

procedure makeRectangle(newx:int32; newy:int32; newwidth:int32; newheight:int32); @returns("esi"); @external;

Rectangle Implementation (Rectangle.hla)

unit Rectangles;
#include("stdlib.hhf");
#includeonce("Shape.hhf");
#includeonce("Rectangle.hhf");

static vmt(Rectangle);

// constructor
procedure Rectangle.create;
begin create;
   if (esi = 0) then
      mov(malloc(@size(Rectangle)), esi);
   endif;
   call Shape.create;
   mov(&Rectangle._VMT_, this._pVMT_);
   this.setWidth(0);
   this.setHeight(0);
   push(esi);
end create;

// accessors for width & height
procedure Rectangle.getWidth;
begin getWidth;
   mov(this.width, eax);
   push(eax);
end getWidth;

procedure Rectangle.getHeight;
begin getHeight;
   mov(this.height, eax);
   push(eax);
end getHeight;

method Rectangle.setWidth(newwidth:int32);
begin setWidth;
   mov(newwidth, this.width);
end setWidth;

method Rectangle.setHeight(newheight:int32);
begin setHeight;
   mov(newheight, this.height);
end setHeight;

// draw the rectangle
method Rectangle.draw;
begin draw;
   push(eax);
   mov(this.getX(), eax);
   stdout.put("Drawing a Rectangle at:(", (type int32 eax), ",");
   mov(this.getY(), eax);
   stdout.put((type int32 eax), ") ");
   mov(this.getWidth(), eax);
   stdout.put("width ", (type int32 eax), ", ");
   mov(this.getHeight(), eax);
   stdout.put("height ", (type int32 eax), nl);
   pop(eax);
end draw;

// make a Rectangle object
procedure makeRectangle(newx:int32; newy:int32; newwidth:int32; newheight:int32);
begin makeRectangle;
   Rectangle.create();
   (type Rectangle [esi]).moveTo(newx, newy);
   (type Rectangle [esi]).setWidth(newwidth);
   (type Rectangle [esi]).setHeight(newheight);
   push(esi);
end makeRectangle;

end Rectangles;

Circle Interface (Circle.hhf)

type Circle:class inherits(Shape)
   var radius:int32;
   override procedure create; @external;
   procedure getRadius; @returns("eax"); @external;
   method setRadius(newradius:int32); @external;
   override method draw; @external;
endclass;

procedure makeCircle(newx:int32; newy:int32; newradius:int32); @returns("esi"); @external;

Circle Implementation (Circle.hla)

unit Circles;
#include("stdlib.hhf");
#includeonce("Shape.hhf");
#includeonce("Circle.hhf");

static vmt(Circle);

// constructor
procedure Circle.create;
begin create;
   if (esi = 0) then
      mov(malloc(@size(Circle)), esi);
   endif;
   call Shape.create;
   mov(&Circle._VMT_, this._pVMT_);
   this.setRadius(0);
   push(esi);
end create;

// accessors for radius
procedure Circle.getRadius;
begin getRadius;
   mov(this.radius, eax);
   push(eax);
end getRadius;

method Circle.setRadius(newradius:int32);
begin setRadius;
   mov(newradius, this.radius);
end setRadius;

// draw the circle
method Circle.draw;
begin draw;
   push(eax);
   mov(this.getX(), eax);
   stdout.put("Drawing a Circle at:(", (type int32 eax), ",");
   mov(this.getY(), eax);
   stdout.put((type int32 eax), ") ");
   mov(this.getRadius(), eax);
   stdout.put("radius ", (type int32 eax), nl);
   pop(eax);
end draw;

// make a circle object
procedure makeCircle(newx:int32; newy:int32; newradius:int32);
begin makeCircle;
   Circle.create();
   (type Circle [esi]).moveTo(newx, newy);
   (type Circle [esi]).setRadius(newradius);
   push(esi);
end makeCircle;

end Circles;

Try shapes module (Polymporph.hla)

program Polymorph;

#includeonce("stdlib.hhf");

#includeonce("Shape.hhf");
#includeonce("Circle.hhf");
#includeonce("Rectangle.hhf");

type pShape: pointer to Shape;

static scribble: pShape[2];
static rect: pointer to Rectangle;

begin Polymorph;

   // set up some shape instances
   mov(makeRectangle(10, 20, 5, 6), scribble[0*4]);
   mov(makeCircle(15, 25, 8), scribble[1*4]);

   // iterate through some shapes and handle polymorphically
   for (mov(0, ebx); ebx < 2; inc(ebx)) do
      scribble.draw[ebx*4]();
      scribble.rMoveTo[ebx*4](100, 100);
      scribble.draw[ebx*4]();
   endfor;

   // access a rectangle specific function
   mov(makeRectangle(0, 0, 15, 15), rect);
   rect.setWidth(30);
   rect.draw();

end Polymorph;

Output

Drawing a Rectangle at:(10,20) width 5, height 6
Drawing a Rectangle at:(110,120) width 5, height 6
Drawing a Circle at:(15,25) radius 8
Drawing a Circle at:(115,125) radius 8
Drawing a Rectangle at:(0,0) width 30, height 15

Chris Rathman / Chris.Rathman@tx.rr.com