Call a subroutine on each character in string - MIPS

霸气de小男生 提交于 2019-12-25 06:07:58

问题


I'm new to MIPS assembly, I want to write a routine that takes the memory address of a string and the memory address of another callback subroutine. This routine will go through every letter in the string and for each letter call the subroutine (this prints the ASCII value of each letter). The pseudo code would look something like this:

string_for_each(string, subroutine) {
  for_each_character_in_string {
    subroutine(address_of(character))
  }
}

This is what my routine looks like right now:

string_for_each:

    addi    $sp, $sp, -4            # PUSH return address to caller
    sw  $ra, 0($sp)

    jal loop

    lw  $ra, 0($sp)                 # Pop return address to caller
    addi    $sp, $sp, 4

    jr  $ra

loop:

    lb  $t1, 0($a0)                 # Get current character
    beq $t1, $zero, end_for_each    # Done when reaching NULL character
    jr  $a1                         # Call callback subroutine
    addi    $a0, $a0, 1             # Increment to get next character in string
    j   loop

end_for_each:   

    jr  $ra                         # Return to caller

The thing is that the register $a0 contains the address to the string, and $a1 contains the address to the callback subroutine, and the address to the current character in the string that will be passed to the callback subroutine should also be in $a0. How can $a0 contain both the starting address of the string and the current character at the same time?

The callback subroutine:

ascii:  
    .data
STR_the_ascii_value_is:
    .asciiz "\nAscii('X') = "

    .text

    la  $t0, STR_the_ascii_value_is

    # Replace X with the input character

    add $t1, $t0, 8 # Position of X
    lb  $t2, 0($a0) # Get the Ascii value
    sb  $t2, 0($t1)

    # Print "The Ascii value of..."

    add $a0, $t0, $zero 
    li  $v0, 4
    syscall

    # Append the Ascii value

    add $a0, $t2, $zero
    li  $v0, 1
    syscall


    jr  $ra

回答1:


You will need to save $a0 and $a1 elsewhere (usually stack) for the duration of the subroutine call. Also, your loop isn't a subroutine, no reason to call it using jal. On the other hand, the callback is a subroutine, you should call it using jalr. Something along these lines should work:

string_for_each:

    addiu $sp, $sp, -12             # Need 3 locals for $a0, $a1 and $ra
    sw  $ra, 0($sp)                 # Store $ra
    sw  $a1, 8($sp)                 # Store $a1

loop:
    sw  $a0, 4($sp)                 # Store $a0 as it will be used for argument
    lb  $t0, 0($a0)                 # Get current character
    beq $t0, $zero, end_for_each    # Done when reaching NULL character
    jalr $a1                        # Call callback subroutine
    lw  $a0, 4($sp)                 # Reload $a0
    lw  $a1, 8($sp)                 # $a1 could have changed (calling convention)
    addi $a0, $a0, 1                # Increment to get next character in string
    j   loop

end_for_each:
    lw  $ra, 0($sp)                 # Reload return address to caller
    addiu $sp, $sp, 12              # Free locals
    jr  $ra


来源:https://stackoverflow.com/questions/32204287/call-a-subroutine-on-each-character-in-string-mips

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!