MIPS 在函数参数上使用字符串

MIPS use string on arguments of function

我在 MIPS 上有这个函数,它将缓冲区中的字符串的小写字母转换为大写字母:

funcion:
    addi $t0,$zero,0

    loop:
        lb $t1, buffer($t0)
        beq $t1, 0, exit_loop
        blt $t1, 'a', case
        bgt $t1, 'z', case
        sub $t1, $t1, 32
        sb $t1, buffer($t0)

    case: 
            addi $t0, $t0, 1
            j loop

    exit_loop:
        jr $ra

    .data

buffer: .asciiz "Meow"
buffer2: .asciiz "Guau"

我想将它用于 buffer2,如何将类似字符串的参数发送给函数?

我试试这个

    la $a0,buffer

    jal convertir_a_mayusculas

并更改循环函数

    loop:
        lb $t1, $a0($t0)
        beq $t1, 0, exit_loop
        blt $t1, 'a', case
        bgt $t1, 'z', case
        sub $t1, $t1, 32
        sb $t1, $a0($t0)

但是不起作用,怎么了?

$a0($t0) 不是有效的寻址模式,因为它有两个寄存器,好消息是您根本不需要 $t0:只需递增 $a0.

funcion:

    loop:
        lb $t1, ($a0)
        beq $t1, 0, exit_loop
        blt $t1, 'a', case
        bgt $t1, 'z', case
        sub $t1, $t1, 32
        sb $t1, ($a0)

    case: 
            addi $a0, $a0, 1
            j loop

    exit_loop:
        jr $ra

如果 MARS 设置中未启用 pseudo-instructions,您可能需要将 ($a0) 更改为 0($a0)

这个clobber$a0,我不记得MIPS调用约定是否使它变易变了,如果你需要保留它,就把它复制到t0开头函数,然后使用 t0

在第二次尝试中使用寄存器来保存字符串地址是正确的方法。

如果缓冲区超过 16 位,使用 lb $t1, buffer($t0) 可能会产生问题。它可以在小示例中工作,但在实际代码中很危险。

第二次尝试的主要问题是指令 lb $t1, $a0($t0) 在句法上不正确。 lb 需要一个目标寄存器、一个地址寄存器和一个 必须 是立即数的偏移量。

因此,由于缓冲区的地址已经在 $a0 中,您可以在循环中使用 lb $t1, 0($a0) 并递增 $a0 来访问连续的字符。

loop:
    lb $t1, 0($a0)       # loads byte at address $a0+0
    beq $t1, 0, exit_loop
    blt $t1, 'a', case
    bgt $t1, 'z', case
    sub $t1, $t1, 32
    sb $t1, 0($a0)
case: 
    addi $a0, $a0, 1    # let $a0 point to next char in buffer
    j loop
exit_loop:
    jr $ra