x86汇编语言中点画圆算法

4

我一直在尝试使用x86汇编语言使用中点圆算法绘制圆形,我已经接近成功了(我认为),我遵循了一个非常类似于这个问题的其他问题:

使用8086汇编语言绘制圆形

这对我遇到的其他问题有所帮助。然而,我没有得到一个完美的圆,我只有基本的形状,但它似乎是凹的。

[x86 circle]1

我尝试复制维基上的C代码示例,如下所示:

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

也许我完全错了,有人可以帮助我吗?
1个回答

6
以下代码似乎与C语言代码不相同:
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

你必须用MOV E,AX替换ADD E,AX

下一个错误是这个:

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

你必须在MUL DX之前插入MOV DX,2
我做了这两个修改,现在程序似乎能画一个圆。
顺便说一下:
将2倍化可以更有效地通过执行ADD AX,AX完成。

谢谢你的帮助。我刚刚尝试了MOV,但结果是一个类似正方形的形状。不过,add ax,ax非常好,谢谢你让我知道这一点。我会相应地更改代码。 - Josh
太好了,我明白了。我忘记了使用MUL时会影响DX。非常感谢你,伙计。我已经卡在那里一段时间了。 - Josh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接