-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathcircle.asm
210 lines (179 loc) · 4.88 KB
/
circle.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
;===================================================================================================
; Circle
;
; Written By: Oded Cnaan ([email protected])
; Site: http://odedc.net
; Licence: GPLv3 (see LICENSE file)
; Package: GrLib
;
; Description:
; Draws a circle
;===================================================================================================
LOCALS @@
;----------------------------------------------------------
; Draws a circle
; Credit: https://stackoverflow.com/questions/37564442/assembly-draw-a-circle
;
; push Xcenter
; push Ycenter
; push Radius
; call GR_DrawCircle
;----------------------------------------------------------
PROC GR_DrawCircle
store_sp_bp
sub sp, 4
pusha
push es
; now the stack is
; bp-4 => y
; bp-2=> x
; bp+0 => old base pointer
; bp+2 => return address
; bp+4 => param4 (Radius)
; bp+6 => param3 (Ycenter)
; bp+8 => param2 (Xcenter)
; saved registers
IsDblBuffering @@NotDbl
GetDblBufferSeg es
@@NotDbl:
mov cx, 0 ; x = 0
mov bx, [word bp+4] ; radius
mov di, [word bp+6] ; Ycenter
mov dx, [word bp+8] ; Xcenter
mov si, bx
@@circle0:
call @@8pixels ;Set 8 pixels
sub bx,cx ;D=D-X
inc cx ;X+1
sub bx,cx ;D=D-(2x+1)
jg @@circle1 ;>> no step for Y
add bx,si ;D=D+Y
dec si ;Y-1
add bx,si ;D=D+(2Y-1)
@@circle1:
cmp si,cx ;Check X>Y
jae @@circle0 ;>> Need more pixels
jmp @@fin
@@8pixels:
call @@4pixels ;4 pixels
@@4pixels:
xchg cx,si ;Swap x and y
call @@2pixels ;2 pixels
@@2pixels:
neg si
mov al, [gr_pen_color] ; color
push di
add di,si
imul di,VGA_SCREEN_WIDTH
add di,dx
push di
add di, cx
mov [BYTE es:di],al
pop di
sub di,cx
stosb
pop di
ret
@@fin:
pop es
popa
restore_sp_bp
ret 6
ENDP GR_DrawCircle
;----------------------------------------------------------
; Fills a circle
; Credit: https://stackoverflow.com/questions/31563382/what-is-the-easiest-way-to-draw-a-perfectly-filled-circledisc-in-assembly
;
; push Xcenter
; push Ycenter
; push Radius
; call GR_FillCircle
;----------------------------------------------------------
PROC GR_FillCircle
store_sp_bp
sub sp, 6h
; now the stack is
; bp-6 => y
; bp-4 => x
; bp-2 => tmp
; bp+0 => old base pointer
; bp+2 => return address
; bp+4 => param4 (radius)
; bp+6 => param3 (ycenter)
; bp+8 => param2 (xcenter)
; saved registers
mov cx,[WORD bp+04h] ;Radius
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) and (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 is in bx now
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
mov [word bp-4], bx
mov [word bp-6], ax
gr_set_pixel [bp-4], [bp-6], [gr_pen_color]
@@continue:
;Advance j
inc bx
loop @@advance_h
;Advance i
inc ax
pop bx ;Restore j
pop cx ;Restore counter
loop @@advance_v
restore_sp_bp
ret 06h
ENDP GR_FillCircle
;////////////////////////////////////////////////////////////////////////////
; FUNCTION LIKE MACROS
;////////////////////////////////////////////////////////////////////////////
;----------------------------------------------------------------------
; Fills a circle
;
; grm_FillCircle (Xcenter, Ycenter, Radius)
;----------------------------------------------------------------------
MACRO grm_FillCircle Xcenter, Ycenter, Radius
push Xcenter
push Ycenter
push Radius
call GR_FillCircle
ENDM
;----------------------------------------------------------------------
; Draw a circle
;
; grm_DrawCircle (Xcenter, Ycenter, Radius)
;----------------------------------------------------------------------
MACRO grm_DrawCircle Xcenter, Ycenter, Radius
push Xcenter
push Ycenter
push Radius
call GR_DrawCircle
ENDM