【问题标题】:MIPS swap functionMIPS交换功能
【发布时间】:2018-08-29 23:41:13
【问题描述】:

从我今天的问题历史中可以明显看出,我正在开发一个 MIPS 项目,该项目将反转一个字符串,在本例中为“Hello, World”。我想我的循环和字符串反转函数是正确的,但我无法弄清楚交换函数本身,或者如何输出被操纵的字符串。

我知道这样的基本交换是:

sll $t1, $a1, 2
add $t1, $a0,$t1
lb $t0,0($t1)
lb $t2, 4($t1)

sb $t0,0($t1)
sb $t2, 4($t1)
jr $ra

但我不知道它的作用或我如何解释它以适应我的代码。如果那里的某个圣徒可以解释它是如何工作的以及系统调用是如何工作的,我将永远感激不尽。我的代码如下:

.data 

    string: .asciiz "Hello, World!"

.text
main:
    li $v0, 4
    la $a0, string #store string in a0
    syscall



    jal stringreverse

stringreverse:
    add $t0,$a0,$zero   #base address of string
    add $a1, $zero,14   #stores size of string in a1
    addi $t2, $a1, -1   #j = length -1
    add $t3,$zero,$zero     #i = 0

loop:
    jal swap
    addi $t2,$t2,-1     #j--
    addi $t3,$t3,+1     #i++

    slt  $t7,$t3,$t2 #set t7 to 1 when j is less than i
    bne  $t7,$zero,loop # if i is greater than j, keep looping
    j done
swap:   #swaps the sooner element with the later and returns back to the loop
    lb      $v0,0($t3)              # updated to fit my registers t3 =i
    lb      $v1,0($t2)              # updated to fit my registers t2 =j

    sb      $v1,0($t3)              
    sb      $v0,0($t2)              

    jr $ra

done:
    .....procedure here.....
    syscall 

【问题讨论】:

  • 查看我对您上一个问题的回答:stackoverflow.com/questions/49393986/… BTW,您真的应该只编辑原件而不是发布[稍微修改]的副本
  • 反向结构与我的相似。在我的反向/交换中,我始终使用char* pointers(与索引变量相比)。请注意main -> reverse -> swap,因此main 中的$ra 值需要由reverse 保留,因为jal swap 破坏了它
  • 另外,请注意,从 mips ABI 中,只有 $s0-$s7 必须保留(并且堆栈寄存器必须在函数退出时指向函数入口的同一位置)。否则,任何 reg 都可以用于任何目的。我故意在我的swap 中使用$v0/$v1(与$t* 相比)。唯一真正硬连线的 [按架构] regs 是 $ra$zero
  • 感谢您的建议,我不知道礼仪。至于你的第二条评论,你能详细说明一下吗?我正在研究示例,并且对程序的实际工作方式知之甚少。所以我不太确定你所说的 $ra 值是什么意思。
  • 当你做jal func时,它会将返回地址(jal之后的地址放入$ra(返回地址)寄存器)然后跳转到funcjal$ra 的使用是为数不多的硬连线选择之一。通常的返回方式是jr $ra,即跳转到$ra中的地址。这是正常的顺序,但jr 绑定到$ra,您可以使用任何其他注册(例如在我的代码中,我使用$t0 来说明这一点:jr $t0 因为我之前将$ra 保存到$t0 中)

标签: assembly mips mips32


【解决方案1】:

看起来您将 lb(加载字节指令)视为 la(加载地址指令)。

你可能想做更多这样的事情:

swap:
    lb    $temp1,   str($t2)    #load temp1 address with byte at $t2 in str 
    lb    $temp2,   str($t1)    #load temp2 address with byte at $t1 in str
    sb    $temp2,   str($t2)    #store temp2 byte into $t2'th position in str
    sb    $temp1,   str($t1)    #store temp1 byte into $t1'th position in str
    jr    $ra

有一些数据,例如:

.data
str:
    .asciiz "your string here"

希望这可以为您解决一些问题。

【讨论】:

  • 我相信 $a# 和 $v# 寄存器通常被保留用作系统调用的参数。在这种情况下,您要查找的相关系统调用是 li $v0, 4 #system call to print la $a0, ($regwithstringaddress) #load string syscallli $v0, 10 #system call to exit syscall
  • 大喊大叫,我的男人!所以我开始主要的第一个li一直都是错误的?我应该在 li $v0, 8 la $a0, string syscall 才能读取字符串?
  • 是的,我之前评论中的代码应该用字符串加载$a0,然后打印出来。
  • 请注意,str($reg) 只有在您将模拟器设置为在低 32kiB 的地址空间中具有静态数据时才可能,例如从地址00x1000 或其他地址开始的数据部分。否则标签地址不能适合像 lblw 这样的单个 I 类型指令的 16 位有符号立即数。
猜你喜欢
  • 2023-03-17
  • 1970-01-01
  • 2021-11-15
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多