4

I have been trying to draw a circle using x86 assembler using the midpoint circle algorithm, I have gotten it pretty close (I think), I have followed another question very similar to this one:

Drawing a circle using 8086 Assembly Language

and this has helped with other problems I have encounter. However, I am not quite getting a circle, I have the basic shape but it seems to be concave.

[x86 circle]1

I have tried to copy the C code example on wiki as seen below:

C:

void drawcircle(int x0, int y0, int radius)
{
    int x = radius;
    int y = 0;
    int err = 0;

    while (x >= y)
    {
        putpixel(x0 + x, y0 + y);
        putpixel(x0 + y, y0 + x);
        putpixel(x0 - y, y0 + x);
        putpixel(x0 - x, y0 + y);
        putpixel(x0 - x, y0 - y);
        putpixel(x0 - y, y0 - x);
        putpixel(x0 + y, y0 - x);
        putpixel(x0 + x, y0 - y);

        y += 1;
        err += 1 + 2*y;
        if (2*(err-x) + 1 > 0)
        {
            x -= 1;
            err += 1 - 2*x;
        }
    }
}

ASM:

DSEG    SEGMENT PARA PUBLIC 'DATA'         
    Y       DW  0
    X       DW  0
    Y_C     DW  0
    X_C     DW  0
    E       DW  0
DSEG    ENDS

CSEG    SEGMENT PARA PUBLIC 'CODE'
    ASSUME CS:CSEG, DS:DSEG, SS:SSEG

MAIN    PROC    FAR

    PUSH    DS                         
    MOV     AX,0                       
    PUSH    AX                         
    MOV     AX,DSEG                    
    MOV     DS,AX                      


                            ;The program begins here.
    MOV     AH,00H          ;Video: 640x480
    MOV     AL,18
    INT     10H

    MOV     DX,240
    MOV     CX,320
    MOV     SI,100
    MOV     AL,3
    CALL    CIRCLE


    MOV     AH,00H
    INT     16H

    MOV     AH,00H
    MOV     AL,2            ;Reset the screen to normal
    INT     10H


    RET                                ;The program ends here.

MAIN    ENDP
;--------------------------------------------------------------
;       CIRCLE
;       Description:    Draws a circle
;       Input param:    DX = CENTER (X)
;                       CX = CENTER (Y)
;                       AL = Colour
;                       SI = radius
;       Reg Effected:   None
;--------------------------------------------------------------
CIRCLE      PROC
    PUSH    DX
    PUSH    CX

    MOV     X,SI
    MOV     X_C,DX
    MOV     Y_C,CX

CIR:
    MOV     DX,X
    CMP     DX,Y
    JNGE    FIN_CIR

    CALL    DRAWCIRCLE

    INC     Y

    PUSH    AX

    MOV     AX,2
    MUL     Y
    INC     AX
    ADD     AX,E
    ADD     E,AX

    SUB     AX,X
    MOV     DX,2
    MUL     DX
    INC     AX
    CMP     AX,0
    JG      E_CHECK

    POP     AX
    JMP     CIR

E_CHECK:
    DEC     X
    MOV     AX,X
    MUL     DX
    MOV     DX,1
    SUB     DX,AX
    ADD     E,DX

    POP     AX
    JMP     CIR

FIN_CIR:
    POP     CX
    POP     DX
    RET
CIRCLE      ENDP

;-------------------------------------------------------------
;      DRAWCIRCLE
;       Description:    Draws a circle, using midpoint circle algorithm 
;       Input params:   DX = Row (X)
;                       CX = Column (Y)
;                       AL = Colour
;                       SI = radius
;       Reg Effected:   None
;--------------------------------------------------------------

DRAWCIRCLE      PROC
    PUSH    DX
    PUSH    CX

    MOV     DX,X_C
    MOV     CX,Y_C
    ADD     DX,X
    ADD     CX,Y
    CALL    WRITEPIXEL

    MOV     DX,X_C
    MOV     CX,Y_C
    ADD     DX,Y
    ADD     CX,X
    CALL    WRITEPIXEL

    MOV     DX,X_C
    SUB     DX,Y
    CALL    WRITEPIXEL

    MOV     DX,X_C
    MOV     CX,Y_C
    SUB     DX,X
    ADD     CX,Y
    CALL    WRITEPIXEL

    MOV     CX,Y_C
    SUB     CX,Y
    CALL    WRITEPIXEL

    MOV     DX,X_C
    MOV     CX,Y_C
    SUB     DX,Y
    SUB     CX,X
    CALL    WRITEPIXEL

    MOV     DX,X_C
    ADD     DX,Y
    CALL    WRITEPIXEL

    MOV     DX,X_C
    MOV     CX,Y_C
    ADD     DX,X
    SUB     CX,Y
    CALL    WRITEPIXEL

    POP     CX
    POP     DX
    RET
DRAWCIRCLE      ENDP

Maybe I have gone completely wrong, can anyone help me?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Josh
  • 41
  • 3

1 Answers1

6

The following lines seem not to be equal to the C code:

MOV     AX,2
MUL     Y 
INC     AX
ADD     AX,E  <- After this AX = err+2*y+1
ADD     E,AX  <- Now you do: err += err+2*y+1

You must replace the ADD E,AX by MOV E,AX.

The next error is this one:

    ...
    MOV     DX,2
    MUL     DX    <- This instruction "destroys" DX!
    ...
E_CHECK:
    DEC     X
    MOV     AX,X
    MUL     DX    <- DX is no longer 2 here

You must insert a MOV DX,2 before the MUL DX.

I made the two modifications and now the program seems to draw a circle.

By the way:

Multiplying by 2 can be done more efficiently by doing ADD AX,AX.

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • Thanks for helping I just tried MOV instead unfortunately the outcome is that of a square like shape, the add ax,ax however is great thanks for letting me know that I will change the code accordingly. – Josh Nov 19 '16 at 17:43
  • Perfect I see, I forgot that when using MUL it effects DX. Thank you so much man, been stuck on that for a while. – Josh Nov 19 '16 at 17:58