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.
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