hi everyone
I hope you can help me with converting some c code into assembly code, i have tried much now, and i still don't get it.
i'm new to programming ASM
this c code gets two number from the user to draw an ellipse

``````#include<stdio.h>
#include<graphics.h>
#include<math.h>
#include<dos.h>
void main()
{
long d1,d2;
long rx,ry,rxsq,rysq,tworxsq,tworysq,dx,dy;
int gd=DETECT,gm,x,y;
clrscr();
printf("enter x radius of the ellipse(20)");
scanf("%ld",&rx);
printf("enter y radius of the ellipse(40)");
scanf("%ld",&ry);
initgraph(&gd,&gm,"");

rxsq=rx*rx;
rysq=ry*ry;
tworxsq=2*rxsq;
tworysq=2*rysq;
x=0;
y=ry;
d1=rysq-rxsq*ry+(0.25*rxsq);
dx=tworysq*x;
dy=tworxsq*y;

do{
putpixel(200+x,200+y,15);
putpixel(200-x,200-y,15);
putpixel(200+x,200-y,15);
putpixel(200-x,200+y,15);
if(d1<0)
{
x=x+1;
y=y;
dx=dx+tworysq;
d1=d1+dx+rysq;
}
else
{
x=x+1;
y=y-1;
dx=dx+tworysq;
dy=dy-tworxsq;
d1=d1+dx-dy+rysq;
}
delay(200);
}
while(dx<dy); // in dige yani chi ?
d2=rysq*(x+0.5)*(x+0.5)+rxsq*(y-1)*(y-1)-rxsq*rysq;
do{
putpixel(200+x,200+y,15);
putpixel(200-x,200-y,15);
putpixel(200+x,200-y,15);
putpixel(200-x,200+y,15);
if(d2>0){
x=x;
y=y-1;
dy=dy-tworxsq;
d2=d2-dy+rxsq;
}
else

{
x=x+1;
y=y-1;
dy=dy-tworxsq;
dx=dx+tworysq;
d2=d2+dx-dy+rxsq;
}
}
while(y>0);
getch();
}``````

my asm code

``````putpix macro x,y
mov cx,x
mov dx,y
mov ah,0ch
mov al,9
int 10h
endm

init macro
mov al,13h
mov ah,0
int 10h
endm

.model small
.stack 128
.data
d1 dw 0
d2 dw 0
rx dw 0
ry dw 0
rxsq dw 0
rysq dw 0
tworxsq dw 0
tworysq dw 0
x dw 0
y dw 0
dxx dw 0
dyy dw 0
km1 dw 0
km2 dw 0
km3 dw 0
two dw 2
four dw 4

.code
main proc far
mov ax,@data
mov ds,ax
init
mov rx,30
mov ry,10

mov ax,rx
mul ax
mov rxsq,ax

mov ax,ry
mul ax
mov rysq,ax

mov ax,rxsq
mul two
mov tworxsq,ax

mov ax,rysq
mul two
mov tworysq,ax

mov x,0
mov bx,ry
mov y,bx
;-----
;d1=rysq-rxsq*ry+(0.25*rxsq)
;4d1=4rysq-4rxsq*ry+(rxsq);
;
mov ax,rysq
mul four
mov cx,ax
;
mov ax,rxsq
mul ry
mul four
mov bx,ax
;
sub cx,bx
;
mov ax,cx
div four
mov d1,ax
;-----
mov ax,rxsq
mul two
mov dxx,ax
mov ax,rysq
mul two
mov dyy,ax
;***loop1
lw1:cmp dxx,ax
jge endw1
;200+x
mov bx,x
;200+y
mov cx,y
putpix bx,cx
;200-x
mov bx,x
sub bx,200
neg bx
;200-y
mov cx,y
sub cx,200
neg cx
putpix bx,cx
;200+x
mov bx,x
;200-y
mov cx,y
sub cx,200
neg cx
putpix bx,cx
;200-x
mov bx,x
sub bx,200
neg bx
;200+y
mov cx,y
putpix bx,cx
cmp d1,0
jge else1
inc x
mov bx,tworysq
mov bx,rysq
jmp ifexit1
else1:
inc x
dec y
mov bx,tworysq
mov bx,tworxsq
sub dyy,bx
;d1=d1+dx-dy+rysq;
mov bx,dxx
sub bx,dyy
ifexit1:
mov cx,09999h
l12:
loop l12
jmp lw1
endw1:
;d2=rysq*(x+0.5)*(x+0.5)+rxsq*(y-1)*(y-1)-rxsq*rysq;
;4d2=rysq*(2x+1)*(2x+1)+4rxsq*(y-1)*(y-1)-4rxsq*rysq;
;4d2=km1+km2+km3
;km1
mov ax,x
mul two
mul ax
mul rysq
mov km1,ax
;km2
mov ax,y
dec ax
mul ax
mul rxsq
mul four
mov km2,ax
;km3
mov ax,rxsq
mul ax
mul four
mov km3,ax

mov ax,km1
div four
mov d2,ax

;***loop2
lw2:
cmp y,0
jle endw2
;200+x
mov bx,x
;200+y
mov cx,y
putpix bx,cx
;200-x
mov bx,x
sub bx,200
neg bx
;200-y
mov cx,y
sub cx,200
neg cx
putpix bx,cx
;200+x
mov bx,x
;200-y
mov cx,y
sub cx,200
neg cx
putpix bx,cx
;200-x
mov bx,x
sub bx,200
neg bx
;200+y
mov cx,y
putpix bx,cx

cmp d2,0
jle else2
dec y
mov bx,tworxsq
sub dyy,bx
;d2=d2-dy+rxsq;
mov bx,rxsq
sub d2,bx
jmp ifexit2
else2:
inc x
dec y
mov bx,tworxsq
sub y,bx
;d2=d2+dx-dy+rxsq;
mov bx,dxx
sub bx,dyy
sub d2,dx
ifexit2:
jmp lw2
endw2:
getch:mov ah,0
int 16h
mov ah,4ch
int 21h

main endp
end main``````

Looks like you're trying to do a deviation of the Bresenham DDA algorithm. Is this a class assignment or a personal or work project?

This is a big function. One method is to dump the assembly code generated by the compiler to get some ideas.

It also looks …

My question is, why are you still using fossil-ware?
I mean, how many Gigs of (processor speed, memory, hard disk) do you have?

A whole football field to play in, and you're still scribbling on the back of an old envelope.

Of course it doesn't work. You were suppose to analyze what I did, review your code, and single-step, etc. and make appropriate changes! One typically doesn't learn by being handed the answer. They typically need to be nudged into the correct direction so they can hopefully find the answer themselves!

Do you carry a cell phone?
Do you own a microwave oven?
Do you have a game console?
Do you have a television set?
Do you own an automobile?
etcetera
There you go!

## All 16 Replies

Looks like you're trying to do a deviation of the Bresenham DDA algorithm. Is this a class assignment or a personal or work project?

This is a big function. One method is to dump the assembly code generated by the compiler to get some ideas.

It also looks like you're not trying to write this for speed! You're stalling the processor almost all the time!

Interesting thing about a DDA algorithm, it uses a binary base in conjunction with increment/decrement. Rework your C code to be closer in appearance to the assembly!

How volatile is the putpixel() function? If X,Y are preserved then no need to move from memory to registers for each pixel. Just modify the displacement!

Years ago I wrote a graphics driver for drawing lines, circles, etc. With the Bresenham DDA algorithm but using self modifying code for fastest speed! If you're using an older pre Pentium computer you should be able to do the same. But one step at a time.

Okay, reformating your code while typing this have noticed a few things in the c code! Shouldn't y=y not be there? And It looks like your error correction is d1 ? (e) might be more familiar here!

Stop mixing floating-point with your integer code. Not

You're dealing with integers...

d1 = rysq - rxsq*ry + (0.25*rxsq);
should be more like
d1 = rysq - rxsq*ry + (rxsq >>2);

DO NOT...
mul 4
Do a shift

``shl ax,2``

much much faster!!!

``````div 4
asr ax,2``````

``````mov bx,x
sub bx,200
neg bx``````

...is WRONG!
- ( x - 200)
See the problem!
Instead use something like the following!

Store your 200 in a register, interlace the +/- x/y math then process.

``````mov	si,200		; Center X axis
mov	di,200		; Center Y axis

mov	bx,si		; +x +y
mov	cx,di
putpix bx,cx

mov	bx,si		; -x -y
mov	cx,di
sub	bx,x
sub	cx,y
putpix	bx,cx

mov	bx,si		; +x -y
mov	cx,di
sub	cx,y
putpix	bx,cx

mov	bx,si		; -x +y
mov	cx,di
sub	bx,x
putpix	bx,cx``````

My question is, why are you still using fossil-ware?
I mean, how many Gigs of (processor speed, memory, hard disk) do you have?

A whole football field to play in, and you're still scribbling on the back of an old envelope.

i fix some errors
i fix putmix macro
and i use shift operation instead of mul
and fixed some other things like x=x & y=y but still doesn't work

``````putpix macro x,y
mov ax,0A000h
mov es,ax        ;{es = \$A000}
mov ax,y
shl ax,6
mov bx,ax        ;{bx = y * 64}
shl ax,1
shl ax,1         ;{ax = y * 256}
add bx,ax        ;{bx = y * 320}
add bx,x         ;{bx = y * 320 + x}
mov es:[bx],al   ;{set point}
endm

init macro
mov al,13h
mov ah,0
int 10h
endm

.model small
.stack 128
.data
d1 dw 0
d2 dw 0
rx dw 0
ry dw 0
rxsq dw 0
rysq dw 0
tworxsq dw 0
tworysq dw 0
x dw 0
y dw 0
dxx dw 0
dyy dw 0
km1 dw 0
km2 dw 0
km3 dw 0
two dw 2
four dw 4

.code
main proc far
mov ax,@data
mov ds,ax
init
mov rx,30
mov ry,10

mov ax,rx
mul ax
mov rxsq,ax

mov ax,ry
mul ax
mov rysq,ax

;    	tworxsq=2*rxsq;
;   	tworysq=2*rysq;
mov ax,rxsq
shl ax,1
mov tworxsq,ax

mov ax,rysq
shl ax,1
mov tworysq,ax
;x=0;
;y=ry;
mov x,0
mov bx,ry
mov y,bx
;-----
;d1=rysq-rxsq*ry+(0.25*rxsq)
;d1=rysq-rxsq*ry+(rxsq>>4);
;
mov bx,rxsq
shr bx,2

mov ax,rxsq
mul ry
sub ax,bx
neg ax
mov d1,ax
;-----
;dx=tworysq*x;
mov ax,tworysq
mul x
mov dxx,ax
;dy=tworxsq*y;
mov ax,tworxsq
mul y
mov dyy,ax
;***loop1
lw1:cmp dxx,ax
jge endw1
mov	si,200		; Center X axis
mov	di,200		; Center Y axis
mov	bx,si		; +x +y
mov	cx,di
putpix bx,cx

mov	bx,si		; -x -y
mov	cx,di
sub	bx,x
sub	cx,y
putpix	bx,cx

mov	bx,si		; +x -y
mov	cx,di
sub	cx,y
putpix	bx,cx

mov	bx,si		; -x +y
mov	cx,di
sub	bx,x
putpix	bx,cx
cmp d1,0
jge else1
;y=y; ???
mov y,y
inc x
mov bx,tworysq
mov bx,rysq
jmp ifexit1
else1:
inc x
dec y
mov bx,tworysq
mov bx,tworxsq
sub dyy,bx
;d1=d1+dx-dy+rysq;
mov bx,dxx
sub bx,dyy
ifexit1:
mov cx,09999h
l12:
loop l12
jmp lw1
endw1:
;d2=rysq*(x+0.5)*(x+0.5)+rxsq*(y-1)*(y-1)-rxsq*rysq;
;d2=rysq*(x+0.5)*(x+0.5)+rxsq*(y-1)*(y-1)-rxsq*rysq;
;4d2=rysq*(2x+1)*(2x+1)+4rxsq*(y-1)*(y-1)-4rxsq*rysq;
;4d2=km1+km2+km3
;km1
mov ax,x
mul two
mul ax
mul rysq
mov km1,ax
;km2
mov ax,y
dec ax
mul ax
mul rxsq
mul four
mov km2,ax
;km3
mov ax,rxsq
mul ax
mul four
mov km3,ax
mov ax,km1
div four
mov d2,ax
;***loop2
lw2:
cmp y,0
jle endw2
mov	si,200		; Center X axis
mov	di,200		; Center Y axis
mov	bx,si		; +x +y
mov	cx,di
putpix bx,cx

mov	bx,si		; -x -y
mov	cx,di
sub	bx,x
sub	cx,y
putpix	bx,cx

mov	bx,si		; +x -y
mov	cx,di
sub	cx,y
putpix	bx,cx

mov	bx,si		; -x +y
mov	cx,di
sub	bx,x
putpix	bx,cx
cmp d2,0
jle else2
dec y
mov bx,tworxsq
sub dyy,bx
;d2=d2-dy+rxsq;
mov bx,dyy
sub bx,rxsq ;
neg bx
jmp ifexit2
else2:
inc x
dec y
mov bx,tworxsq
sub y,bx
;d2=d2+dx-dy+rxsq;
mov bx,dxx
sub bx,dyy
ifexit2:
jmp lw2
endw2:
getch:mov ah,0
int 16h
mov ah,4ch
int 21h
main endp
end main``````

Of course it doesn't work. You were suppose to analyze what I did, review your code, and single-step, etc. and make appropriate changes! One typically doesn't learn by being handed the answer. They typically need to be nudged into the correct direction so they can hopefully find the answer themselves!

Did you analyze what putpix does? If you had you would have seen that it uses bx for the offset calculation for the 256 color pixel write. You were using the BIOS call before, but now you are writing directly to memory.

What two registers are you passing in? AND what registers are pixel write using?

What processor are you using? This may be 16-bit 8086 code but are you running on a modern day Pentium type or an old 8086 through 80486? If a newer computer then using the old shifting for the multiplication is a mistake! On the older processors multiple shifts waas MUCH faster then a multiply. But on the newer processors it is quite the reverse of that!

I don't like heavy macros like you're using because of this kind of mistake. YOU DO NOT NEED TO KEEP RESETTING ES to the Video segment!!! You aren't using it anywhere else, so set it at your code initialization, and not in the write for each pixel!

Second, You aren't calling a function to plot each pixel so why are you using real X and real Y for each pixel write?

How many bytes in a stride? # of pixels for one pixel row? According to your own code 320. You use an anchor point each time.

so once you calculate your starting position (anchor point of elipse).
(+x) gets right edge -(x*2) gets left edge
(+y) gets bottom edge -(y*2) gets top edge.

Once you get this working post again, there are multitudes of optimizations you can do!

My question is, why are you still using fossil-ware?
I mean, how many Gigs of (processor speed, memory, hard disk) do you have?

A whole football field to play in, and you're still scribbling on the back of an old envelope.

this is my class assignment and i don't know why should i learn
i have no plan to develope an os or write the driver of the graphic card
i know with assembly we can crack applications through disAsm..
personaly i use c# and java to earn money
thank you Mr wildgoose for commenting

There is nothing wrong with starting with basic Assembly Language.
How are you coming with the rework?

finally i find a source that draws an ellipse!
http://img2.pict.com/5c/e0/0d/1348515/0/untitled.gif

``````.MODEL small
.DATA

;	Draws an ellipse using Floating point arithmetic

X_centre	EQU	[si]		;Centre of the ellipse
Y_centre	EQU	[si+2]		;
A		EQU	word ptr [si+4]	;Ellipse 1/2 width
B		EQU	word ptr [si+6]	;Ellipse 1/2 height
colour		EQU	byte ptr [si+8]	;Colour attribute

X_offset	dw	?		;X distance from ellipse centre
Y_offset	dw	?		;Y	"	"	"
temp		dw	?		;Scratch variable
;-------------------------------------------------------------------------------
.CODE
PUBLIC	ellipse
;-----------------------------------------------;
; Plot the ellipse defined by the equation	;
;						;
;	X**2/A**2 + Y**2/B**2 = 1		;
;						;
; Where, 2A is the ellipse width and B is the	;
;	ellipse height. A is > B		;
;						;
; Entry:	si = address of parameter block	;
;		es = Address of video memory	;
;-----------------------------------------------;

ellipse	proc	uses	ax bx cx dx

mov	al,colour

;	1st plot the pixels at the extremities of the ellipse

mov	cx,X_centre
mov	dx,Y_centre

call	plotadot		;Top pixel located above centre location

mov	dx,Y_centre
sub	dx,B			;Subtract the ellipse 1/2 height

call	plotadot		;Bottom pixel located below the centre

mov	dx,Y_centre

mov	cx,X_centre
sub	cx,A			;Subtract the ellipse 1/2 width

;	Calculate the Y coordinates corresponding to all positions X from centre

mov	cx,A			;Set loop index to ellipse 1/2 width
dec	cx			;Don't need to do the extreme positions
eloop:	push	cx			;Save the loop index

mov	temp,cx			;Get the X position
fild	temp
fimul	temp			;st=X**2
fild	A			;st=A,st(1)=X**2
fimul	A			;st=A**2,st(1)=X**2

fdiv				;st=X**2/A**2
fld1				;st=1, st(1)=X**2/A**2
fsubr				;st = 1 - X**2/A**2
fsqrt				;st = SQRT(1-X**2/A**2)
fimul	B			;st = B*SQRT(1-X**2/A**2)
fistp	y_offset

mov	dx,Y_offset
mov	X_offset,cx		;Take a copy of the X offset
mov	cx,X_centre

mov	dx,Y_centre

mov	dx,Y_centre
sub	dx,Y_offset

mov	cx,X_centre
sub	cx,X_offset

mov	dx,Y_centre

skip:	pop	cx			;Restore the loop index
loop	eloop

ret
ellipse	endp
end``````

http://img2.pict.com/5c/e0/0d/1348515/0/untitled.gif

USES is typically a MASM thing and its about register preservation. I don't use TASM but you can remove the uses line, and merely push bx yourself. AX, CX, DX are typically scratch but BX is preserved thus make sure it gets pushed, and then popped.

The version of TASM you are using is DOS based and thus 16-bit (REAL MODE), same as the code. I'm assuming you've added other code to put the computer into graphics mode and calls this function. Also that you've created a plotadot function? You can easily rework this function to fit your application!

``````void ellipse( short cx, short cy,     // center of ellipse
short width, short height,
char color,          // 2 bytes ?
);``````

Interesting. I don't see bx inuse, Most likely used by plotadot.

Too much heavy math for a DDA but kind of looks like a DDA. Will have to pick it apart to understand the math better!

This algorithm only deals with a fixed orientation of an ellipse but it uses the width for the stepping factor. Which means that if you set the width to half the height or thinner, you will see holes between pixels. Once you get this working you should modify the algorithm to use whichever is the longest, width or height as the stepping factor. It will replot some pixels but should be a consistent drawn line of pixels, and not a series of dotted pixels. And I'm guessing the reason the corners were painted separately is that the algorithm was not inclusive of its limits. [0,width) 0<=x<width not 0<=X<=width, thus they wouldn't have been plotted. But will have to analyze the math to know for sure!

So once you get this working, you should improve upon the algoithm to make your version your own. Since you did 'find' this version, you really should have posted credit to the original author, otherwise it really is plagiarism!

Yep! Heavy lifting in the math. And the math isn't even optimized!

Essentially ratio of the inverse of the (x / width) is applied to the y axis!

x / width ranges from (x, 0] just less then 1.0 and ranges down to 0.0 (1.0, 0.0]. (They start at ((x-1(/width) not x/width. Subtract that ratio from 1.0 and applies it to the Y axis scaling it (0.0, Y] from slightly more then 0 to Y (0.0, y].

It keeps pushing integer data onto the FPU stack and converting it to Extended-Double Precision Floating-Point, does the calculation in Floating-Point, and pops the answer off the stack while converting it to integer, which all takes time. Could pre-push then recycle most of what's on the FPU stack, but hardly worth it as it is an efficient algorithm. If the ratio of width < height gets large enough such as a ratio 1 : 2, gaps in the elipse start to appear.

Get your algorithm running but look into an ellipse based DDA algorithm. If you can't find one, look for a Bresenham DDA line. Essentially, Y/X the longer axis is used as the step, it uses a N^2 mechanism in integer with an error correction factor.

Then look into the Bresenham DDA circle. Pretty cool, draws a circle as octets, eight arcs at once!

If you modify the circle from octet to quad draw, and apply an adjusted error correction, you should get your DDA ellipse!

Mr wildgoose thank you for the answer
i wonder what is your job or what was your job ? :)

that code belong's to this book
Graphics Programming using Assembly by Ron Thomas

Just a lowly software/hardware developer!

i can't understand what is the need to develope low level software/hardware

Do you carry a cell phone?
Do you own a microwave oven?
Do you have a game console?
Do you have a television set?
Do you own an automobile?
etcetera
There you go!

commented: That's where it's at :) +36

you learned me good things thank you :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.