I was trying to draw a circle using 8086 assembler. I tried utilizing the midpoint circle algorithm which sadly resulted in drawing a tilted square for some reason (screenshots below). For reference, I rewrote the algorithm in python and managed to draw a circle without a problem.
I have a feeling that there is something wrong with my negative numbers manipulation but can't for the life of me figure it out because Turbo Debugger is telling me literally nothing. Could you guide me in the right direction? I enclose the code below:
; Program: graph.asm
.MODEL small
.STACK 256
.DATA
.CODE
jmp start
;=========================================
; Basic program to draw a circle
;=========================================
mode db 18 ;640 x 480
x_center dw 300
y_center dw 200
y_value dw 0
x_value dw 100
decision dw 1
colour db 1 ;1=blue
;=========================================
start:
mov ah,00 ;subfunction 0
mov al,mode ;select mode 18
int 10h ;call graphics interrupt
;==========================
mov bx, x_value
sub decision, bx
mov al,colour ;colour goes in al
mov ah,0ch
drawcircle:
mov al,colour ;colour goes in al
mov ah,0ch
mov cx, x_value ;Octonant 1
add cx, x_center ;( x_value + x_center, y_value + y_center)
mov dx, y_value
add dx, y_center
int 10h
mov cx, x_value ;Octonant 4
neg cx
add cx, x_center ;( -x_value + x_center, y_value + y_center)
int 10h
mov cx, y_value ;Octonant 2
add cx, x_center ;( y_value + x_center, x_value + y_center)
mov dx, x_value
add dx, y_center
int 10h
mov cx, y_value ;Octonant 3
neg cx
add cx, x_center ;( -y_value + x_center, x_value + y_center)
int 10h
mov cx, x_value ;Octonant 7
add cx, x_center ;( x_value + x_center, -y_value + y_center)
mov dx, y_value
neg dx
add dx, y_center
int 10h
mov cx, x_value ;Octonant 5
neg cx
add cx, x_center ;( -x_value + x_center, -y_value + y_center)
int 10h
mov cx, y_value ;Octonant 8
add cx, x_center ;( y_value + x_center, -x_value + y_center)
mov dx, x_value
neg dx
add dx, y_center
int 10h
mov cx, y_value ;Octonant 6
neg cx
add cx, x_center ;( -y_value + x_center, -x_value + y_center)
int 10h
inc y_value
condition1:
cmp decision,0
ja condition2
mov cx, y_value
mov ax, 2
imul cx
add cx, 1
inc cx
add decision, cx
mov bx, y_value
mov dx, x_value
cmp bx, dx
ja readkey
jmp drawcircle
condition2:
dec x_value
mov cx, y_value
sub cx, x_value
mov ax, 2
imul cx
inc cx
add decision, cx
mov bx, y_value
mov dx, x_value
cmp bx, dx
ja readkey
jmp drawcircle
;==========================
readkey:
mov ah,00
int 16h ;wait for keypress
;==========================
endd:
mov ah,00 ;again subfunc 0
mov al,03 ;text mode 3
int 10h ;call int
mov ah,04ch
mov al,00 ;end program normally
int 21h
END Start
Attempt in Assembler
Attempt in Python
Thanks in advance for help!
the square which is your assembly code drew comes from equation :
|x| + |y| = constant
This means your values are not getting squared
; a short program to check how
; set and get pixel color works
name "pixel"
org 100h
PUTC MACRO char
PUSH AX
MOV AL, char
MOV AH, 0Eh
INT 10h
POP AX
ENDM
;;;;;
; first and second number:
num1 dw ?
num2 dw ?
num3 dw ?
start:
lea dx, msg1
mov ah, 09h ; output string at ds:dx
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store first number:
mov num1, cx ;x coordinate
; new line:
putc 0Dh
putc 0Ah
lea dx, msg2
mov ah, 09h
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store second number:
mov num2, cx
putc 0Dh
putc 0Ah
lea dx, msg3
mov ah, 09h
int 21h
; get the multi-digit signed number
; from the keyboard, and store
; the result in cx register:
call scan_num
; store third number:
mov num3, cx
mov si,num1 ;x coordinate
mov di,num2 ;y coordinate
mov bp,num3 ;radius
mov ah, 0 ; set display mode function.
mov al, 13h ; mode 13h = 320x200 pixels, 256 colors.
int 10h ; set it!
mov sp,0 ;center point
;radius
;first point
mov bx,1 ;(1-r) condition
sub bx,bp ;same as above
jmp x1
x1:
cmp bx,0 ;condition compare
JL condt1
jmp condt2
condt1:
;increment x by 1
add bx,1;value for P(k+1)
mov ax,2
add sp,1
mul sp
add bx,ax
cmp sp,bp
jae done
mov cx, sp ;1(x,y)
add cx,si ; column
mov dx, bp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
; pause the screen for dos compatibility:
mov cx, bp ;2(y,x)
add cx,si ; column
mov dx, sp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;3 (-x,-y)
mov ax,-1
mul sp
add ax,si
mov cx, ax ; column
mov ax,-1
mul bp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;4 (-y,-x)
mov ax,-1
mul bp
add ax,si
mov cx, ax ; column
mov ax,-1
mul sp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
mov cx, sp ;5(x,-y)
add cx,si ; column
mov ax,-1
mul bp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
mov cx, bp ;6(y,-x)
add cx,si ; column
mov ax,-1
mul sp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;7 (-y,x)
mov ax,-1
mul bp
add ax,si
mov cx, ax ; column
mov dx, sp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;8(-x,y)
mov ax,-1
mul sp
add ax,si
mov cx, ax ; column
mov dx, bp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
jmp x1
condt2:
mov ax,2
sub bp,1
mul bp
sub bx,ax
mov ax,2
add sp,1
mul sp
add bx,ax
add bx,1
cmp sp,bp
jae done
mov cx, sp ;1(x,y)
add cx,si ; column
mov dx, bp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
; pause the screen for dos compatibility:
mov cx, bp ;2(y,x)
add cx,si ; column
mov dx, sp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;3 (-x,-y)
mov ax,-1
mul sp
add ax,si
mov cx, ax ; column
mov ax,-1
mul bp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;4 (-y,-x)
mov ax,-1
mul bp
add ax,si
mov cx, ax ; column
mov ax,-1
mul sp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
mov cx, sp ;5(x,-y)
add cx,si ; column
mov ax,-1
mul bp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
mov cx, bp ;6(y,-x)
add cx,si ; column
mov ax,-1
mul sp
add ax,di
mov dx,ax ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;7 (-y,x)
mov ax,-1
mul bp
add ax,si
mov cx, ax ; column
mov dx, sp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
;8(-x,y)
mov ax,-1
mul sp
add ax,si
mov cx, ax ; column
mov dx, bp
add dx,di ; row
mov al, 15 ; white
mov ah, 0ch ; put pixel
int 10h
xor al, al ; al = 0
mov cx, 10 ; column
mov dx, 20 ; row
mov ah, 0dh ; get pixel
int 10h
jmp x1
done:
int 20h
SCAN_NUM PROC NEAR
PUSH DX
PUSH AX
PUSH SI
MOV CX, 0
; reset flag:
MOV CS:make_minus, 0
next_digit:
; get char from keyboard
; into AL:
MOV AH, 00h
INT 16h
; and print it:
MOV AH, 0Eh
INT 10h
; check for MINUS:
CMP AL, '-'
JE set_minus
; check for ENTER key:
CMP AL, 0Dh ; carriage return?
JNE not_cr
JMP stop_input
not_cr:
CMP AL, 8 ; 'BACKSPACE' pressed?
JNE backspace_checked
MOV DX, 0 ; remove last digit by
MOV AX, CX ; division:
DIV CS:ten ; AX = DX:AX / 10 (DX-rem).
MOV CX, AX
PUTC ' ' ; clear position.
PUTC 8 ; backspace again.
JMP next_digit
backspace_checked:
; allow only digits:
CMP AL, '0'
JAE ok_AE_0
JMP remove_not_digit
ok_AE_0:
CMP AL, '9'
JBE ok_digit
remove_not_digit:
PUTC 8 ; backspace.
PUTC ' ' ; clear last entered not digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for next input.
ok_digit:
; multiply CX by 10 (first time the result is zero)
PUSH AX
MOV AX, CX
MUL CS:ten ; DX:AX = AX*10
MOV CX, AX
POP AX
; check if the number is too big
; (result should be 16 bits)
CMP DX, 0
JNE too_big
; convert from ASCII code:
SUB AL, 30h
; add AL to CX:
MOV AH, 0
MOV DX, CX ; backup, in case the result will be too big.
ADD CX, AX
JC too_big2 ; jump if the number is too big.
JMP next_digit
set_minus:
MOV CS:make_minus, 1
JMP next_digit
too_big2:
MOV CX, DX ; restore the backuped value before add.
MOV DX, 0 ; DX was zero before backup!
too_big:
MOV AX, CX
DIV CS:ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10
MOV CX, AX
PUTC 8 ; backspace.
PUTC ' ' ; clear last entered digit.
PUTC 8 ; backspace again.
JMP next_digit ; wait for Enter/Backspace.
stop_input:
; check flag:
CMP CS:make_minus, 0
JE not_minus
NEG CX
not_minus:
POP SI
POP AX
POP DX
RET
make_minus DB ? ; used as a flag.
SCAN_NUM ENDP
msg1 db "enter x coordinate: $"
msg2 db "enter y coordinate: $"
msg3 db "enter radius: $"
ten DW 10
ret
来源:https://stackoverflow.com/questions/35728180/drawing-a-circle-using-8086-assembly-language