I'm very very new to mips. I'm not sure where to start with this:
let's say I have
li $t1, -3
li $t2, -9
I want to print a string that is
(-3,-9)
What data structure do I store this in? .byte? .space?
This is what I have so far, it prints out "(,)"; Am I on the right track? Where do I go from here?
string: .space 10
.text
.globl main
main: la $t0, string
li $t1, -3
li $t2, -9
li $t3, '('
li $t4, ','
li $t5, ')'
li $t6, '-'
sb $t3, ($t0)
sb $t4, 1($t0)
sb $t5, 2($t0)
j exit
exit:
li $v0, 4 # print the string
la $a0, string
syscall
li $v0, 10 # terminate program
syscall
CodePudding user response:
Assembly (MIPS/MARS) uses C-style nul-terminated strings — a nul character, '\0' ascii value 0, goes at the end and is interpreted as to end the string, but itself is not part of the string.
So, remember to null terminate your string. Also remember to allocate 1 more byte of storage than you need for the string, to hold that nul byte. Note that the .space
directive will provide you with initially zero'd storage, but if you use that storage multiple times, then you'll probably want to nul-terminate dynamically. If you put "(-82,-45)" there and then restart for another conversion, from the beginning put this time "(-9,-3)" — without nul-termination it will actually hold "(-9,-3)5)", with leftover characters from the prior.
If you're taking numbers to characters you'll need an algorithm called itoa
(stands for integer to ascii) or print number or convert number to string. These are pretty straight forward and there's quite a few of them, though they are all similar. The idea is to use math to produce/extract individual digits and then having a single digit at a time, convert to their ascii equivalent for printing or putting in a string.
Most itoa
algorithms will check for < 0 and if so, then emit a -
sign, then negate the number and proceed as if it were positive (which, once negated, it is).
The simplest itoa
approach is if you know, for example, that you want at most 2 digit numbers, then the upper digit is isolated by dividing the number by 10. So, for 45, then 45/10=4, then add '0' aka 48 to that and you'll have 52, which is the ascii code for the character '4'. Next take your 45 and mod by 10, so 45=5, and add 48 to it to get 53, which is the code for '5'. You can generalize that into a loop.
Some algorithms work backward to produce digits because that's easy to do: first mod by 10, then divide by 10, and repeat until the value goes to nothing (0). 456->6, and 456/10->45, next 45->5, and 45/10->4, next 4->4 and 4/10->0 so you stop. 6, 5, 4, just has to be reversed for printing or copying.
You don't need to think in assembly language for this, as any language can manipulate bytes into strings. You want to think algorithmically (rather than in assembly). The above can be done in C and thinking algorithmically in assembly is hard when you don't know it; it is also useful to know what you're trying to code up before doing so in assembly. Coding a C version, then translate that to assembly is worthwhile.
.space
will reserve global storage which is initialized to zero upon program start.
You can also allocate stack space or allocate from the heap, but both of those are more complicated than the global allocation.
Your start is ok, just need to work some itoa
algorithms into it.
Since translating numbers sometimes results in different count of characters (e.g. 3 is one character long but -3 and 45 are each two characters long). Your itoa
approach will use a variable to tell where (which byte) to store next rather than using fixed offsets like you're currently doing. When choosing using a variable, you can use a pointer or an index. A pointer would be natural to use here, but to be clear an index would work as well, and either one can be done in C and also in assembly. The pointer or index needs to be advanced when you add a character to the string, so you always know where to go next (and where to put the nul terminator when you're done putting characters into the string).
Since you're converting 2 different numbers into strings, a good approach would probably use a function to help; however, functions add a bunch of complexity in assembly; this complexity is probably best picked up after other basics.