String 在MIPS程序集中切换字符位置

String 在MIPS程序集中切换字符位置,string,assembly,mips,String,Assembly,Mips,我想打印出来 Hello, world. ello, world.H llo, world.He lo, world.Hel o, world.Hell , world.Hello world.Hello, world.Hello, orld.Hello, w rld.Hello, wo ld.Hello, wor d.Hello, worl .Hello, world Hello, world. 仅在内存中使用此字符串字符串:.asciiz“你好,世界。”。到目前为止,这是我的代码:

我想打印出来

Hello, world.
ello, world.H
llo, world.He
lo, world.Hel
o, world.Hell
, world.Hello
 world.Hello,
world.Hello,
orld.Hello, w
rld.Hello, wo
ld.Hello, wor
d.Hello, worl
.Hello, world
Hello, world.
仅在内存中使用此字符串
字符串:.asciiz“你好,世界。”
。到目前为止,这是我的代码:

    .text
String:    .asciiz "Hello, world."
x:         .float 13

    .data 
Main:       lw $t0,x
            jal PrintString
            li $v0, 10
            syscall

PrintString:    la $a0,String
                li $v0,4
                syscall
                bgtz $t0, MoveString
                jr $ra

MoveString: (CODE)
但我不确定在MoveString标签中放什么。我需要将
String
中的字符移位1,然后将
x
中的字符减去1。我不知道该怎么做。谢谢你的帮助

首先要注意几点:

  • 你把
    .text
    .data
    搞混了
  • 继续,在字符串的末尾添加一个换行符,这将使显示更加美观:

    String:    .asciiz "Hello, world.\n"
    
  • 假设字符串长度使用13,则应使用整数而不是浮点:

    x:         .word 13
    
现在,我们来谈谈这个问题。有两种方法可以做到这一点:1)将字符串旋转到位,每次调用
syscall 4
,或2)保持字符串原样,每次打印一个字母,使用索引来实现旋转效果。你已经选择了方法1,让我们继续吧

首先编写一些伪代码。您需要一个将存储在
$a0
的字符串向左旋转一个字母的子程序。立即,您应该考虑某种循环,它迭代字符串中的每个字母:

for int index from 0 to 12
    copy letter from (index + 1) to index
但是等等:第一个字母怎么了?它会被击倒的。当我们到达终点时会发生什么?我们将把
String
范围之外的内容复制到最后一个字母槽。因此,让我们通过将第一个字母存储到临时寄存器来解决这个问题:

temp = letter[0]

for int index from 0 to 11
    copy letter from (index + 1) to index

letter[12] = temp
那更好;应该这样做。下一个问题:我们如何在MIPS中做到这一点

我们知道,
$a0
将保存字符串的地址,因此我们认为这是理所当然的。我们至少需要一个临时寄存器——因为我们已经在为
x
使用
$t0
,让我们使用
$t1
来保存第一个字母:

MoveString:
lb $t1, String
我们还需要一个索引寄存器,所以让我们使用
$t2
来实现这一点。将其初始化为零:

li $t2, 0
最好只为每个字母增加一次地址寄存器,但我们不想重复
$a0
,因为它会弄乱
PrintString
。因此,让我们将其复制到循环的
$a1

move $a1, $a0
最后,我们需要知道字符串的长度,因此让我们将另一份
x
加载到
$t3

lb $t3, x
sub $t3, $t3, 1               ; We're only iterating over the first 12 letters,
                              ; since the last letter is done manually with temp
现在我们可以开始循环了。我们需要将字母(仅为一个字节)从
$a1+1
复制到
$a1

MoveStringLoop:
lb $t4, 1($a1)                  ; Load the letter from (address + 1)
sb $t4, 0($a1)                  ; Store it to (address)
add $a1, $a1, 1                 ; Increment our address
add $t2, $t2, 1                 ; Increment our index
blt $t2, $t3, MoveStringLoop    ; Loop again if index < (length - 1)

sb $t1, 0($a1)                  ; Copy the temp letter to the end of the string
无论如何,这不是一个最优的解决方案;我相信一个真正的编译器和一些更好的编码可以在一半的指令中完成这项工作。但既然您正在学习如何编写汇编,现在就不用担心微优化了。以下是最终代码及其输出:

    .data
String:    .asciiz "Hello, world.\n"
x:         .word 13

    .text 
Main:       lw $t0,x
            jal PrintString
            li $v0, 10
            syscall

PrintString:    la $a0,String
                li $v0,4
                syscall
                bgtz $t0, MoveString
                jr $ra

MoveString:
                lb $t1, String
                li $t2, 0
                move $a1, $a0
                lb $t3, x
                sub $t3, $t3, 1

MoveStringLoop:
                    lb $t4, 1($a1)
                    sb $t4, 0($a1)
                    add $a1, $a1, 1
                    add $t2, $t2, 1
                    blt $t2, $t3, MoveStringLoop

                sb $t1, 0($a1)

                sub $t0, $t0, 1
                b PrintString
输出:

Hello, world.
ello, world.H
llo, world.He
lo, world.Hel
o, world.Hell
, world.Hello
 world.Hello,
world.Hello,
orld.Hello, w
rld.Hello, wo
ld.Hello, wor
d.Hello, worl
.Hello, world
Hello, world.
首先有几点注意:

  • 你把
    .text
    .data
    搞混了
  • 继续,在字符串的末尾添加一个换行符,这将使显示更加美观:

    String:    .asciiz "Hello, world.\n"
    
  • 假设字符串长度使用13,则应使用整数而不是浮点:

    x:         .word 13
    
现在,我们来谈谈这个问题。有两种方法可以做到这一点:1)将字符串旋转到位,每次调用
syscall 4
,或2)保持字符串原样,每次打印一个字母,使用索引来实现旋转效果。你已经选择了方法1,让我们继续吧

首先编写一些伪代码。您需要一个将存储在
$a0
的字符串向左旋转一个字母的子程序。立即,您应该考虑某种循环,它迭代字符串中的每个字母:

for int index from 0 to 12
    copy letter from (index + 1) to index
但是等等:第一个字母怎么了?它会被击倒的。当我们到达终点时会发生什么?我们将把
String
范围之外的内容复制到最后一个字母槽。因此,让我们通过将第一个字母存储到临时寄存器来解决这个问题:

temp = letter[0]

for int index from 0 to 11
    copy letter from (index + 1) to index

letter[12] = temp
那更好;应该这样做。下一个问题:我们如何在MIPS中做到这一点

我们知道,
$a0
将保存字符串的地址,因此我们认为这是理所当然的。我们至少需要一个临时寄存器——因为我们已经在为
x
使用
$t0
,让我们使用
$t1
来保存第一个字母:

MoveString:
lb $t1, String
我们还需要一个索引寄存器,所以让我们使用
$t2
来实现这一点。将其初始化为零:

li $t2, 0
最好只为每个字母增加一次地址寄存器,但我们不想重复
$a0
,因为它会弄乱
PrintString
。因此,让我们将其复制到循环的
$a1

move $a1, $a0
最后,我们需要知道字符串的长度,因此让我们将另一份
x
加载到
$t3

lb $t3, x
sub $t3, $t3, 1               ; We're only iterating over the first 12 letters,
                              ; since the last letter is done manually with temp
现在我们可以开始循环了。我们需要将字母(仅为一个字节)从
$a1+1
复制到
$a1

MoveStringLoop:
lb $t4, 1($a1)                  ; Load the letter from (address + 1)
sb $t4, 0($a1)                  ; Store it to (address)
add $a1, $a1, 1                 ; Increment our address
add $t2, $t2, 1                 ; Increment our index
blt $t2, $t3, MoveStringLoop    ; Loop again if index < (length - 1)

sb $t1, 0($a1)                  ; Copy the temp letter to the end of the string
无论如何,这不是一个最优的解决方案;我相信一个真正的编译器和一些更好的编码可以在一半的指令中完成这项工作。但既然您正在学习如何编写汇编,现在就不用担心微优化了。以下是最终代码及其输出:

    .data
String:    .asciiz "Hello, world.\n"
x:         .word 13

    .text 
Main:       lw $t0,x
            jal PrintString
            li $v0, 10
            syscall

PrintString:    la $a0,String
                li $v0,4
                syscall
                bgtz $t0, MoveString
                jr $ra

MoveString:
                lb $t1, String
                li $t2, 0
                move $a1, $a0
                lb $t3, x
                sub $t3, $t3, 1

MoveStringLoop:
                    lb $t4, 1($a1)
                    sb $t4, 0($a1)
                    add $a1, $a1, 1
                    add $t2, $t2, 1
                    blt $t2, $t3, MoveStringLoop

                sb $t1, 0($a1)

                sub $t0, $t0, 1
                b PrintString
输出:

Hello, world.
ello, world.H
llo, world.He
lo, world.Hel
o, world.Hell
, world.Hello
 world.Hello,
world.Hello,
orld.Hello, w
rld.Hello, wo
ld.Hello, wor
d.Hello, worl
.Hello, world
Hello, world.

这正是我要找的。非常感谢!这正是我要找的。非常感谢!