###################################################################### # snprintf.s # # This is the main function that tests the snprintf function # The "data" segment is a static memory area where we can # allocate and initialize memory for our program to use. # This is separate from the stack or the heap, and the allocation # cannot be changed once the program starts. The program can # write data to this area, though. .data # Note that the directives in this section will not be # translated into machine language. They are instructions # to the assembler, linker, and loader to set aside (and # initialize) space in the static memory area of the program. # The labels work like pointers-- by the time the code is # run, they will be replaced with the starting addresses # of their memory blocks. # For this program, we will allocate a buffer to hold the # result of your sprintf function. The asciiz blocks will # be initialized with null-terminated ASCII strings. buffer: .space 200 # 200 bytes of empty space # starting at address 'buffer' guard: .space 200 # 200 bytes of guard space, into which # snprintf shouldn't write, but it might # if it ignores the outbufsize argument # (arg1). format: .asciiz "string: %s, unsigned dec: %u, hex: 0x%x, char: %c, dec: %d.\n" # null-terminated string of # ascii bytes. Note that the # \n counts as one byte: a newline # character. str: .asciiz "thirty-nine" # null-terminated string at # address 'str' chrs: .asciiz " characters:\n" # null-terminated string at # address 'chrs' # The "text" of the program is the assembly code that will # be run. This directive marks the beginning of our program's # text segment. .text # The special label called "__start" marks the start point # of execution. Later, the "done" pseudo-instruction will make # the program terminate properly. __start: addi $sp,$sp,-16 # reserve stack space # $v0 = snprintf(buffer, buffersize, format, str, 39, 46, 111, -39) # la isn't really a MIPS instruction, assemblers # translate it into lui/ori pairs as needed. la $a0,buffer # arg 0 <- buffer li $a1,200 # arg 1 <- size of buffer la $a2,format # arg 2 <- format la $a3,str # arg 3 <- str addiu $t0,$0,39 sw $t0,0($sp) # arg 4 <- 39 addiu $t8,$0,46 sw $t8,4($sp) # arg 5 <- 46 addiu $t0,$0,111 sw $t0,8($sp) # arg 6 <- 111 ('o', as a character) addiu $t0,$0,-39 sw $t0,12($sp) # arg 7 <- -39 jal snprintf # $v0 = snprintf(...) # print the return value from sprintf using # putint() addu $a0,$v0,$0 # $a0 <- $v0 jal putint # putint($a0) ## output the string 'chrs' then 'buffer' (which ## holds the output of sprintf) addiu $v0, $0, 4 # The code to print a string using syscall la $a0, chrs # output string chrs syscall la $a0, buffer # output string buffer syscall addiu $sp, $sp, 16 # restore stack addiu $v0, $0, 10 # terminate program syscall # putint writes the number in $a0 to the console # in decimal. It uses the special command # putc to do the output. # HINT: You should read and understand the body of putint, # because you will be doing some similar conversions # in your own code. putint: addiu $sp,$sp,-8 # get 2 words of stack sw $ra,0($sp) # store return address # The number is printed as follows: # It is successively divided by the base (10) and the # reminders are printed in the reverse order they were found # using recursion. addiu $t0, $0, 10 # $t0 <- 10 divu $a0, $t0 # lo <- $a0 / $t0, hi <- $a0 % $t0 mfhi $t0 # $t0 <- $a0 % $t0 addi $t0,$t0,'0' # $t0 += '0' ($t0 is now a digit character) mflo $a0 # $a0 /= 10 beq $a0,$0,onedig # if( $a0 != 0 ) { sw $t0,4($sp) # save $t0 on our stack jal putint # putint() (putint will deliberately use $a0, and return $v0) lw $t0,4($sp) # restore $t0 add $a0,$v0,$0 # $a0 = $v0, get the result of putint # } onedig: addu $a0, $0, $t0 # output the digit character $t0 addiu $v0, $0, 11 # 11 is the code to print a single character form $a0 syscall lw $ra,0($sp) # restore return address addiu $sp,$sp, 8 # restore stack addu $v0,$a0,$0 # return the modified argument... jr $ra # return ############################################################################ ################# ALL YOUR CHANGES MUST BE BELOW THIS LINE ################# ############################################################################ # You should comment this function snprintf: # Your code and comments go here! jr $ra