我试图实现一个椭圆绘制算法与8086大会在VGA(320x200)模式,但形状是不正确的绘制更大的半径。
正如你所看到的,形状是凹的或直的,而不是椭圆形的。我得到可接受的结果时,轴有小的长度,即(10,15),但任何更多,然后,它停止类似椭圆。我使用FPU来计算所有值。
.387
SCREEN_WIDTH = 320
SCREEN_HEIGHT = 200
HALF_SCREEN_WIDTH = SCREEN_WIDTH / 2
HALF_SCREEN_HEIGHT = SCREEN_HEIGHT / 2
stack1 segment stack
dw 300 dup(?)
stack_top dw ? ;stack_top pointer
stack1 ends
code1 segment
start1:
mov ax,seg stack1
mov ss,ax ; initialize stack
mov sp, offset stack_top
mov al, 13h
mov ah, 0 ; change mode
int 10h ; enter graphics mode
mov byte ptr cs:[color], 10
start_draw:
call clear_screen
call ellipse
wait_key:
in al, 60h ;take keyboard input
cmp al, 1 ;if ESC end
je end_program
jmp wait_key
;-------------------------------------------------------------
;-------------------------------------------------------------
x_radius dw 40 ;width of the ellipse
y_radius dw 50 ;height of the ellipse
x_derivative dw ? ;derivates calculated from ellipse equation
y_derivative dw ?
x_squared dw ? ;squared values for convenience
y_squared dw ?
decision_param dw ?
four dw 4 ;int values used in some of the expressions
two dw 2 ;storing them so I can load them to the FPU
;----------------------
calc_x_derivative:
;x_derivative = 2 * y_squared * x
;RPN: 2 y_squared x * *
finit
fild word ptr cs:[y_squared]
fimul word ptr cs:[two] ;instead of multiplying by 2
fimul word ptr cs:[x]
fistp word ptr cs:[x_derivative]
ret
calc_y_derivative:
;y_derivative = 2 * x_squared * y
;RPN: 2 x_squared y * *
finit
fild word ptr cs:[x_squared]
fimul word ptr cs:[two]
fimul word ptr cs:[y]
fistp word ptr cs:[y_derivative]
ret
ellipse:
;initialize x as 0 and y as y_radius
mov word ptr cs:[x], 0
mov ax, word ptr cs:[y_radius]
mov word ptr cs:[y], ax
x_radius_squared:
finit
fild word ptr cs:[y_radius]
fimul word ptr cs:[y_radius]
fistp word ptr cs:[y_squared]
y_radius_squared:
finit
fild word ptr cs:[x_radius]
fimul word ptr cs:[x_radius]
fistp word ptr cs:[x_squared]
derivatives:
call calc_x_derivative
call calc_y_derivative
calc_decision_param_1:
;d1 = y_squared - (x_squared * ry) + (1/4 * x_squared)
;RPN: y_squared x_squared ry * - x_squared 4 / +
finit
fild word ptr cs:[y_squared]
fild word ptr cs:[x_squared]
fild word ptr cs:[y_radius]
fmul
fsub
fild word ptr cs:[x_squared]
fidiv word ptr cs:[four]
fadd
fistp word ptr cs:[decision_param]
region_1_loop:
call color_all_symmetries
inc word ptr cs:[x]
call calc_x_derivative
cmp word ptr cs:[decision_param], 0 ;compare decision_param to 0
jge region_1_alternative_next ;if its lower decrement y and calculate alternative decision_param
region_1_next:
;decision_param = decision_param + x_derivative + (y_squared)
;RPN: decision_param x_derivative + y_squared +
finit
fild word ptr cs:[decision_param]
fild word ptr cs:[x_derivative]
fadd
fild word ptr cs:[y_squared]
fadd
fistp word ptr cs:[decision_param]
jmp region_1_loop_end
region_1_alternative_next:
;decision_param = decision_param + x_derivative - y_derivative + (y_squared)
;RPN: decision_param x_derivative + y_derivative - y_squared +
dec word ptr cs:[y]
call calc_y_derivative
finit
fild word ptr cs:[decision_param]
fild word ptr cs:[x_derivative]
fadd
fild word ptr cs:[y_derivative]
fsub
fild word ptr cs:[y_squared]
fadd
fistp word ptr cs:[decision_param]
region_1_loop_end:
mov ax, word ptr cs:[x_derivative]
cmp ax, word ptr cs:[y_derivative] ;check if x_derivative < y_derivative
jge calc_decision_param_2 ;if it is we are done with region 1
jmp region_1_loop
calc_decision_param_2:
;decision_param = (y_squared * (x + 1/2) * (x + 1/2)) + (x_squared * (y - 1) * (y - 1)) - (x_squared * y_squared)
;RPN: y_squared x 1 2 / + * x 1 2 / + * x_squared y 1 - * y 1 - * + x_squared y_squared * -
fild word ptr cs:[y_squared]
fild word ptr cs:[x]
fld1
fidiv word ptr cs:[two]
fadd
fmul
fild word ptr cs:[x]
fld1
fidiv word ptr cs:[two]
fadd
fmul
fild word ptr cs:[x_squared]
fild word ptr cs:[y]
fld1
fsub
fmul
fild word ptr cs:[y]
fld1
fsub
fmul
fadd
fild word ptr cs:[x_squared]
fimul word ptr cs:[y_squared]
fsub
fistp word ptr cs:[decision_param]
region_2_loop:
call color_all_symmetries
dec word ptr cs:[y]
call calc_y_derivative
cmp word ptr cs:[decision_param], 0 ;check if decision_param < 0
jge alternative_region_2_next
region_2_next:
;decision_param = decision_param + x_squared - y_derivative
;RPN: decision_param x_squared + y_derivative -
finit
fild word ptr cs:[decision_param]
fild word ptr cs:[x_squared]
fadd
fild word ptr cs:[y_derivative]
fsub
fistp word ptr cs:[decision_param]
jmp region_2_loop_end
alternative_region_2_next:
inc word ptr cs:[x]
call calc_x_derivative
region_2_alternative_decision_param:
;decision_param = decision_param + x_derivative - y_derivative + (x_squared)
;RPN: decision_param x_derivative + y_derivative - x_squared +
finit
fild word ptr cs:[decision_param]
fild word ptr cs:[x_derivative]
fadd
fild word ptr cs:[y_derivative]
fsub
fild word ptr cs:[x_squared]
fadd
fistp word ptr cs:[decision_param]
region_2_loop_end:
;y_derivative = y_derivative - (2 * x_squared)
;RPN: y_derivative 2 x_squared * -
finit
fild word ptr cs:[y_derivative]
fild word ptr cs:[two]
fild word ptr cs:[x_squared]
fmul
fsub
fistp word ptr cs:[y_derivative]
cmp word ptr cs:[y], 0 ; check if y <= 0
jg region_2_loop
end_ellipse:
ret
;-------------------------------------------------------------
;--------------------- color_pixel -------------------------
x dw ?
y dw ?
temp_y dw ?
temp_x dw ?
color db ?
;---------------------
color_all_symmetries:
; Coloring points (xc + x, yc + y), (xc - x, yc + y), (xc + x, yc - y), (xc - x, yc - y)
push ax
;Point (xc + x, yc - y)
mov ax, HALF_SCREEN_HEIGHT
sub ax, word ptr cs:[y]
mov word ptr cs:[temp_y], ax
mov ax, word ptr cs:[x]
add ax, HALF_SCREEN_WIDTH
mov word ptr cs:[temp_x], ax
call color_pixel
;Point (xc - x, yc - y)
mov ax, HALF_SCREEN_HEIGHT
sub ax, word ptr cs:[y]
mov word ptr cs:[temp_y], ax
mov ax, HALF_SCREEN_WIDTH
sub ax, word ptr cs:[x]
mov word ptr cs:[temp_x], ax
call color_pixel
;Point (xc + x, yc + y)
mov ax, HALF_SCREEN_HEIGHT
add ax, word ptr cs:[y]
mov word ptr cs:[temp_y], ax
mov ax, word ptr cs:[x]
add ax, HALF_SCREEN_WIDTH
mov word ptr cs:[temp_x], ax
call color_pixel
;Point (xc - x, yc - y)
mov ax, HALF_SCREEN_HEIGHT
add ax, word ptr cs:[y]
mov word ptr cs:[temp_y], ax
mov ax, HALF_SCREEN_WIDTH
sub ax, word ptr cs:[x]
mov word ptr cs:[temp_x], ax
call color_pixel
pop ax
ret
color_pixel:
push ax
push es
;position needs to be in a format y*320 + x
mov ax, 0a000h
mov es, ax
mov ax, word ptr cs:[temp_y] ;selecting a row
mov bx, SCREEN_WIDTH
mul bx ;ax multiplying y by 320 to get proper position
mov bx, word ptr cs:[temp_x] ;selecting a column
add bx, ax ;adding to the pixel position
mov al, byte ptr cs:[color] ;adding a color
mov byte ptr es:[bx], al
pop es
pop ax
ret
;-------------------------------------------------------------
end_program:
mov al, 3h
mov ah, 0
int 10h
mov ax, 4c00h
int 21h
clear_screen:
mov ax, 0a000h
mov es, ax
xor ax, ax
mov di, ax
mov cx, SCREEN_WIDTH * SCREEN_HEIGHT
mov al, 0
cld
rep stosb ;while cx != 0, mov byte ptr es:[di], al; di++; cx--
ret
code1 ends
end start1
我尝试了许多不同版本的相同算法都没有成功。我想这可能是我的变量(特别是导数和决策参数)溢出的问题,我试图通过使用double words
而不是words
来声明变量来修复它,但我在算法中比较它们时遇到了麻烦,当我编译程序时,它仍然没有按预期工作。
1条答案
按热度按时间wgx48brx1#
我想这可能是我的变量(特别是导数和决策参数)溢出的问题
你对变量溢出的怀疑是正确的。
例如,考虑 calc_decision_param_1 的计算:
其结果为(50 * 50)-(40 * 40 * 50)+(40 * 40 / 4)= -77100
这不再适合有符号字,因此
fistp word ptr cs:[decision_param]
指令只能在字大小的目标中存储默认的“IntegerIndefinite value 8000 h”。你应该做的是将一些变量定义为dword整数:x_derivative、y_derivative 和 decision_param。所有其他变量将适合其当前的单词大小。
但我在算法中比较时遇到了麻烦
检查
decision_param < 0
是否应该简单地查看dword变量的符号位的代码:以及检查
x_derivative < y_derivative
是否可以使用ficomp
来比较这些有符号双字整数的代码。基于(冲突的)注解(;check if x_derivative < y_derivative
和;if it is we are done with region 1
),它看起来像:看起来
x_radius_squared:
和y_radius_squared:
做的事情与它们的名字告诉我们的完全相反!