Я не думаю, что вы сможете найти чисто портативное решение на основе python без использования / proc или утилит командной строки, по крайней мере, не в самом python. Парсинг os.system не уродлив - кто-то должен иметь дело с несколькими платформами, будь то вы или кто-то еще. Реализация этого для ОС, которую вы заинтересованы, должна быть довольно простой, честно.
Ваша адресация пикселей кажется неправильной.
width
- [ваша переменная] для ширины экрана, которая является 64
. Но в вашем примере битмап имеет ширину 512 и высоту 256 [которые являются значениями по умолчанию в mars
].
Итак, вам нужно либо изменить геометрию отображения в mars
или установите для параметра width
значение. То же самое для высоты.
Примечание: mars
выполняет not сохранение установленных вами значений, поэтому, если вы хотите использовать геометрию, отличную от значения по умолчанию , вам нужно будет установить каждое время. Итак, возможно, простой способ - использовать значения по умолчанию mars
.
UPDATE:
Я изменил значения, чтобы они совпадали с ошибками по умолчанию, но все же. Я думаю, может быть, мне нужно что-то изменить в коде setpixel. N также добавить счетчик где-нибудь
blockquote>. Боюсь, что появилось множество ошибок. В основном, ваши функции сделали не сохранение / восстановление
$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
Вот очищенная , отредактированная рабочая версия.
Когда я сделал переделку, я попытался использовать алгоритм со страницы wikipedia для алгоритма круга, но либо их версия сломана, либо I сломал ее , Он не создает круг, а образец алмаза / шестиугольника. Итак, я оставил его в качестве опции.
Итак, я добавил версию Джону Кеннеди [Santa Monica College] [с сайта OSU]. Он работает.
Я также добавил некоторые опции для автоматического отображения на дисплей и автоматического вычисления центроида. Проверьте значения дисплея, так как он предполагает 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 список
Примечание: этот ответ является продолжением моей предыдущей, которая не поместилась бы по соображениям космоса в первый ответ.
После экспериментов единственным жизнеспособным отображением отображения является «куча», отображение с геометрией, показанной ниже. Это ограничение марса.
Вот обновленная / улучшенная версия, которая делает цвет:
# 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:
$ra
сохраняется / восстанавливается из стека в начале / конце функций. Это важно для правильной работыfncA->fncB->fncC
– Craig Estey 24 April 2016 в 01:58