【发布时间】:2018-11-11 09:40:49
【问题描述】:
我正在尝试使用 MARS 在位图中绘制一个圆圈。我已经从维基百科转换了 c 公式,但是我得到的结果是错误的。我认为我的转换存在错误,但我终其一生都无法弄清楚它是什么。
#Procedure: drawCircle:
#Draw a circle in the center of the input pixel (This will be implemented using the
#midpoint circle algorithm from https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
#a0 = x0
#a1 = y0
#a2 = color
#a3 = radius
drawCircle:
#MAKE ROOM ON STACK
addi $sp, $sp, -20 #Make room on stack for 1 words
sw $ra, 0($sp) #Store $ra on element 0 of stack
sw $a0, 4($sp) #Store $a0 on element 1 of stack
sw $a1, 8($sp) #Store $a1 on element 2 of stack
sw $a2, 12($sp) #Store $a1 on element 3 of stack
sw $a3, 16($sp) #Store $a1 on element 4 of stack
#VARIABLES
move $t0, $a0 #x0
move $t1, $a1 #y0
move $t2, $a3 #radius
addi $t3, $t2, -1 #x
li $t4, 0 #y
li $t5, 1 #dx
li $t6, 1 #dy
li $t7, 0 #Err
#CALCULATE ERR (dx - (radius << 1))
sll $t8, $t2, 1 #Bitshift radius left 1
subu $t7, $t5, $t8 #Subtract dx - shifted radius
#While(x >= y)
circleLoop:
blt $t3, $t4, skipCircleLoop #If x < y, skip circleLoop
#Draw Dot (x0 + x, y0 + y)
addu $a0, $t0, $t3
addu $a1, $t1, $t4
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 + y, y0 + x)
addu $a0, $t0, $t4
addu $a1, $t1, $t3
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 - y, y0 + x)
subu $a0, $t0, $t4
addu $a1, $t1, $t3
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 - x, y0 + y)
subu $a0, $t0, $t3
addu $a1, $t1, $t4
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 - x, y0 - y)
subu $a0, $t0, $t3
subu $a1, $t1, $t4
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 - y, y0 - x)
subu $a0, $t0, $t4
subu $a1, $t1, $t3
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 + y, y0 - x)
addu $a0, $t0, $t4
subu $a1, $t1, $t3
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#Draw Dot (x0 + x, y0 - y)
addu $a0, $t0, $t3
subu $a1, $t1, $t4
lw $a2, 12($sp)
jal drawDot #Jump to drawDot
#If (err <= 0)
bgtz $t7, doElse
addi $t4, $t4, 1 #y++
addu $t7, $t7, $t6 #err += dy
addi $t6, $t6, 2 #dy += 2
j circleContinue #Skip else stmt
#Else If (err > 0)
doElse:
addi $t3, $t3, -1 #x--
addi $t5, $t5, 2 #dx += 2
sll $t8, $t2, 1 #Bitshift radius left 1
subu $t9, $t5, $t8 #Subtract dx - shifted radius
addu $t7, $t7, $t9 #err += $t9
circleContinue:
#LOOP
j circleLoop
#CONTINUE
skipCircleLoop:
#RESTORE $RA
lw $ra, 0($sp) #Restore $ra from stack
addi $sp, $sp, 20 #Readjust stack
我调用的所有程序都没有更改任何 t 寄存器。我得到以下值的结果:x = 10 y = 10 color = 5 radius = 10
【问题讨论】:
-
您是否在调试器中单步执行了您的代码,以查找寄存器值与您的预期不符的位置?
-
@PeterCordes 是的,我现在还在做这件事,因为有很多价值观。到目前为止,什么都没有引起我的注意。我只是想确保我在转换中没有犯明显的错误。我注意到的一件事是第一个和第二个 drawDots 相距很远,这似乎不正确。
-
这里有点奇怪,当绘制第一个和第二个点的坐标时,它们分别是 10, 19 和 19, 10。绘制时,一个在位图的左半边绘制,另一个在右半边绘制。
-
drawDot代码在哪里? ......啊,你同时想通了......是的,位图的大小确实看起来不错,因为用错误的宽度大小计算目标地址将使y坐标以可预测的方式“环绕”到所有地方(就像在您期望 256x256 时绘制成 512x512 一样,每隔一条线位于图片的右半部分,而奇数行位于左侧,总图片是所需大小的一半,仅使用 512x128 区域)
标签: assembly bitmap mips32 mars-simulator