1

I want to make a programme that reads several characters with no particular limit but just pressing Enter (I found that the ascii code for the Enter key is 13, correct me if I'm wrong) and kind of "stitch" them together.

For example, if the user gives the characters '3', '4', '5', the programme should show the integer '345'. So, each character should match a bit.

I tried to play with the loop as below:

.text
.globl main
main:

add $t0, $zero, $zero       #counter

loop:
    li  $v0, 12         #v0 = the character that was read
    syscall
    subi    $v0, $v0, 48        

#from the register column, I found that after the syscalls, the v0
#register always adds 48 to the given character

    beq $v0, 13, exit       #if Enter is given, exit from the loop

    move    $t1, $v0   #move the character to t1

    sb  $t1, ($t0)      #store the character to t0

    addiu   $t0, $t0, 1     #point to the next spot of the t0

j loop
exit:

add $a0, $t0, $zero         #load the contents of t0 to a0

li  $v0, 1                #print the result
syscall

li  $v0, 10
syscall

The error that shows at my awkardly written code is "Runtime exception at 0x00400020: address out of range 0x00000000" due to the "store byte" command.

Should I have give an offset?

Is the whole "store byte" thingy fundamentally wrong?

Is the given_character-48 each time necessary?

What should I do?

Coursal
  • 1,387
  • 4
  • 17
  • 32
  • I didn't write in my answer anything about how to deal with non-native large integers, as that looks a bit too complex for your current Assembly skills IMO. So I'm pushing you toward "string" solution, but maybe that's not what you expected. – Ped7g Nov 24 '16 at 19:16
  • BTW, I'm unable to figure out, why input '3', '4', '5' should produce '347' on output. It's not clear from your question, what kind of calculation you want to do with input values ... so I will just guess it's a typo. – Ped7g Nov 24 '16 at 19:25
  • it really is a typo – Coursal Nov 24 '16 at 20:18

1 Answers1

1

There are few problems with your code and how do you understand things, one is:

subi    $v0, $v0, 48

This will convert ASCII digits from '0' - '9' characters into value 0-9, so you can later use it as number for calculation.

As you want to "stitch it together" as string, you don't want to convert the ASCII character into number, just keep it as is.


Other one is:

sb  $t1, ($t0)

This takes value from register t1, and contacts memory chip with "write it at address t0" command. But the t0 is zero, and memory address 0x00000000 is not available for you for writing.

You can't keep in computer data of arbitrary size, the memory has finite amount, so you have to decide what largest string you want to keep (plus you are keeping it in uncompressed form, so number of bytes reserved for your string is directly limiting your string to be of the same amount of ASCII characters minus one, the last one reserved is for null-terminator of string).

Allocate some memory buffer for the result (in data segment), and do la $t0,result_buffer first.

Then after last character (or after running out of reserved space, so you if you want to create correct safe application, you should have also some counter to check max length of input string) store one more byte behind it, of zero value, then in result you will have null-terminated string.


And that one can be output with function li $v0, 4 (and a0 should contain address of result_buffer again). The 1 is for printing integers, you are not building an integer from input.


If you want to build integer from input, then [without coding your own non-native long integer support] you are limited to 32b integer (which you can store into some spare register, during input, so you don't need to reserve space in memory, just do result = 10 * result + input in every step), so you will be able to enter max number 231-1 (if the "print integer" works for signed numbers).


EDIT: and of course SPIM/MARS have built-in debuggers, you should have step instruction by instruction over your code to see what it is actually doing. Although if you didn't realize you are writing to 0x00000000 from that error message, debugging it and watching sb with target t0 = 0 would probably not ring the bell either.

Still you should at least try. The sooner you will understand the debugger and how it shows the machine, the sooner you will be able to code on your own. (SO is not debugging service and questions of your quality gets usually downvoted and closed).

Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • I know that my questions aren't the most bright, for sure. I try to learn mips by myself and it gets difficult without someone to help. You seem to be more than experienced in assembly and to be honest, since english isn't my first language, sometimes several terms fly above my head. Like the "result_buffer" thing or a bunch of other terms that are loosely translated to my first language. I know people like you put effort and get frustated by questions like mine, but I appreciate your help no matter what. I will try. – Coursal Nov 24 '16 at 20:29
  • @Coursal just keep posting what is confusing you, I will try to explain in other words.. about buffer, string in assembly is series of bytes. So you have to have somewhere spare memory few bytes long (for maximum string). And the easiest way to allocate few bytes in MIPS ASM source is to do in `.data` section add `result_buffer: .space 25` -> that will reserve 25 bytes with label `result_buffer` pointing at the first one. You may check also this answer (it's for x86, but ASCII strings are same on MIPS): http://stackoverflow.com/questions/40575898/how-to-use-strings-in-emu8086/40580889#40580889 – Ped7g Nov 24 '16 at 20:35