Reputation: 1787
I want to create a red screen in the MARS Bitmap-display, than I want to make the borders yellow.
I do this by first making the first and last row yellow, and than the first and last columns.
This is my code:
#MIPS
#ND
#1 b
li $t0, -4 #$t0 holds current iterator
li $s0, 0 #Current COLOMN_iterator
li $s1, 0 #Current ROW_iterator
main:
li $t1, 0x00ff0000 #Loading RED in register
li $t2, 0x00ffff00 #Loading YELLOW in register
addi $gp, $gp, 4 #Incrementing register with one word (next pixel in display)
addi $t0, $t0, 4 #Incrementing current location to next pixel
addi $s0, $s0, 1 #Column++
blt $s1, 1, makePixelYellow #if currentRow == 1
beq $s1, 31, makePixelYellow #if currentRow == 31
j makePixelRed
makePixelYellow:
sw $t2, -4($gp) #Make pixel yellow
bne $s0, 32, main
addi $s1, $s1, 1 #Column finsihed, so row++
li $s0, 0 #Resetting column
j main
makePixelRed:
sw $t1, -4($gp) #Make pixel red
j main
Output & settings of the Bitmap display:
I think the problem occurs somewhere on line 19. I'm able to make all the rows below a specific n yellow using Branch-less than. But I'm not able to color one specific row using Branch-equal.
The label is only executing correctly on branch-less than, not branch-equal. It's MIPS ASM by the way.
Upvotes: 2
Views: 6080
Reputation: 16606
Answer by Jester: you don't update row/column when you branch to makePixelRed
code.
My general advice about computer graphics programming:
Usually when programming some pixel graphics, you don't want to branch per-pixel, that's very costly in terms of performance, with code aimed for performance you do the opposite, rather emit more code-paths covering different situations to draw desired output with minimal branching involved.
The "calculate something + branch a lot + draw single pixel + loop" is used only when performance is not critical, but instead you want to have only single general code for pixel drawing and looping (like column/row advancing, which would actually save you from your error, if you would use those branches only to set yellow/red pixel, and then return to some "main" ending to finish the loop code), like in some raytracer code, or when coding on minimal binary size (256B intros use often this kind of architecture, one quite complex formulae to calculate pixel colour and then single setPixel code and loop = it's slow, but it saves many bytes by not having multiple setPixel copies everywhere).
Here is some more direct "set yellow border + red body" example from me (tested with MARS 4.5, delayed branching OFF, and I used the same Bitmap setting like you (16x16 unit with 512x256 display, which means 32x16 bitmap target .. UX FTW!)
li $t1, 0x00ff0000 #Loading RED in register
li $t2, 0x00ffff00 #Loading YELLOW in register
big_loop:
# top row + first column
move $a0, $gp # pointer to write to
li $a1, 33 # 32 pixels for first row, +1 for left column
move $a2, $t2 # yellow
jal setPixels
# 14 red rows with yellow endings+starts
li $t0, 14
red_rows_loop:
li $a1, 30
move $a2, $t1
jal setPixels # set 30 red pixels in middle
sw $t2, ($a0) # set 1 yellow at end, and 1 at start of next row
sw $t2, 4($a0)
addi $a0, $a0, 8
addi $t0, $t0, -1
bnez $t0, red_rows_loop
# finish last row to be full yellow
li $a1, 31 # 31 pixels more needed (1 is already there)
move $a2, $t2 # yellow
jal setPixels
li $v0, 32 # MARS service delay(ms)
li $a0, 40 # 40ms = ~25 FPS if the draw would be instant
syscall
addiu $t1, $t1, 0xFE0408 # adjust main color (red -2, green +4, blue +8 + overflows (B -> G -> R)
andi $t1, $t1, 0xFFFFFF # force "alpha" to zero
j big_loop # infinite loop will animated colours...
# Sets $a1 pixels to $a2 value starting at $a0 (memory fill)
# a0 = pointer to write to, a1 = count of pixels, a2 = value of pixel to set
# a0 will be updated to point right after the last written word
setPixels:
sw $a2, ($a0) # set pixel (or simply memory word)
addi $a0, $a0, 4 # advance memory pointer
addi $a1, $a1, -1 # count-down loop
bnez $a1, setPixels
jr $ra # return
Upvotes: 2