hi i am required to write a program in mips assembler where i am to create a checkerboard which is too be saved and written to a bmp file, compile this program it has a problem with writing the file because it jumps straight to my error message could someone please help me with this problem. Here is the code:
.data
.align 0
bmpheader:
.ascii "BM" # 00>BITMAPFILEHEADER.bfType
.word 0 # 02>BITMAPFILEHEADER.bfSize
.half 0 # 06>BITMAPFILEHEADER.bfReserved1
.half 0 # 08>BITMAPFILEHEADER.bfReserved2
.word 62 # 10>BITMAPFILEHEADER.bfOffBits
.word 40 # 14>BITMAPINFOHEADER.biSize
.word 0 # 18>BITMAPINFOHEADER.biWidth
.word 0 # 22>BITMAPINFOHEADER.biHeight
.half 1 # 26>BITMAPINFOHEADER.biPlanes
.half 1 # 28>BITMAPINFOHEADER.biBitCount
.word 0 # 30>BITMAPINFOHEADER.biCompression
.word 0 # 34>BITMAPINFOHEADER.biSizeImage;
.word 0 # 38>BITMAPINFOHEADER.biXPelsPerMeter
.word 0 # 42>BITMAPINFOHEADER.biYPelsPerMeter
.word 0 # 46>BITMAPINFOHEADER.biClrUsed
.word 0 # 50>BITMAPINFOHEADER.biClrImportant
.byte 0x00 0x00 0x00 0x00 # first palette color (0 bits)
.byte 0xff 0xff 0xff 0x00 # second palette color (1 bits)
arg1: .asciiz "Enter square size: "
arg2: .asciiz "Enter checkerboard size: "
arg1_error: .asciiz "Illegal value of square size\n"
arg2_error: .asciiz "Illegal value of checkerboard size\n"
mem_error: .asciiz "Memory allocation error\n"
file_open_error: .asciiz "Open file error\n"
file_write_error: .asciiz "Write file error\n"
bmp_file: .asciiz "chkboard.bmp"
ok_message: .asciiz "OK\n"
.text
main:
#----Get args from user----
li $v0, 4 # print string
la $a0, arg1
syscall
li $v0, 5 # read integer
syscall
slti $t0, $v0, 1
sgt $t1, $v0, 100
or $t0, $t0, $t1
beqz $t0, get_arg2
li $v0, 4 # print string
la $a0, arg1_error
syscall
b exit # exit the program
get_arg2:
move $s0, $v0 # square size in $s0
li $v0, 4 # print string
la $a0, arg2
syscall
li $v0, 5 # read integer
syscall
slti $t0, $v0, 1
sgt $t1, $v0, 100
or $t0, $t0, $t1
beqz $t0, set_header
li $v0, 4 # print string
la $a0, arg2_error
syscall
b exit # exit the program
set_header:
move $s1, $v0 # checkerboard size in $s1
mul $a0, $s0, $s1
add $t0, $a0, 0x0000001f
andi $t0, $t0, 0xffffffe0
srl $s2, $t0, 3 # number of bytes per line in $s2
la $t0, bmpheader
usw $a0, 18($t0) # bitmap width
usw $a0, 22($t0) # bitmap height
mul $a0, $a0, $s2 # bitmap pixels data size
add $t1, $a0, 62
usw $t1, 2($t0) # bitmap file size
usw $a0, 34($t0) # BITMAPINFOHEADER.biSizeImage
li $v0, 9 # alloc memory
syscall
bnez $v0, checkerboard
li $v0, 4 # print string
la $a0, mem_error
syscall
b exit # exit the program
checkerboard:
move $s3, $v0 # start address of pixels in memory in $s3
move $s4, $a0 # pixels data size in $s4
move $t0, $zero # square flag
move $t1, $s3 # start address of a line
move $t2, $s1 # vertcal square counter (number of rows)
#----Single line of pixels----
line:
move $t3, $t1 # pixel address
li $t4, 0x80 # pixel mask
move $t5, $s1 # square counter (in a line)
move $t6, $s0 # pixel counter (in a square)
# temporary buffer in $t7 (actually it needn't to be initialized)
pixel:
beqz $t0, clear # if square flag is 0, branch to "clear" (current pixel is cleared)
or $t7, $t7, $t4 # otherwise, set the current pixel (we do it on the temporary buffer using our pixel mask)
b shift
clear:
not $t8, $t4 # pixel mask inverted (because we need to do logical AND)
and $t7, $t7, $t8 # clear the pixel
shift:
srl $t4, $t4, 1 # shift the pixel mask one bit right (because we want to address the next pixel on the right)
bnez $t4, next # if the mask is nonzero (so we are still on the same byte), branch to "next"
sb $t7, ($t3) # otherwise (i.e. we have to address the next byte), store the whole previous byte from temporary buffer
add $t3, $t3, 1 # increment the address, so it points to the next byte
li $t4, 0x80 # and reset the pixel mask, so it addresses the leftmost pixel in a byte
next:
sub $t6, $t6, 1 # decrement the pixel counter in a square
bnez $t6, pixel # repeat to produce one line of a black or white square
move $t6, $s0 # reset the pixel counter in a square (to square size - the first program argument)
not $t0, $t0 # invert the square flag (if we have made a line of a black square, now we will make a line of a white square and vice versa)
sub $t5, $t5, 1 # decrement the square counter in a line
bnez $t5, pixel # loop if we haven't complete the whole line
beq $t4, 0x80, advance # if pixel mask is 0x80 (which means we've completed and stored the whole byte in memory), skip storing the buffer
sb $t7, ($t3) # otherwise we have to "flush" the buffer
#----Duplicate the line----
advance:
add $t1, $t1, $s2 # move to the next line (add the line length in bytes to the start address of the line)
sub $t6, $t6, 1 # this register (see above) contains the square size (in pixels) so we can use it as a counter for how many times to copy the line to produce a row of checkerboard
beqz $t6, row # if the square size is 1, there is no need to do anything else (because the line have already been generated)
duplicate:
sub $t3, $t1, $s2 # the address of the previous line (that one that was first generated or the one just copied)
move $t4, $t1 # the address of the current line
move $t5, $s2 # set byte counter (how many bytes to copy) to the line length, this value is a multiple of 4
copy:
lw $t7, ($t3) # load a word from the source (previous) line
add $t3, $t3, 4 # increment the source pointer
sw $t7, ($t4) # store the word to the destination (current) line
add $t4, $t4, 4 # increment the destination pointer
sub $t5, $t5, 4 # decrement the byte counter
bnez $t5, copy # loop if there's any data left for copying
add $t1, $t1, $s2 # move to the next line (add the line length in bytes to the start address of the current line)
sub $t6, $t6, 1 # decrement the line counter in a row of the checkerboard
bnez $t6, duplicate # repeat to complete the row
row:
move $t6, $s0 # reset the pixel counter in a square (to square size - the first program argument)
and $t5, $s1, 1 # check if bit 0 of checkerboard size value is set (i.e. simply check if the value is even)
bnez $t5, count # and if not, branch to "count"
not $t0, $t0 # negate logically the square flag
count:
sub $t2, $t2, 1 # decrement the row counter
bnez $t2, line # repeat if not done
#----Write .BMP file (header+data)----
li $v0, 13 # open file
la $a0, bmp_file # file path
li $a1, 0x8301 # flags WRITE|CREATE|TRUNCATE|BINARY
li $a2, 0x1a4 # 0644 UNIX mode (rw-r--r--)
syscall
bgez $v0, write_file
li $v0, 4 # print string
la $a0, file_open_error
syscall
b exit # exit the program
write_file:
move $a0, $v0 # file descriptor
li $v0, 15 # write to file
la $a1, bmpheader # file buffer
li $a2, 62 # number of bytes to write
syscall
bgez $v0, write_data
li $v0, 4 # print string
la $a0, file_write_error
syscall
b exit # exit the program
write_data:
li $v0, 15 # write to file
move $a1, $s3 # file buffer
move $a2, $s4 # number of bytes to write
syscall
bgez $v0, close_file
li $v0, 4 # print string
la $a0, file_write_error
syscall
b exit # exit the program
close_file:
li $v0, 16 # close file syscall
syscall
li $v0, 4 # print string
la $a0, ok_message
syscall
exit:
li $v0, 10 # exit the program
syscall