0

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.

Andrea Spadaccini
  • 12,378
  • 5
  • 40
  • 54
KeyC0de
  • 4,728
  • 8
  • 44
  • 68

1 Answers1

2

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
Michael
  • 57,169
  • 9
  • 80
  • 125
  • Thank you. That's because we are dealing with 64bit registers. This is why they use sd. From the manual `sd` is for storing a double word in memory. Now i'm not 100% certain about this, but MIPS considers a word as 32bit. I have used the 64bit convention as well. But it's true that it's strange, since for one they are reserving 4 bytes (.space) but then using the `sd` instruction to store, which will mess another 4 more bytes. I suppose it doesn't matter in this case, because the upper 32bits are probably all 0s. So we have to first reserver .space 8 and then .word 8 to store a 64bit int? – KeyC0de May 02 '17 at 10:28
  • Yeah, the registers are 64-bit, but the addresses might fit in 32 bits. The fact that they only reserve 4 bytes of memory for each address and use `sw` for the format string address suggests that this is the case. If `syscall 5` expects string addresses and integers to be 4 bytes, then `sd` should not be used because that would overwrite whatever is located after that address/integer. – Michael May 02 '17 at 10:32
  • One more question. Since this is an array, i want to print "%d|%d" multiple times. The address where i must store each consecutive integer pair will have to be augmented by 4, or 8 in each loop iteration? This is what i'm trying to troubleshoot now, because i'm getting errors in that `syscall 5` instruction. – KeyC0de May 02 '17 at 11:16
  • You would use the same addresses for every iteration. The two integers should be store 4 bytes apart as far as I can tell from the documentation. – Michael May 02 '17 at 11:18
  • Yeah that's what i thought as well. But i get syscall error and now i'm experimenting with alternate solutions. But how do we store them apart? First `.space 4` and then `.word 4` (for the 1st integer and same for the other), or just `.space 4`, or just `.word 4`? This is what i'm trying to troubleshoot now. Thank you for the help. It is very appreciated. – KeyC0de May 02 '17 at 11:22
  • `.space N` reserves `N` bytes of space (probably with an initial value of 0). `.word N` reserves 4 bytes of space with an initial value of `N`. – Michael May 02 '17 at 11:23
  • News. `.space` [argument] reserves space based on the number of bytes in the argument, `.word [argument]` initializes that space based on the argument, or the array of arguments. I did some changes and i had some progress. However what is printed is gibberish, like that: `￐C￐CJFJF$M$M`S`SA￉A￉￴￴x)x)',',ᄌ1ᄌ1`>`>/B/BヤMヤM↓`↓`MヤMヤWᅠWᅠ│ᄚ│ᄚᅭᅭ8£8£ ̄ ̄` I have to print numbers. What i mainly did is not to supply the label of the formatted string into `addi r14`.. prior to `syscall 5`, but the label of the first argument to that formatted string.. It's so strange and it's not documented precisely at all. – KeyC0de May 02 '17 at 14:44
  • Well, it's not clear to me exactly what you're doing. I suggest starting by modifying the example from the manual to just print two integers. That should be pretty straight-forward. – Michael May 02 '17 at 14:54