algorithmassemblymipsmars-simulatorbresenham

Bresenham's line algorithm in MIPS


I need to draw a line on a 32x32 white/black image using Bresenham's line algorithm. I have read_bmp and save_bmp functions, as well as function which sets color, function which draws a pixel and a function which draws a line. Unfortunately, when I complile my code, there is only pixel showing in a result.bmp file.

.eqv    pHeader 0
.eqv    filesize 4
.eqv    pImg    8
.eqv    width   12
.eqv    height  16
.eqv    linesbytes 20

.eqv    bi_imgoffset  10
.eqv    bi_imgwidth   18
.eqv    bi_imgheight  22

.eqv    max_file_size 2048

    .data
filename:   .asciiz "white32x32.bmp"
resultfile: .asciiz "result.bmp"
color_err:  .asciiz "Incorrect color - should be 0 or 1"

num_one:      .word 1
num_neg_one:  .word -1
mult2:  .word 2
loop:   .word 32
        .align  4
descriptor: .word   0, 0, 0, 0, 0, 0, 0, 0, 0

filebuf:    .space max_file_size

    .text
    
    
    move $t0, $zero 
    lw   $s0, loop 
main:
    la $a0, filename
    la $a1, descriptor
    la $t0, filebuf
    sw $t0, pHeader($a1)
    li $t0, max_file_size
    sw $t0, filesize($a1)
    jal read_bmp_file
    # check for errors
    
    
        la   $a0, descriptor
        li   $a1, 6  #cx
        li   $a2, 8  #cy
        li   $a3, 0  #color
        li $s0, 10   #x
        li $s1, 12   #y
        jal line_to
        addi $t0, $t0, 32
        j main
        
        move $t0, $zero 
    lw   $s0, loop 
    li $v0, 10
    syscall
    
line_to:
    

# |register|   variable  |
# | t0     |   cx        |   
# | t1     |   cy        |
# | t2     |    dx - dy  |   
# | t3     |   ai        |
# | t4     |   bi        |
# | s0     |   x         |
# | s1     |   y         |
# | s2     | dx = x-cx   |
# | s3     } dy = y-cy   |      
# | s4     |   xi        |
# | s5     |   yi        |


    sub $s3, $s0, $t0 #s3 = x - cx
    sub $s4, $s1, $t1 #s4 = y - cy

#if (dx < 0) { xi = 1 } else { xi = -1}
    slt $t0, $s0, $s1   #dx = -dx;
    beq $t0, $zero, if_1_else  
    if_1_then:
     lw $s4, num_one
         j if_1_exit
    if_1_else:
         lw $s4, num_neg_one
    if_1_exit:

#if (dy < 0) { yi = 1 } else { yi = -1}
    slt $t0, $s0, $s1   #dy = -dy;
    beq $t0, $zero, if_2_else  
    if_2_then:
        lw $s5, num_one
         j if_2_exit
    if_2_else:
         lw $s5, num_neg_one
    if_2_exit:

    sub $t2, $s2, $s3 #   dy - dx

    lw $t0, num_neg_one
    mult $t0, $s3
    mflo $s3 # s3 = -dy

    move $t0, $a0 # t0 = cx
    move $t1, $a1 # t1 = cy
    move $s1, $s0 # s0 = x
    move $s2, $s1 # s1 = y
    jal set_next_pixel

loop_cond:
    

    sub $t3, $s1, $t0 
    sub $t4, $s2, $t1 
    add $t3, $t3, $t4 
    beqz $t3, loop1_end
    
    lw $t3, mult2
        mult $t3, $t2
        mflo $t3
        
        slt $t4, $s3, $t3 
    beqz $t4, loop1_end
    
    lopp_if_1_then:
        add $t2, $t2, $s3 
        add $t0, $t0, $s4 
        loop1_end:
        
        slt $t4, $t3, $s2 
        beqz $t4, loop2_end
        loop_if_2_then:
        add $t2, $t2, $s2 
        add $t1, $t1, $s5 
        loop2_end:

        j loop_cond 
        
 #loop_cond_end:
         
        
    jr $ra
set_next_pixel:
    lw $t0, linesbytes($a0)
    mul $t0, $t0, $a2   # $t0 offset of the beginning of the row
    
    sra $t1, $a1, 3     # pixel byte offset within the row
    add $t0, $t0, $t1   # pixel byte offset within the image
    
    lw $t1, pImg($a0)
    add $t0, $t0, $t1   # address of the pixel byte
    
    lb $t1, 0($t0)
    
    and $a1, $a1, 0x7   # pixel offset within the byte
    li $t2, 0x80
    srlv $t2, $t2, $a1  # mask on the position of pixel
    
    jal set_color
#   sub $a3, $a3, 1
#   bnez $a3, set_next_pixel
    
    la $a0, resultfile
    la $a1, descriptor
    jal save_bmp_file
    
    li $v0, 10
    syscall
    
set_color:
    addi $v1, $zero, 1
    blt $a3, $zero, print_color_err     # if a3 < 0, then error
    bgt $a3, $v1, print_color_err   #if a3 > 1, then error
    beq $a3,$v1, white  # if a3 = 1, then white
        beq $a3,$zero, black    # if a3 = 0, then black
        jr $ra
black:
    xor $t1, $t1, $t2    # set proper pixel to 0 (black)
    sb $t1, 0($t0)
    jr $ra
white:
    or $t1, $t1, $t2    # set proper pixel to 1 (white)
    sb $t1, 0($t0)
    jr $ra
print_color_err:
    li $v0, 4
    la $a0, color_err
    syscall


read_bmp_file:
    # $a0 - file name 
    # $a1 - file descriptor
    #   pHeader - contains pointer to file buffer
    #   filesize - maximum file size allowed
    move $t0, $a1
    li $a1, 0
    li $a2, 0
    li $v0, 13 # open file
    syscall
    # check for errors: $v0 < 0
    
    move $a0, $v0
    lw $a1, pHeader($t0)
    lw $a2, filesize($t0)
    li $v0, 14
    syscall
    
    sw $v0, filesize($t0)  # actual size of bmp file

    li $v0, 16 # close file
    syscall

    lhu $t1, bi_imgoffset($a1)
    add $t1, $t1, $a1
    sw $t1, pImg($t0)
    
    lhu $t1, bi_imgwidth($a1)
    sw $t1, width($t0)
    
    lhu $t1, bi_imgheight($a1)
    sw $t1, height($t0)
    
    # number of words in a line: (width + 31) / 32
    # number of bytes in a line: ((width + 31) / 32) * 4
    lw $t1, width($t0)
    add $t1, $t1, 31
    sra $t1, $t1, 5 # t1 contains number of words
    sll $t1, $t1, 2
    sw $t1, linesbytes($t0)
    jr $ra
    


save_bmp_file:
    # $a0 - file name 
    # $a1 - file descriptor
    #   pHeader - contains pointer to file buffer
    #   filesize - maximum file size allowed
    move $t0, $a1
    li $a1, 1  # write
    li $a2, 0
    li $v0, 13 # open file
    syscall
    # check for errors: $v0 < 0
    
    move $a0, $v0
    lw $a1, pHeader($t0)
    lw $a2, filesize($t0)
    li $v0, 15
    syscall
    
    li $v0, 16 # close file
    syscall

Every function besides line_to works fine, but I do not know what causes a problem in line_to.


Solution

  • You need a philosophy for debugging.

    Static Debugging

    You can see that there is a mismatch between comments and code.

    (btw, +1 for having a written register-variable map.)

    Dynamic Debugging


    Other Problems

    Other Observations