	;; 
	;; Author: Bill Slough
	;;
	;; Invoking subroutines with stack frames
	;;
	;; Draws rectangles of varying sizes
	;; 

	.ORIG x3000

	;; Main program...............................................................

START	LD	R6,TOP  		; initialize stack pointer
	AND	R5,R5,#0		; frame pointer = null

	LEA	R0,P    		; i = 0
	LEA	R1,Q
LOOP0	LEA	R2,P_END		; while (corner points remain)
	NOT	R2,R2    		;
	ADD	R2,R2,#1 		;
	ADD	R2,R0,R2 		; 
	BRz	ELOOP0

	LDR	R3,R0,#0 		;  
	ADD	R6,R6,#-1		;
	STR	R3,R6,#0		;   push P[i].row

	LDR	R3,R0,#1 		;
	ADD	R6,R6,#-1		;
	STR	R3,R6,#0		;   push P[i].column

	LDR	R3,R1,#0 		;
	ADD	R6,R6,#-1		;
	STR	R3,R6,#0		;   push Q[i].row

	LDR	R3,R1,#1  		;
	ADD	R6,R6,#-1 		;
	STR	R3,R6,#0		;   push Q[i].column

	LD	R3,RED  		;
	ADD	R6,R6,#-1		;
	STR	R3,R6,#0		;   push RED

	JSR	DRAW_RECT 		;   draw_rect(P[i].row, P[i].column,
	ADD	R6,R6,#5		;             Q[i].row, Q[i].column, RED)
	
	ADD	R0,R0,#2		;
	ADD	R1,R1,#2		;   i = i + 1
	BR	LOOP0                   ; end while
ELOOP0	
STOP   	HALT

TOP	.FILL	xC000                   ; where does the stack begin?
RED	.FILL	x7C00                   ; desired color for rectangles

F_ROW	.FILL	6       		; where to start the flood fill...
F_COL	.FILL	11                      ; currently (6,11)

	;; P stores the coordinates of the upper-left corner points
P	.FILL	5		; (5, 10)
	.FILL	10		;
	.FILL	20		; (20, 40)
	.FILL	40		;
	.FILL	90		; (90, 90)
	.FILL	90		;
	.FILL	10		; (10, 60)
	.FILL	60		;
	.FILL	0		; (0, 0)
	.FILL	0
P_END	.FILL	-1

	;; Q stores the coordinates of the lower-right corner points
Q	.FILL	30		; (30, 50)
	.FILL	50		;
	.FILL	100		; (100, 100)
	.FILL	100		;
	.FILL	95		; (95, 120)
	.FILL	120		;
	.FILL	70		; (70, 80)
	.FILL	80		;
	.FILL	123		; (123, 127)
	.FILL	127
Q_END	.FILL	-1

	;; Subroutine ................................................................
DRAW_RECT
	;; Draw a rectangle, given the coordinates of opposing corner points
	;;
	;; Parameters:
	;; 	ULrow   (upper left corner)
	;; 	ULcol
	;; 	LRrow   (lower right corner)
	;; 	LRcol
	;; 	color   (desired color)
	;; 
	;; Frame offsets:
	;; 	-4  saved R4
	;; 	-3  saved R3
	;; 	-2  saved R2
	;; 	-1  saved R1
	;; 	 0  saved R0
	;; 	+1  previous frame pointer
	;; 	+2  return address
	;; 	+3  color
	;; 	+4  LRcolumn
	;; 	+5  LRrow
	;; 	+6  ULcolumn
	;; 	+7  ULrow

	;; PROLOG
	ADD	R6,R6,#-1 		;
	STR	R7,R6,#0  		; push return address

	ADD	R6,R6,#-1		;	
	STR	R5,R6,#0  		; push previous frame pointer

	ADD	R5,R6,#-1		; establish frame pointer for this frame

	STR	R0,R6,#-1		; save registers being used in this routine
	STR	R1,R6,#-2		;
	STR	R2,R6,#-3		;
	STR	R3,R6,#-4
	STR	R4,R6,#-5
	ADD	R6,R6,#-5		; adjust stack pointer to the top of the frame

	;; BODY
	;; Draw horizontal line segments 
	LDR	R3,R5,#7 		; R3 = ULrow
	LDR	R4,R5,#5		; R4 = LRrow
 
	LDR	R0,R5,#6 		; c = ULcolumn
LOOP1	LDR	R1,R5,#4		; while (c <= LRcolumn)
	NOT	R2,R0                   ;
	ADD	R2,R2,#1		;
	ADD	R1,R1,R2		;
	BRn	ELOOP1                  ;
BODY1
	ADD	R6,R6,#-1 		;   
	STR	R3,R6,#0		;    push ULrow

	ADD	R6,R6,#-1 		;
	STR	R0,R6,#0		;    push c

	LDR	R1,R5,#3 		;
	ADD	R6,R6,#-1		;
	STR	R1,R6,#0		;    push color 

	JSR	DRAW_PIXEL 		;    draw_pixel(ULrow, c, color)
	ADD	R6,R6,#3		;    remove parameters

	ADD	R6,R6,#-1 		;    
	STR	R4,R6,#0		;    push LRrow

	ADD	R6,R6,#-1 		;
	STR	R0,R6,#0		;    push c 

	ADD	R6,R6,#-1 		;
	STR	R1,R6,#0		;    push color

	JSR	DRAW_PIXEL 		;    draw_pixel(LRrow, c, color)
	ADD	R6,R6,#3		;

	ADD	R0,R0,#1 		;    c = c + 1
	BR	LOOP1   		; end while
ELOOP1
	;; Draw vertical line segments 
	LDR	R3,R5,#6 		; R3 = ULcolumn
	LDR	R4,R5,#4		; R4 = LRcolumn
 
	LDR	R0,R5,#7 		; r = ULrow
LOOP2	LDR	R1,R5,#5		; while (r <= LRrow)
	NOT	R2,R0                   ;
	ADD	R2,R2,#1		;
	ADD	R1,R1,R2		;
	BRn	ELOOP2                  ;
BODY2
	ADD	R6,R6,#-1 		;   
	STR	R0,R6,#0		;    push r

	ADD	R6,R6,#-1 		;
	STR	R3,R6,#0		;    push ULcolumn

	LDR	R1,R5,#3 		;
	ADD	R6,R6,#-1		;
	STR	R1,R6,#0		;    push color

	JSR	DRAW_PIXEL 		;    draw_pixel(r, ULcolumn, color)
	ADD	R6,R6,#3		;    remove parameters

	ADD	R6,R6,#-1 		;    
	STR	R0,R6,#0		;    push r

	ADD	R6,R6,#-1 		;
	STR	R4,R6,#0		;    push LRcolumn

	ADD	R6,R6,#-1 		;
	STR	R1,R6,#0		;    push color

	JSR	DRAW_PIXEL 		;    draw_pixel(r, LRcolumn, color)
	ADD	R6,R6,#3		;

	ADD	R0,R0,#1 		;    r = r + 1
	BR	LOOP2   		; end while
ELOOP2	
	;; EPILOG
	LDR	R4,R5,#-4
	LDR	R3,R5,#-3
	LDR	R2,R5,#-2 		; restore R2
	LDR	R1,R5,#-1 		; restore R1
	LDR	R0,R5,#0  		; restore R0
	LDR	R7,R5,#2 		; get the return address
	LDR	R5,R5,#1  		; restore the previous frame pointer
	ADD	R6,R6,#7 		; adjust the stack pointer, deallocate frame
	RET

	;; Subroutine ................................................................
DRAW_PIXEL
	;; Draw a pixel on the graphics display unit at a specified location
	;;
	;; Parameters:
	;; 	row     -- a value between 0 and 123
	;; 	column  -- a value between 0 and 127
	;; 	color   -- a 15-bit RGB value
	;;
	;; Frame offsets:
	;; 	-4  saved R4
	;; 	-3  saved R3
	;; 	-2  saved R2
	;; 	-1  saved R1
	;; 	 0  saved R0
	;; 	+1  previous frame pointer
	;; 	+2  return address
	;; 	+3  color
	;; 	+4  column
	;; 	+5  row

	;; PROLOG
	ADD	R6,R6,#-1 		;
	STR	R7,R6,#0  		; push return address

	ADD	R6,R6,#-1		;	
	STR	R5,R6,#0  		; push previous frame pointer

	ADD	R5,R6,#-1		; establish frame pointer for this frame

	STR	R0,R6,#-1		; save registers being used in this routine
	STR	R1,R6,#-2		;
	STR	R2,R6,#-3		;
	STR	R3,R6,#-4 		;
	STR	R4,R6,#-5 		;
	ADD	R6,R6,#-5		; adjust stack pointer to the top of the frame

	;; BODY
	LDR	R0,R5,#5 		; R0 = row
	LDR	R1,R5,#4 		; R1 = column
	LDR	R2,R5,#3 		; R2 = color
	
	ADD	R3,R0,#0	  	;
	LD	R4,PIX_PER_ROW 	;
	MUL	R3,R3,R4		;
	ADD	R3,R3,R1		; R3 = PIX_PER_ROW * row + column

	LD	R4,VIDEO_ADDR
	ADD	R4,R4,R3 		; R4 = address of desired pixel

	STR	R2,R4,#0 		; Video[row,column] = color

	;; EPILOG
	LDR	R4,R5,#-4 		; restore R4
	LDR	R3,R5,#-3 		; restore R3
	LDR	R2,R5,#-2 		; restore R2
	LDR	R1,R5,#-1 		; restore R1
	LDR	R0,R5,#0  		; restore R0
	LDR	R7,R5,#2 		; get the return address
	LDR	R5,R5,#1  		; restore the previous frame pointer
	ADD	R6,R6,#7 		; adjust the stack pointer, deallocate frame
	RET

	;; Constants used by DRAW_PIXEL
VIDEO_ADDR	.FILL	xC000	; base address of the video display
PIX_PER_ROW	.FILL	128	; number of pixels per row
	
	.END