0
votes

I'm pretty new to assembly programming and programming in general and I'm doing my best to learn. I've been having trouble storing inputs to variables, can you help me please?

The problem seems to occur when I load the addresses of n1 and n2, or something like that. I have tried looking at similar problems and cannot translate them well. If anyone has any online references for learning, as well, that would be greatly appreciated.

Here is my code:

.data
prompt_n1: .asciiz "Enter first integer n1: "
prompt_n2: .asciiz "Enter second integer n2: "

debug_print: .asciiz "Your numbers are: "

n1: .word 0
n2: .word 0

.text

main:
#Prompt the user for n1.
li $v0, 4
la $a0, prompt_n1
syscall

#Store console: n1
li $v0, 5
syscall

#Attempts to load value of v0 into n1 - Problem Here
la $t0, n1
lw $t1, 0($v0)
sw $t0, 0($t1)

#Prompt the user for n2.
li $v0, 4
la $a0, prompt_n2
syscall

#Store console: n2
li $v0, 5
syscall

#Attempts to load value of v0 into n1 - Problem Here
la $t0, n2
lw $t4, 0($v0)
sw $t0, 0($t4)

j print_statement

print_statement:
li $v0, 4
la $a0, debug_print
syscall

li $v0, 1
lw $a0, n1
syscall

li $v0, 1
lw $a0, n2
syscall

Thank you for your time and help.

1

1 Answers

1
votes

Several problems ...

After doing the syscall 5 to get the user's value, it is in $v0. You were trying to transfer this to $t1 using a lw instruction. But, you were using $v0 as the base address of the lw. If the value the user entered was not a multiple of four, this would cause an alignment exception [as you got]

What you wanted was move [register to register] and not load from memory. But, actually, you really didn't need to do this.

Rather, just store $v0 into n1, which is pointed to by $t0. So, your sw was also incorrect.

Also, because n1 and n2 were not the first items after the .data directives, they might not be aligned to a four byte boundary, as they must to use lw/sw on them. So, you need a .align directive.

These issues were repeated for the input of n2.

And, after printing, there was nothing to stop the program, so it would have kept on going, attempting to fetch and execute instructions with whatever random values were in that memory. The program needs a syscall to properly terminate execution when it is done.

I've annotated your code showing the before and after, with bug fixes [please pardon the gratuitous style cleanup]:

    .data
prompt_n1:  .asciiz     "Enter first integer n1: "
prompt_n2:  .asciiz     "Enter second integer n2: "

debug_print:    .asciiz "Your numbers are: "
space:          .asciiz " "

# NOTE/BUG: because of the variable length byte arrays above (i.e. the .asciiz
# directives), these may not be aligned to a four byte boundary. there are two
# solutions:
# (1) place n1 and n2 immediately after the .data directive
# (2) add a .align directive [as below]
            .align      4
n1:         .word       0
n2:         .word       0

    .text

main:
    # Prompt the user for n1.
    li      $v0,4
    la      $a0,prompt_n1
    syscall

    # Store console: n1
    li      $v0,5
    syscall

    # Attempts to load value of v0 into n1 - Problem Here
    la      $t0,n1

    # NOTE/BUG: this is incorrect for several reasons:
    # (1) $v0 has a value input by the user -- it could be 0, 1, etc.
    # (2) these are not valid data addresses
    # (3) if the user enters a value that is _not_ a multiple of four, it
    #     generates an alignment exception
    # (4) this instruction is just not needed and is just wrong
    ###lw       $t1,0($v0)

    # NOTE/BUG: $t1 has _not_ been set -- this should use the [correctly] set
    # register $t0 [which has the address of n1] and should store the value
    # read from the user
    ###sw       $t0,0($t1)
    sw      $v0,0($t0)

    # Prompt the user for n2.
    li      $v0,4
    la      $a0,prompt_n2
    syscall

    # Store console: n2
    li      $v0,5
    syscall

    # Attempts to load value of v0 into n1 - Problem Here
    # NOTE/BUG: the lw is commented out for the same reason as above and has
    # a similar mistake as above
    la      $t0,n2
    ###lw       $t4,0($v0)
    ###sw       $t0,0($t4)
    sw      $v0,0($t0)

    j       print_statement

print_statement:
    li      $v0,4
    la      $a0,debug_print
    syscall

    li      $v0,1
    lw      $a0,n1
    syscall

    # NOTE/BUG: added this to separate the numbers
    li      $v0,4
    la      $a0,space
    syscall

    li      $v0,1
    lw      $a0,n2
    syscall

    # NOTE/BUG: there was no more code here so it just "falls off the end of
    # the world" -- we need to terminate program execution correctly with the
    # exit syscall
    li      $v0,10
    syscall

Some resources:

http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html

http://courses.missouristate.edu/kenvollmar/mars/help/syscallhelp.html

http://logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm

http://chortle.ccsu.edu/assemblytutorial/index.html