位图 ASM 中的颜色特定行

Color specific row in bitmap ASM

我想在 MARS 位图显示中创建一个红色屏幕,而不是将边框设为黄色。

我首先将第一行和最后一行设为黄色,然后将第一列和最后一列设为黄色。

这是我的代码:

#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

位图显示的输出和设置:

我认为问题出现在第 19 行的某处。我可以使用 Branch-less than 将特定 n 下面的所有行设为黄色。但是我无法使用 Branch-equal 为特定行着色。

标签仅在小于分支而非分支等于时正确执行。 顺便说一句,它是 MIPS ASM。

Jester 的回答:当您分支到 makePixelRed 代码时,您不会更新 row/column。


我对计算机图形编程的一般建议:

通常在对一些像素图形进行编程时,您不希望按像素进行分支,这在性能方面的成本非常高,而针对性能的代码则相反,而是发出更多的代码路径来涵盖不同的情况以最少的分支绘制所需的输出。

"calculate something + branch a lot + draw single pixel + loop" 仅在性能不重要时使用,但您只想使用单个通用代码进行像素绘制和循环(例如 column/row 前进,这实际上可以节省您的时间你的错误,如果你只使用这些分支来设置 yellow/red 像素,然后 return 到一些 "main" 结束以完成循环代码),就像在一些光线跟踪器代码中,或者在编码时在最小的二进制大小上(256B 介绍经常使用这种架构,一个非常复杂的公式来计算像素颜色,然后是单个 setPixel 代码和循环 = 它很慢,但它通过没有多个 setPixel 副本来节省很多字节)。

这是我的一些更直接的 "set yellow border + red body" 示例(使用 MARS 4.5 测试,延迟分支关闭,并且我使用了与您相同的位图设置(16x16 单元和 512x256 显示,这意味着 32x16 位图目标。 .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