Why am i getting an error on the sb function in my integer to string loop?

32 Views Asked by At

i am writing a bigger program but am stuck on this problem of converting my value from an integer to a string. ive tried various solutions from similar problems but im either not implementing them correctly or there is another issue i am missing. This is the error i am getting on qtspim.

Exception occurred at PC=0x004000ec Bad address in data/stack read: 0x0000003f

I ran the program without the int_to_string loop and it ran perfectly, with expected output.

The bigger program reads in a value from another file, converts it to an integer, adds 10 and then should write this value to the new file.

Because the entire program is quite long and has a lot of unnecessary information to this particular issue, ive extracted and modified the code which i will paste below (that's why you might see some lines that look inefficient or odd - it still runs as expected though), but this is the line that keeps producing errors:

    sb $t3, 0($t2)                  # Store the ASCII character in the buffer

Any help would be appreciated!

.data
    header_buffer:              .asciiz "123 "
    width:              .word 0         # Integer to store width of file
    height:             .word 0         # Integer to store height of file
    max_val:            .word 0         # Integer to store maximum value of a pixel
    num_pixels:         .word 0         # Integer to store number of pixels in file 
    buffer:             .space 128
    filename:           .asciiz "input.ppm"
    output_filename:    .asciiz "output.ppm"


.text
    .globl main
    
    
main:
    li $t0, 64
    sw $t0, width
    sw $t0, height
    li $t0, 255
    sw $t0, max_val
    li $t0, 12288
    sw $t0, num_pixels
    

# Open the output file for writing
open_output:
    li $v0, 13          # System call code for opening a file (write mode)
    la $a0, output_filename
    li $a1, 1           # File mode (write)
    li $a2, 0
    syscall
    move $s1, $v0       # Save the file descriptor in $s1

    
# Initialise registers 
prep_to_read_pixels:
    li $s2, 0           # Sum of R values
    li $s3, 0           # Sum of G values
    li $s4, 0           # Sum of B values
    
    li $t5, 0           # Pixel counter
    la $t6, max_val     # Max value of pixel
    li $t8, 0           # Int value of pixel 
    la $t1, header_buffer
    li $t0, 0

read_red:

    lb $t2, 0($t1)                      # Load the read character
    move $t7, $t2                       # Copy read char to $t7
    addi $t1, $t1, 1                    # Move pointer
    addi $t0, $t0, 1                    #track num digits in number
    addi $t9, $t9, 1                    # Increment - change position of the end of header to the current end
    beq $t2, 32, incr_red               # Check if char is whitespace 
    beq $t2, 10, incr_red               # Check if char is new line
    jal loop_to_convert
    j read_red
    
incr_red:
    addi $t5, $t5, 1
    add $s2, $s2, $t8
    addi $t8, $t8, 10
    ble $t8, $t6, update_and_store_red
    jal clamp   
    j update_and_store_red



    
update_and_store_red:
    move $t0, $t8       # Copy the integer to convert     
    la $t4, buffer
    move $t4, $t2
    addi, $t2, $t2, 31
    sb $zero, ($t2)
    addi $t2, $t2, -1
    jal int_to_string
    li $v0, 15          # System call code for writing a byte
    move $a0, $s1       # File descriptor (stdout)
    move $a1, $t4       # Byte to write
    la $a2, 64       # Number of bytes to write
    syscall
    li $t2, 0
    li $t0, 0
    beq $t5, 1, exit
    j read_red
    

exit:
    # Close the file
    li $v0, 16           # Close syscall code
    move $a0, $s1        # File descriptor
    syscall

    # Exit the program
    li $v0, 10           # Exit syscall code
    syscall

loop_to_convert:
    addi $t7, $t7, -48      # Convert ascii char to digit equivalent by subtracting "0" (ascii code 48)
    mul $t8, $t8, 10        # Multiply the running total by 10
    add $t8, $t8, $t7       # Add new digit to running total
    jr $ra                  # Jump back
    
clamp:
    li $t8, 255    # Clamp value to 255
    jr $ra
    
int_to_string:
    addi $t7, $t7, 1
    div $t0, $t0, 10                # Divide $t0 by 10 (get quotient in $t0, remainder in $t3)
    mflo $t0                        # Quotient
    mfhi $t3                        # Remainder
    addi $t3, $t3, 48               # Convert to ASCII      
    sb $t3, 0($t2)                  # Store the ASCII character in the buffer
    addi $t2, $t2, -1               # Move the pointer to the left in the buffer
    bnez $t0, int_to_string         # Repeat until $t0 becomes zero
done:
    jr $ra
0

There are 0 best solutions below