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