assemblymipssimulatormips64edumips64

How to print an array, or a formatted string in EDUMIPS64 simulator?


The documentation for this program is extremely limited. There's almost nothing i can draw from in order to do that. Along with the PDF of the program there's only this:

.data
format_str:     .asciiz "%dth of %s:\n%s version %i.%i is being tested!"
s1:             .asciiz "June"
s2:             .asciiz "EduMIPS64"
fs_addr:        .space  4
                .word   5
s1_addr:        .space  4
s2_addr:        .space  4
                .word   0
                .word   5
test:
.code
        daddi r5, r0, format_str
        sw r5, fs_addr(r0)
        daddi r2, r0, s1
        daddi r3, r0, s2
        sd r2, s1_addr(r0)
        sd r3, s2_addr(r0)
        daddi r14, r0, fs_addr
        syscall 5
        syscall 0

You can check it out here. EDU/WINMIPS64 is very different from regular MIPS assembly

There are a couple of paragraphs explaining this, that are of not much help. At any rate, this here prints a formatted string, along with some string parameters (stored in s1 and s2) and integer parameters (where are they stored?).

I have two arrays stored in memory. I have personally executed instructions upon them and now i want to print them. How do i supply on such a formatted string these two integers (which are double words, ie. needing 8 bytes to be stored)? The help material doesn't explain.

This is the code that i have managed to create up to this point (heavily commented):

....
dadd $s4, $zero, $zero                  ; i = 0
printOutput:                                    ; print results from the 2 arrays
        beq $s4, 960, end                       ; if (i = size = 960 / 8) goto end
        dadd $s1, $s4, $s2                      ; full address of 1st array
        dadd $s0, $s4, $s3                      ; full address of 2nd array

        daddi $a3, $zero, printString           ; address ofstring to be printed stored in $a3
        ld $v0, 0($s1)                          ; $v0 will be used to print 1st array[i]. Is this right?
        ld $v1, 0($s2)                          ; $v1 will be used to print 2nd array[i]. Is this right? Which register to use for supplying a formatted string to print integers? It is not explained anywhere! 
        dadd $14, $zero, $a3                    ; print string. $14 is the register to syscall instructions. But i'm just guessing with this. I really don't know how it should handle. I just supplied $a3 because it seems more intuitive.

        syscall 5                               ; prints ouput (on the MEM stage)
        daddi $s4, $s4, 8                       ; i++
        j printOutput
end:

If anyone knows how to do this, i would be very greatful if he/she could share. There's not any examples on this anywhere. Thanks.

UPDATE

With the help of Michael and by trial and error i found the main cause of the problem. The sequence where we supply the labels for the output string and other memory addresses is very sensitive. By trial and error i found that we must obey the following order:

.data
format_string .asciiz "%d and %i etc.."
start_address .space  4
syscallArg1   .space  4                   ; 1st parameter to syscall 5
syscallArg2   .space  4                   ; 2nd parameter to syscall 5
---other labels go here---
.text
---code---

Note that we have to supply to $14 the start_address label, which must not contain anything (just some available empty space). Before this one the formatted string must go and after this one the arguments to the syscall 5 must lie. Other labels can go afterwards, or before all those.


Solution

  • What the manual says is that you should store the address of the format string, followed by zero or more parameters (e.g. an integer or a string address), in continuous memory, and then load the starting address of that memory into r14 before executing sycall 5.

    Their example code looks slightly incorrect to me, because they should be using sw rather than sd to store r2 and r3 in memory (assuming that the string addresses actually fit in 32 bits).

    So you need to reserve some space in the data section, and then store first the address of your format string, followed by any parameters. And then place the starting address of that piece of memory in r14. For example, if your format string was "%d, %d" and the two values you want to print are in r2 and r3 you would sw r2 and r3 directly after where you store the address of the format string.


    For example:

    .data
    format_str: .asciiz "%d"
    printf_args: .space 8
    ...
    .code
    daddi r5, r0, format_str
    sw r5, printf_args(r0)
    daddi r5, r0, 123
    sw r5, printf_args+4(r0)
    daddi r14, r0, printf_args
    syscall 5