所以我想画一个圆圈,但屏幕上只出现4个点。如何生成更多点并连接它们?我已经包含了一张图片,因此您可以看到它在火星中的显示方式。
.data
#midpoint circle algorithm variables
radius: .word 10
err: .word -10
#yvalue = radius
colour: .word 0x00FFFFFF
bmp: .space 0x80000
height: .word 64
width: .word 64
base: .word 0x10040000
.text
lw $a0, radius # x
li $a1, 0 # y
drawn:
bge $a0, $a1, loading
loading:
lw $t1, err
jal plot8points
add $t1, $t1, $a1 #err += y
addi $a1, $a1, 1 #y++
add $t1, $t1, $a1 #err + = y
bltz $a0, drawn
sub $t1, $t1, $a0 # err -= x
addi $a0, $a0, -1 # x--
sub $t1, $t1, $a0 # err-= x
plot8points:
lw $t3, radius # xcenter
li $t4, 0 # ycenter
move $t7, $a0 # x
move $t8, $a1 # y
jal plot4points
blt $a0, $a1, end_loading
jal plot4points
jal plot4morepoints
#jal exit
end_loading:
jr $ra
plot4points:
add $a0, $t7, $t3
add $a1, $t8, $t4
jal setpixel
sub $a0, $t3, $t7
add $a1, $t4, $t8
jal setpixel
add $a0, $t3, $t7
sub $a1, $t4, $t8
jal setpixel
sub $a0, $t3, $7
sub $a1, $t4, $t8
jal setpixel
plot4morepoints:
add $a0, $t3, $t8
add $a1, $t4, $t7
jal setpixel
sub $a0, $t3, $t8
add $a1, $t4, $t7
jal setpixel
add $a0, $t3, $t8
sub $a1, $t4, $t7
jal setpixel
sub $a0, $t3, $t8
sub $a1, $t4, $t7
jal setpixel
setpixel:
lw $t0, colour
lw $s4, width
lw $s2, base
mul $t6, $a1, $s4
add $t6, $t6, $a0
sll $t6, $t6, 2
add $t6, $t6, $s2
sw $t0, ($t6)
jr $ra
#exit:
li $v0, 10
syscall
答案 0 :(得分:2)
您的像素寻址似乎有误。
width
是[您的变量],显示宽度为64
。但是,在您的示例中,位图的宽度为512,高度为256 [这是mars
]中的默认值。
因此,您需要更改mars
中的显示几何图形或将width
变量设置为匹配。高度也一样。
注意: mars
不保留您设置的值,因此如果您想使用非默认几何体,则必须设置每个时间。因此,也许简单的方法是使用mars
默认值。
<强>更新强>
我更改了值以匹配默认值但仍然是错误。我想也许我需要在setpixel代码中更改一些东西,并在某处添加一个计数器
我担心会有很多错误。大多数情况下,您的函数在堆栈中不保存/恢复$ra
并在最后执行jr $ra
。
另外,对我来说,似乎你的八分圆反射代码比它需要的更复杂[因此容易出错]。
我创建了两个版本。第一个是您的原始代码,其中包含有关[某些]错误的注释。第二个是完整的返工工作。
这是带注释的版本[请原谅无偿风格的清理]:
.data
# midpoint circle algorithm variables
radius: .word 10
err: .word -10
colour: .word 0x00FFFFFF
# yvalue = radius
bmp: .space 0x80000
dpy_width: .word 512
dpy_height: .word 256
dpy_base: .word 0x10040000
.text
lw $a0,radius # x
li $a1,0 # y
# BUG: this bge has no meaning since, either way, it goes to "loading"
# probably should be "end_loading"
drawn:
bge $a0,$a1,loading
# BUG: this falls through into the plot8points function
loading:
lw $t1,err
jal plot8points
add $t1,$t1,$a1 # err += y
addi $a1,$a1,1 # y++
add $t1,$t1,$a1 # err + = y
bltz $a0,drawn
sub $t1,$t1,$a0 # err -= x
addi $a0,$a0,-1 # x--
sub $t1,$t1,$a0 # err-= x
# BUG: this is a function but has no return and does _not_ save $ra
plot8points:
lw $t3,radius # xcenter
li $t4,0 # ycenter
move $t7,$a0 # x
move $t8,$a1 # y
jal plot4points
# BUG: we're in a function but this jumps to a label outside the function
blt $a0,$a1,end_loading
jal plot4points
jal plot4morepoints
# jal exit
end_loading:
jr $ra
# BUG: this is a function but has no return and does _not_ save $ra
plot4points:
add $a0,$t7,$t3
add $a1,$t8,$t4
jal setpixel
sub $a0,$t3,$t7
add $a1,$t4,$t8
jal setpixel
add $a0,$t3,$t7
sub $a1,$t4,$t8
jal setpixel
sub $a0,$t3,$7
sub $a1,$t4,$t8
jal setpixel
# BUG: this is a function but has no return and does _not_ save $ra
plot4morepoints:
add $a0,$t3,$t8
add $a1,$t4,$t7
jal setpixel
sub $a0,$t3,$t8
add $a1,$t4,$t7
jal setpixel
add $a0,$t3,$t8
sub $a1,$t4,$t7
jal setpixel
sub $a0,$t3,$t8
sub $a1,$t4,$t7
jal setpixel
# setpixel -- draw pixel on display
#
# arguments:
# a0 -- X coord
# a1 -- Y coord
setpixel:
lw $t0,colour # color
lw $s4,dpy_width # display width
lw $s2,dpy_base # display base address
mul $t6,$a1,$s4 # get y * width
add $t6,$t6,$a0 # get (y * width) + x
sll $t6,$t6,2 # convert to offset
add $t6,$t6,$s2 # add in base address
sw $t0,($t6) # store pixel
jr $ra
# exit:
li $v0,10
syscall
这是经过清理,重构的工作版本。
当我做返工时,我尝试使用维基百科页面中的算法来获得圆算法,但是他们的版本被破坏了,或者我打破了它。它不会产生圆形,而是钻石/六边形图案。所以,我把它留作了一个选项。
所以,我添加了约翰肯尼迪的[圣莫尼卡学院]版本[来自俄勒冈州立大学网站]。它有效。
我还添加了一些选项来自动调整显示并自动计算质心。检查显示值,因为它采用512x256和“静态”显示基址。
我还添加了一些选项,允许绘制同心圆,只是为了娱乐。
# breshenham circle algorithm
.data
radius: .word 10
center_x: .word 0
center_y: .word 0
dpy_color: .word 0x00FFFFFF
# midpoint circle algorithm variables
bmp: .space 0x80000
dpy_width: .word 512
dpy_height: .word 256
dpy_base: .word 0x10010000
.eqv dpy_margin 8
ask_diamond: .word 0
ask_radmin: .word 0
ask_radinc: .word 16
msg_nl: .asciiz "\n"
msg_comma: .asciiz ","
.text
.globl main
main:
.eqv dflg $fp
li dflg,0 # clear debug flag
# prompt user for ask_diamond value
la $a0,_S_000 # prompt user
li $v0,4 # print string
syscall
li $v0,5
syscall
sw $v0,ask_diamond
# prompt user for ask_radmin value
la $a0,_S_001 # prompt user
li $v0,4 # print string
syscall
li $v0,5
syscall
sw $v0,ask_radmin
lw $t0,ask_radmin
beqz $t0,main_skipinc
# prompt user for ask_radinc value
la $a0,_S_002 # prompt user
li $v0,4 # print string
syscall
li $v0,5
syscall
sw $v0,ask_radinc
main_skipinc:
lw $t0,ask_radmin
# compute circle center from display geometry
lw $s6,dpy_width
srl $s6,$s6,1
sw $s6,center_x
lw $s5,dpy_height
srl $s5,$s5,1
sw $s5,center_y
# set radius to min((width / 2) - 16,(height / 2) - 16)
move $s0,$s6
blt $s6,$s5,main_gotradius
move $s0,$s5
main_gotradius:
subi $s0,$s0,dpy_margin # give us some margin
sw $s0,radius
main_loop:
# output circle
jal kdraw
jal radbump
# output diamond/hexagon
lw $t0,ask_diamond # is it enabled?
beqz $t0,main_next # if no, skip
jal wdraw
jal radbump
main_next:
bnez $v0,main_loop # done with concentric circles? if no, loop
main_done:
li $v0,10
syscall
# wdraw -- draw circle (wikipedia)
#
# NOTES:
# (1) this is wikipedia's algorithm for a circle, but it is more like a
# diamond or polygon
# (2) https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
# (2) either it's "broken" or _I_ broke it
#
# registers:
# s0 -- x
# s1 -- y
# s2 -- decision/error term (err)
#
# * void
# * DrawCircle(int x0,int y0,int radius)
# * {
# * int x = radius;
# * int y = 0;
# *
# * // Decision criterion divided by 2 evaluated at x=r, y=0
# * int decisionOver2 = 1 - x;
# *
# * while (y <= x) {
# * DrawPixel(x + x0,y + y0); // Octant 1
# * DrawPixel(y + x0,x + y0); // Octant 2
# * DrawPixel(-x + x0,y + y0); // Octant 4
# * DrawPixel(-y + x0,x + y0); // Octant 3
# * DrawPixel(-x + x0,-y + y0); // Octant 5
# * DrawPixel(-y + x0,-x + y0); // Octant 6
# * DrawPixel(x + x0,-y + y0); // Octant 7
# * DrawPixel(y + x0,-x + y0); // Octant 8
# *
# * y++;
# *
# * // Change in decision criterion for y -> y+1
# * if (decisionOver2 <= 0) {
# * decisionOver2 += 2 * y + 1;
# * }
# *
# * // Change for y -> y+1, x -> x-1
# * else {
# * x--;
# * decisionOver2 += 2 * (y - x) + 1;
# * }
# * }
# * }
wdraw:
subi $sp,$sp,4
sw $ra,0($sp)
lw $s0,radius # x = radius
li $s1,0 # y = 0
# get initial decision (err = 1 - x)
li $s2,1 # err = 1
sub $s2,$s2,$s0 # err = 1 - x
wdraw_loop:
bgt $s1,$s0,wdraw_done # y <= x? if no, fly (we're done)
# draw pixels in all 8 octants
jal draw8
addi $s1,$s1,1 # y += 1
bgtz $s2,wdraw_case2 # err <= 0? if no, fly
# change in decision criterion for y -> y+1
# err += (2 * y) + 1
wdraw_case1:
sll $t0,$s2,1 # get 2 * y
addu $s2,$s2,$t0 # err += 2 * y (NOTE: this can overflow)
add $s2,$s2,1 # err += 1
j wdraw_loop
# change for y -> y+1, x -> x-1
# x -= 1
# err += (2 * (y - x)) + 1
wdraw_case2:
subi $s0,$s0,1 # x -= 1
sub $t0,$s1,$s0 # get y - x
sll $t0,$t0,1 # get 2 * (y - x)
addi $t0,$t0,1 # get 2 * (y - x) + 1
add $s2,$s2,$t0 # add it to err
j wdraw_loop
wdraw_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# kdraw -- draw circle (john kennedy)
#
# NOTES:
# (1) this is John Kennedy's algorithm from:
# http://web.engr.oregonstate.edu/~sllu/bcircle.pdf
#
# registers:
# s0 -- x
# s1 -- y
# s2 -- raderr
# s3 -- xchg
# s4 -- ychg
#
# * void
# * PlotCircle(int CX, int CY, int r)
# * {
# * int x;
# * int y;
# * int xchg;
# * int ychg;
# * int raderr;
# *
# * x = r;
# * y = 0;
# *
# * xchg = 1 - (2 * r);
# * ychg = 1;
# *
# * raderr = 0;
# *
# * while (x >= y) {
# * draw8(x,y);
# * y += 1;
# *
# * raderr += ychg;
# * ychg += 2;
# *
# * if (((2 * raderr) + xchg) > 0) {
# * x -= 1;
# * raderr += xchg;
# * xchg += 2;
# * }
# * }
# * }
kdraw:
subi $sp,$sp,4
sw $ra,0($sp)
lw $s0,radius # x = radius
li $s1,0 # y = 0
# initialize: xchg = 1 - (2 * r)
li $s3,1 # xchg = 1
sll $t0,$s0,1 # get 2 * r
sub $s3,$s3,$t0 # xchg -= (2 * r)
li $s4,1 # ychg = 1
li $s2,0 # raderr = 0
kdraw_loop:
blt $s0,$s1,kdraw_done # x >= y? if no, fly (we're done)
# draw pixels in all 8 octants
jal draw8
addi $s1,$s1,1 # y += 1
add $s2,$s2,$s4 # raderr += ychg
addi $s4,$s4,2 # ychg += 2
sll $t0,$s2,1 # get 2 * raderr
add $t0,$t0,$s3 # get (2 * raderr) + xchg
blez $s2,kdraw_loop # >0? if no, loop
subi $s0,$s0,1 # x -= 1
add $s2,$s2,$s3 # raderr += xchg
addi $s3,$s3,2 # xchg += 2
j kdraw_loop
kdraw_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# draw8 -- draw single point in all 8 octants
#
# arguments:
# s0 -- X coord
# s1 -- Y coord
#
# registers:
# t8 -- center_x
# t9 -- center_y
draw8:
subi $sp,$sp,4
sw $ra,0($sp)
#+drawctr $t8,$t9
lw $t8,center_x #+
lw $t9,center_y #+
#+
# draw [+x,+y]
add $a0,$t8,$s0
add $a1,$t9,$s1
jal setpixel
# draw [+y,+x]
add $a0,$t8,$s1
add $a1,$t9,$s0
jal setpixel
# draw [-x,+y]
sub $a0,$t8,$s0
add $a1,$t9,$s1
jal setpixel
# draw [-y,+x]
add $a0,$t8,$s1
sub $a1,$t9,$s0
jal setpixel
# draw [-x,-y]
sub $a0,$t8,$s0
sub $a1,$t9,$s1
jal setpixel
# draw [-y,-x]
sub $a0,$t8,$s1
sub $a1,$t9,$s0
jal setpixel
# draw [+x,-y]
add $a0,$t8,$s0
sub $a1,$t9,$s1
jal setpixel
# draw [+y,-x]
sub $a0,$t8,$s1
add $a1,$t9,$s0
jal setpixel
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# setpixel -- draw pixel on display
#
# arguments:
# a0 -- X coord
# a1 -- Y coord
#
# clobbers:
# v0 -- bitmap offset/index
# v1 -- bitmap address
# trace:
# v0,a0
setpixel:
bnez dflg,setpixel_show # debug output? if yes, fly
setpixel_go:
lw $v0,dpy_width # off = display width
mul $v0,$a1,$v0 # off = y * width
add $v0,$v0,$a0 # off += x
sll $v0,$v0,2 # convert to offset
lw $v1,dpy_base # ptr = display base address
add $v1,$v1,$v0 # ptr += off
lw $v0,dpy_color # color
sw $v0,($v1) # store pixel
jr $ra
setpixel_show:
move $a2,$a0
move $a3,$a1
# print x
li $v0,1
move $a0,$a2
syscall
# print comma
li $v0,4
la $a0,msg_comma
syscall
# print y
li $v0,1
move $a0,$a3
syscall
# print newline
li $v0,4
la $a0,msg_nl
syscall
move $a0,$a2
move $a1,$a3
j setpixel_go
# radbump -- bump down radius
#
# RETURNS:
# v0 -- 1=more to do, 0=done
#
# registers:
# t0 -- radius value
radbump:
lw $t0,radius
lw $t1,ask_radinc
sub $t0,$t0,$t1
lw $v0,ask_radmin # do multiple rings?
beqz $v0,radbump_store # if no, fly
slt $v0,$v0,$t0 # radius < ask_radmin?
radbump_store:
beqz $t0,radbump_safe
sw $t0,radius
radbump_safe:
jr $ra
#+dfnc
#+
.data
_S_000: .asciiz "output diamond pattern? "
_S_001: .asciiz "minimum radius (0=single) > "
_S_002: .asciiz "radius decrement > "
_S_003: .asciiz "dpy_width"
_S_004: .asciiz "dpy_height"
_S_005: .asciiz "radius"
我最近为结构/链接列表做了MIPS答案。我还添加了很多关于如何编写MIPS代码的建议。在理解我在这里所做的事情时,你可能会有所帮助。请参阅:MIPS linked list
答案 1 :(得分:0)
注意:这个答案是我之前的答案的延续,由于空间原因,这个答案不适合第一个答案。
经过实验,唯一可行的显示映射是&#34;堆&#34;使用下面显示的几何图进行映射这是火星的限制。
这是一个更新/改进版本的颜色:
# mipscirc/fix2.asm -- breshenham circle algorithm
# this _must_ be first
.data
.eqv dpy_max 4194304 # maximum display area
dpy_width: .word 512
dpy_height: .word 256
dpy_base: .word 0x10040000 # heap
dpy_now: .word 0 # current base [for debug]
dpy_blit: .word 0 # 1=do offscreen blit (currently broken)
.eqv dpy_stride 9 # left shift
.eqv dpy_size 524288 # display size (bytes)
.eqv dpy_margin 8 # radius margin
.data
sdata:
radius: .word 10
center_x: .word 0
center_y: .word 0
# midpoint circle algorithm variables
color_octant: .space 32
dpy_radius: .word 10
dpy_color: .word 0x00FFFFFF
ask_diamond: .word 0 # 1=do diamond pattern
ask_radmin: .word 0 # minimum radius (0=single circle)
ask_radinc: .word 16 # radius decrement amount
ask_colorinc: .word 0 # color increment (0=single color)
bitmap: .space dpy_size
.text
.globl main
main:
# this _must_ be first
li $a0,dpy_size # maximum size
li $v0,9 # sbrk
syscall
lw $v1,dpy_base # get what we expect
beq $v0,$v1,dpyinit_done
la $a0,_S_000
li $v0,4 # puts
syscall
dpyinit_done:
.eqv mrzhow $fp
li $v1,0 # clear mask
.eqv MRZDBGPRT 0x00000001 # output numbers
.eqv _MRZDBGPRT 0 # output numbers
.eqv MRZDPYSHOW 0x00000002 # show display coordinates
.eqv _MRZDPYSHOW 1 # show display coordinates
.eqv MRZDPYCHK 0x00000004 # check display area bounds
.eqv _MRZDPYCHK 2 # check display area bounds
move mrzhow,$v1 # set final register value
# prompt user for ask_diamond value
la $a0,_S_001 # prompt user
li $a1,0 # set default
jal qask
sw $v0,ask_diamond # place to store
# prompt user for ask_radmin value
la $a0,_S_002 # prompt user
li $a1,4 # set default
jal qask
sw $v0,ask_radmin # place to store
lw $t0,ask_radmin
beqz $t0,main_skipinc
# prompt user for ask_radinc value
la $a0,_S_003 # prompt user
li $a1,6 # set default
jal qask
sw $v0,ask_radinc # place to store
main_skipinc:
# prompt user for ask_colorinc value
la $a0,_S_004 # prompt user
li $a1,-2 # set default
jal qask
sw $v0,ask_colorinc # place to store
lw $t0,ask_radmin
# compute circle center from display geometry
lw $s6,dpy_width
srl $s6,$s6,1
sw $s6,center_x
lw $s5,dpy_height
srl $s5,$s5,1
sw $s5,center_y
# set radius to min((width / 2) - 16,(height / 2) - 16)
move $s0,$s6
blt $s6,$s5,main_gotradius
move $s0,$s5
main_gotradius:
subi $s0,$s0,dpy_margin # give us some margin
sw $s0,dpy_radius
main_loop:
jal colorgo
jal colorinc
bnez $v0,main_loop
main_done:
li $v0,10
syscall
# colorgo -- draw all items with single color
colorgo:
subi $sp,$sp,4
sw $ra,0($sp)
jal dpybase
# reset the radius
colorgo_noblit:
lw $t0,dpy_radius
sw $t0,radius
colorgo_loop:
# output circle
jal kdraw
jal radbump
# output diamond/hexagon
lw $t0,ask_diamond # is it enabled?
beqz $t0,colorgo_next # if no, skip
jal wdraw
jal radbump
colorgo_next:
bnez $v0,colorgo_loop # done with concentric circles? if no, loop
jal dpyblit # blit to screen (if mode applicable)
colorgo_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# colorinc -- increment to next color
#
# RETURNS:
# v0 -- 1=more to do, 0=done
#
# registers:
# t0 -- color value
colorinc:
subi $sp,$sp,4
sw $ra,0($sp)
lw $v0,ask_colorinc # get option that controls increment
beqz $v0,colorinc_done # do increment? if no, fly
bltz $v0,colorinc_rand # random increment? if yes, fly
lw $t0,dpy_color # get current color
addi $t0,$t0,1 # increment it
andi $t0,$t0,0x00FFFFFF # keep it clean
sw $t0,dpy_color # save it back
li $v0,1
j colorinc_done
colorinc_rand:
jal colorany # get random colors
lw $t0,color_octant # the first one
sw $t0,dpy_color # save to the single color
# without a delay, the colors blast by too fast to be enjoyed
###li $t0,1000000
li $t0,500000
colorinc_loop:
subi $t0,$t0,1
bgtz $t0,colorinc_loop
li $v0,1
colorinc_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# colorany -- get random colors
colorany:
lw $t0,ask_colorinc # get option
li $t1,-3 # get value for the "spin" option
bne $t0,$t1,colorany_noslide # slide mode? if no, fly
li $t0,7
la $t1,color_octant
subi $t1,$t1,4
# slide all colors to make room for single new one
colorany_slide:
addi $t1,$t1,4 # advance
lw $a0,4($t1) # get ptr[1]
sw $a0,0($t1) # set ptr[0]
subi $t0,$t0,1 # more to do?
bnez $t0,colorany_slide # if yes, loop
# set new random first element
li $v0,41 # randint
syscall
andi $a0,$a0,0x00FFFFFF # clean the value
sw $a0,4($t1)
j colorany_done
colorany_noslide:
li $t0,8
la $t1,color_octant
colorany_loop:
li $v0,41 # randint
syscall
andi $a0,$a0,0x00FFFFFF # clean the value
sw $a0,0($t1) # store it
subi $t0,$t0,1 # decrement remaining count
addi $t1,$t1,4 # advance pointer
bnez $t0,colorany_loop # done? if no, loop
colorany_done:
jr $ra
# radbump -- bump down radius
#
# RETURNS:
# v0 -- 1=more to do, 0=done
#
# registers:
# t0 -- radius value
radbump:
lw $t0,radius
lw $t1,ask_radinc
sub $t0,$t0,$t1
lw $v0,ask_radmin # do multiple rings?
beqz $v0,radbump_store # if no, fly
slt $v0,$v0,$t0 # radius < ask_radmin?
radbump_store:
beqz $t0,radbump_safe
sw $t0,radius
radbump_safe:
jr $ra
# wdraw -- draw circle (wikipedia)
#
# NOTES:
# (1) this is wikipedia's algorithm for a circle, but it is more like a
# diamond or polygon
# (2) https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
# (2) either it's "broken" or _I_ broke it
#
# registers:
# s0 -- x
# s1 -- y
# s2 -- decision/error term (err)
#
# * void
# * DrawCircle(int x0,int y0,int radius)
# * {
# * int x = radius;
# * int y = 0;
# *
# * // Decision criterion divided by 2 evaluated at x=r, y=0
# * int decisionOver2 = 1 - x;
# *
# * while (y <= x) {
# * DrawPixel(x + x0,y + y0); // Octant 1
# * DrawPixel(y + x0,x + y0); // Octant 2
# * DrawPixel(-x + x0,y + y0); // Octant 4
# * DrawPixel(-y + x0,x + y0); // Octant 3
# * DrawPixel(-x + x0,-y + y0); // Octant 5
# * DrawPixel(-y + x0,-x + y0); // Octant 6
# * DrawPixel(x + x0,-y + y0); // Octant 7
# * DrawPixel(y + x0,-x + y0); // Octant 8
# *
# * y++;
# *
# * // Change in decision criterion for y -> y+1
# * if (decisionOver2 <= 0) {
# * decisionOver2 += 2 * y + 1;
# * }
# *
# * // Change for y -> y+1, x -> x-1
# * else {
# * x--;
# * decisionOver2 += 2 * (y - x) + 1;
# * }
# * }
# * }
wdraw:
subi $sp,$sp,4
sw $ra,0($sp)
lw $s0,radius # x = radius
li $s1,0 # y = 0
# get initial decision (err = 1 - x)
li $s2,1 # err = 1
sub $s2,$s2,$s0 # err = 1 - x
wdraw_loop:
bgt $s1,$s0,wdraw_done # y <= x? if no, fly (we're done)
# draw pixels in all 8 octants
jal draw8
addi $s1,$s1,1 # y += 1
bgtz $s2,wdraw_case2 # err <= 0? if no, fly
# change in decision criterion for y -> y+1
# err += (2 * y) + 1
wdraw_case1:
sll $t0,$s2,1 # get 2 * y
addu $s2,$s2,$t0 # err += 2 * y (NOTE: this can overflow)
add $s2,$s2,1 # err += 1
j wdraw_loop
# change for y -> y+1, x -> x-1
# x -= 1
# err += (2 * (y - x)) + 1
wdraw_case2:
subi $s0,$s0,1 # x -= 1
sub $t0,$s1,$s0 # get y - x
sll $t0,$t0,1 # get 2 * (y - x)
addi $t0,$t0,1 # get 2 * (y - x) + 1
add $s2,$s2,$t0 # add it to err
j wdraw_loop
wdraw_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# kdraw -- draw circle (john kennedy)
#
# NOTES:
# (1) this is John Kennedy's algorithm from:
# http://web.engr.oregonstate.edu/~sllu/bcircle.pdf
#
# registers:
# s0 -- x
# s1 -- y
# s2 -- raderr
# s3 -- xchg
# s4 -- ychg
#
# * void
# * PlotCircle(int CX, int CY, int r)
# * {
# * int x;
# * int y;
# * int xchg;
# * int ychg;
# * int raderr;
# *
# * x = r;
# * y = 0;
# *
# * xchg = 1 - (2 * r);
# * ychg = 1;
# *
# * raderr = 0;
# *
# * while (x >= y) {
# * draw8(x,y);
# * y += 1;
# *
# * raderr += ychg;
# * ychg += 2;
# *
# * if (((2 * raderr) + xchg) > 0) {
# * x -= 1;
# * raderr += xchg;
# * xchg += 2;
# * }
# * }
# * }
kdraw:
subi $sp,$sp,4
sw $ra,0($sp)
lw $s0,radius # x = radius
li $s1,0 # y = 0
# initialize: xchg = 1 - (2 * r)
li $s3,1 # xchg = 1
sll $t0,$s0,1 # get 2 * r
sub $s3,$s3,$t0 # xchg -= (2 * r)
li $s4,1 # ychg = 1
li $s2,0 # raderr = 0
kdraw_loop:
blt $s0,$s1,kdraw_done # x >= y? if no, fly (we're done)
# draw pixels in all 8 octants
jal draw8
addi $s1,$s1,1 # y += 1
add $s2,$s2,$s4 # raderr += ychg
addi $s4,$s4,2 # ychg += 2
sll $t0,$s2,1 # get 2 * raderr
add $t0,$t0,$s3 # get (2 * raderr) + xchg
blez $s2,kdraw_loop # >0? if no, loop
subi $s0,$s0,1 # x -= 1
add $s2,$s2,$s3 # raderr += xchg
addi $s3,$s3,2 # xchg += 2
j kdraw_loop
kdraw_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# draw8 -- draw single point in all 8 octants
#
# arguments:
# s0 -- X coord
# s1 -- Y coord
#
# registers:
# t8 -- center_x
# t9 -- center_y
draw8:
subi $sp,$sp,4
sw $ra,0($sp)
lw $t8,center_x
lw $t9,center_y
lw $a2,dpy_color
lw $t0,ask_colorinc
li $t1,-2
ble $t0,$t1,draw8_octant
# draw [+x,+y]
add $a0,$t8,$s0
add $a1,$t9,$s1
jal dpypixel
# draw [+y,+x]
add $a0,$t8,$s1
add $a1,$t9,$s0
jal dpypixel
# draw [-y,+x]
add $a0,$t8,$s1
sub $a1,$t9,$s0
jal dpypixel
# draw [-x,+y]
sub $a0,$t8,$s0
add $a1,$t9,$s1
jal dpypixel
# draw [-x,-y]
sub $a0,$t8,$s0
sub $a1,$t9,$s1
jal dpypixel
# draw [-y,-x]
sub $a0,$t8,$s1
sub $a1,$t9,$s0
jal dpypixel
# draw [+x,-y]
add $a0,$t8,$s0
sub $a1,$t9,$s1
jal dpypixel
# draw [+y,-x]
sub $a0,$t8,$s1
add $a1,$t9,$s0
jal dpypixel
j draw8_done
draw8_octant:
la $t7,color_octant
# draw [+x,+y]
add $a0,$t8,$s0
add $a1,$t9,$s1
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [+y,+x]
add $a0,$t8,$s1
add $a1,$t9,$s0
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [-y,+x]
add $a0,$t8,$s1
sub $a1,$t9,$s0
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [-x,+y]
sub $a0,$t8,$s0
add $a1,$t9,$s1
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [-x,-y]
sub $a0,$t8,$s0
sub $a1,$t9,$s1
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [-y,-x]
sub $a0,$t8,$s1
sub $a1,$t9,$s0
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [+x,-y]
add $a0,$t8,$s0
sub $a1,$t9,$s1
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
# draw [+y,-x]
sub $a0,$t8,$s1
add $a1,$t9,$s0
lw $a2,0($t7)
addi $t7,$t7,4
jal dpypixel
draw8_done:
lw $ra,0($sp)
addi $sp,$sp,4
jr $ra
# marzmca/marzdpy.inc -- mars display functions
# dpypixel -- draw pixel on display
#
# arguments:
# a0 -- X coord
# a1 -- Y coord
# a2 -- color
# a3 -- display base address
#
# clobbers:
# v1 -- bitmap offset/index
# trace:
# v0,a0
dpypixel:
dpypixel_go:
lw $v1,dpy_width # off = display width
mul $v1,$a1,$v1 # off = y * width
add $v1,$v1,$a0 # off += x
sll $v1,$v1,2 # convert to offset
add $v1,$a3,$v1 # ptr = base + off
sw $a2,($v1) # store pixel
jr $ra
# dpybase -- get display base address
#
# RETURNS:
# a3 -- display base address
dpybase:
lw $a3,dpy_base # direct draw to display
lw $t0,dpy_blit
beqz $t0,dpybase_done
la $a3,bitmap # draw to bitmap
dpybase_done:
sw $a3,dpy_now # remember it [for debug]
jr $ra
# dpyblit -- blit bitmap to display
dpyblit:
lw $a0,dpy_blit # blit mode?
beqz $a0,dpyblit_done # if no, fly
li $t0,2 # zap the background first?
blt $a0,$t2,dpyblit_init # if no, fly
# zero out the display
lw $a0,dpy_base # get the base address
addi $a1,$a0,dpy_size # get the end address
dpyblit_zap:
sw $zero,0($a0) # set black
addi $a0,$a0,4 # advance current pointer
blt $a0,$a1,dpyblit_zap # more to do? if yes, loop
# setup for blit
dpyblit_init:
lw $a0,dpy_base # get the base address
addi $a1,$a0,dpy_size # get the end address
la $a2,bitmap # get offscreen address
dpyblit_loop:
lw $t0,0($a2) # fetch from offscreen image
addi $a2,$a2,4 # advance offscreen pointer
sw $t0,0($a0) # store to live area
addi $a0,$a0,4 # advance current pointer
blt $a0,$a1,dpyblit_loop # more to do? if yes, loop
dpyblit_done:
jr $ra
# marzmca/marzqask.inc -- extra prompting functions
.eqv qask_siz 100
# qask -- prompt user for number (possibly hex)
#
# RETURNS:
# v0 -- value
#
# arguments:
# a0 -- prompt string
# a1 -- default value
#
# registers:
# a2 -- save for a0
# a3 -- save for a1
# t0 -- current buffer char
# t1 -- offset into qask_hex
# t2 -- current hex string char
# t3 -- current hex string pointer
# t6 -- 1=negative
# t7 -- number base
qask:
move $a2,$a0 # remember for reprompt
move $a3,$a1 # remember for reprompt
qask_retry:
# output the prompt
move $a0,$a2
li $v0,4
syscall
la $a0,qask_dft1
li $v0,4
syscall
# output the default value
move $a0,$a3
li $v0,1
syscall
la $a0,qask_dft2
li $v0,4
syscall
# read in string
li $v0,8
la $a0,qask_buf
la $a1,qask_siz
syscall
lb $t0,0($a0) # get first buffer char
li $t1,0x0A # get newline
beq $t0,$t1,qask_dft # empty line? if yes, use default
li $v0,0 # zap accumulator
# decide if we have a negative number
li $t6,0
lb $t0,0($a0) # get first buffer char
li $t1,'-'
bne $t0,$t1,qask_tryhex
li $t6,1 # set negative number
addi $a0,$a0,1 # skip over '-'
# decide if want hex
qask_tryhex:
li $t7,10 # assume base 10
li $t1,'x'
bne $t0,$t1,qask_loop
addi $a0,$a0,1 # skip over 'x'
li $t7,16 # set base 16
qask_loop:
lb $t0,0($a0) # get character
addi $a0,$a0,1 # advance buffer pointer
# bug out if newline -- we are done
li $t1,0x0A
beq $t0,$t1,qask_done
la $t3,qask_hex
li $t1,0
qask_trymatch:
lb $t2,0($t3) # get next hex char
addi $t3,$t3,1 # advance hex string pointer
beq $t2,$t0,qask_match # got a match
addi $t1,$t1,1 # advance hex offset
blt $t1,$t7,qask_trymatch # too large? if no, loop
j qask_retry # if yes, the input char is unknown
qask_match:
mul $v0,$v0,$t7 # acc *= base
add $v0,$v0,$t1 # acc += digit
j qask_loop
qask_dft:
move $v0,$a3
j qask_exit
qask_done:
beqz $t6,qask_exit
neg $v0,$v0 # set negative number
qask_exit:
jr $ra
.data
qask_dft1: .asciiz " ["
qask_dft2: .asciiz "] > "
qask_buf: .space qask_siz
qask_hex: .asciiz "0123456789ABCDEF"
.text
.data
_S_000: .asciiz "dpyinit: mismatch\n"
_S_001: .asciiz "output diamond pattern?"
_S_002: .asciiz "minimum radius (0=single)"
_S_003: .asciiz "radius decrement"
_S_004: .asciiz "color increment (-1=rand, -2=rand/octant, -3=spin)"
_S_005: .asciiz "dpy_width"
_S_006: .asciiz "dpy_height"
_S_007: .asciiz "dpy_radius"
.data #+
#+
edata: