MIPS - Удалить последовательные дубликаты из ввода - PullRequest
0 голосов
/ 29 марта 2020

Я пытаюсь преобразовать программу, написанную в java, в mips.

Программа просит пользователя ввести строку и удалить последовательные дубликаты. Например, если пользователь вводит «abbcddeffga», вывод будет «abcdefga».

В Java все работает нормально, но в MIPS я, вероятно, испортил что-то с регистрами или что-то еще, и Теперь я не знаю, как это исправить (я новичок ie в MIPS).

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);

    System.out.println("String? ");
    String s = in.nextLine();
    int length = s.length();
    String res = "";

    if(length == 1)
        System.out.println(s);

    else {
    for(int i = 1; i < length; i++)
        for(int j = i; j < length; j++) {
            if(s.charAt(i - 1) != s.charAt(j)) {
                if(i == length - 1) {
                    if(length == 2 || s.charAt(i - 1) != s.charAt(i - 2)) {
                        res+= s.charAt(i - 1);
                        res+= s.charAt(j);
                    }
                    else
                        res+= s.charAt(j);
                }
                else {
                    res += s.charAt(i - 1);
                    if(j == length - 1)
                        i = j - 1;
                    else
                        i = j;
                    break;
                }
            }
            else
                if(i == length - 1)
                    res+= s.charAt(i - 1);
        }
    System.out.println(res);    
    }
}

Попытка MIPS:

.data
    string1: .asciiz "String? "
    input: .space 256
    newLine: .asciiz "\n"
    result: .space 256

.text

main:

        li $v0, 4    # print string1
        la $a0, string1
        syscall

        li $v0, 8        # read input
        la $a0, input
        li $a1, 255
        syscall

        li $t0, 0     #loop counter (length)
        lb $t2, newLine

   loop:
        lb $t1, ($a0) # load the content of the address stored in $a0 
        beq $t1, $t2, continue
        addi $t0, $t0, 1 # increment the loop counter
        addi $a0, $a0, 1 # go to next byte      
        j loop


   continue:   
        addi $t1, $zero, 0
        addi $a0, $zero, 0 
        bne $t0, 1, else0 # if length != 1, jump to else0

        li $v0, 4
        la $a0, input
        syscall 

   else0:
        li $t1, 1            #i = 1
        addi $t6, $t0, -1    # length - 1
        addi $t7, $t1, -2    # i - 2
        addi $t9, $t1, -1    # i - 1
     for_loop:
        bge $t1, $t0 print

     for_loop2:
        move $t3, $t1        # j = i
        addi $t8, $t3, -1    #j - 1
        bge $t3, $t0 increment_i

        add $a0, $zero, $t9    # s.charAt(i - 1)
        lb $s1, ($a0)
        addi $s0, $zero, 0

        add $s0, $zero, $t3    # s.charAt(j)
        lb $s2, ($a0)
        addi $s0, $zero, 0

        beq $s1, $s2, else1    # if s.charAt(i - 1) == s.charAt(j), jump to else1
        bne $t1, $t6, else2    # if i != length - 1

        add $s0, $zero, $t7    # s.charAt(i - 2)
        lb  $s3, ($a0)
        addi $a0, $zero, 0

        beq $t0, 2, continue2       # if length == 2 
        beq $s1, $s3, else3         #if s.charAt(i - 1) == s.charAt(i - 2), jump to else3

 continue2:       
        sb $s1, result($s4)  # res += s.charAt(i - 1)
        addi $s4, $s4, 1        
        sb $s2, result($s4)  #  res += s.charAt(j)
        addi $s4, $s4, 1
        j print

   else3:
        sb $s2, result($s4)  # res += s.charAt(j)
        addi $s4, $s4, 1
        j print

   else2:
        sb $s1, result($s4)  # res = s.charAt(i - 1)
        addi $s4, $s4, 1    
        bne $t3, $t6, else4
        move $t1, $t8
        addi $t1, $t1, 1
        j for_loop
   else4:
        move $t1, $t3
        addi $t1, $t1, 1
        j for_loop

   else1:
        bne $t1, $t6, increment_j
        sb $s1, result($s4)  # res = s.charAt(i - 1)
        addi $s4, $s4, 1 
        j print 
      increment_j:
          addi $t3, $t3, 1
          j for_loop2
      increment_i:
          addi $t1, $t1, 1
          j for_loop

   print:
        move $t4, $s4
        addi $s4, $zero, 0
      loop2:
        beq $s4, $t4, exit
        li $v0, 11
        la  $a0, result($s4)
        syscall
        addi $s4, $s4, 1
        j loop2   


exit:
        li $v0, 10
        syscall 

Ответы [ 2 ]

0 голосов
/ 29 марта 2020

Только для записи, ваш алгоритм и реализация массово чрезмерно усложнены.

Все, что вам нужно, - это регистр для запоминания того, какой символ ввода вы видели последним, и указатели ввода / вывода (также в регистрах). Внутренний l oop находит следующий новый символ, внешний l oop сохраняет его и увеличивает выходной указатель.

Я не понял, почему ваша реализация такая огромная путаница (это не так обзор кода), но мне было любопытно, насколько просто это можно было сделать. Вот что я придумал:

.data
    input:  .asciiz "abbcddeffga\n"
    result: .ascii "XXXXXXXXXXXXXXXXXXXXX"    # poison to detect failure to store a \0
            .space 256

.text
_start:
        la      $t0, result     
        la      $t1, input    # read stdin if you want

        li      $t2, -1       # previous char: c = -1  (not equal to any possible unsigned byte value)
.outer:                         # do {
.uniq:                             # do {
        lbu     $t4, ($t1)            # c = *in++
        addiu   $t1, $t1, 1
        beq     $t4, $t2, .uniq    # }while(c == prev) find next new character

        move    $t2, $t4           # prev = c
        sb      $t4, ($t0)
        addiu   $t0, $t0, 1        # *out++ = c
        bnez    $t4, .outer     # }while(c != 0)  // note that 0 terminator is stored first

        la      $a0, result
        li      $v0, 4
        syscall                 # print_string(result)
exit:
        li    $v0, 10
        syscall

Я проверил это в MARS, и оно работает для этой входной строки. Он также работает правильно для пустой строки, обрабатывая этот угловой регистр, не читая входные данные за этим байтом, и сохраняя завершающий 0 на выходе. (Инициализация $ t2 = prev с помощью -1 делает эту работу: lbu никогда не может произвести -1, поэтому мы гарантируем, что на первой итерации нет ложноположительных совпадений prev.)

Завершающий 0 всегда будет новым уникальным символом, поэтому нам не нужно специально его хранить, просто позвольте обычному l oop сохранить его.

Я упростил еще больше, используя жесткий входная строка Код для запроса и чтения строкового ввода не имеет отношения к реальному алгоритму. Добавление этого значения обратно будет ортогональным к функциональности uniq(result, input).

Кроме того, MARS имеет системный вызов print_string , поэтому я использовал его вместо зацикливания вручную над print_character. Выходная строка заканчивается 0, поэтому мы можем безопасно использовать этот системный вызов.

0 голосов
/ 29 марта 2020

Хорошо, мне удалось решить проблемы, я выкладываю правильную версию, так что, возможно, кто-то найдет ее полезной в будущем.

.data
    string1: .asciiz "String? "
    input: .space 256
    newLine: .asciiz "\n"
    result: .space 256

.text

main:

        li $v0, 4    # print string1
        la $a0, string1
        syscall

        li $v0, 8        # read input
        la $a0, input
        li $a1, 255
        syscall

        li $t0, 0     #loop counter (length)
        lb $t2, newLine

   loop:
        lb $t1, ($a0) # load the content of the address stored in $a0 
        beq $t1, $t2, continue
        addi $t0, $t0, 1 # increment the loop counter
        addi $a0, $a0, 1 # go to next byte      
        j loop


   continue:   
        addi $t1, $zero, 0
        addi $a0, $zero, 0 
        bne $t0, 1, else0 # if length != 1, jump to else0

        li $v0, 4
        la $a0, input
        syscall 

   else0:
        li $t1, 1            #i = 1
        addi $t6, $t0, -1    # length - 1
     for_loop:
        bge $t1, $t0 print
        addi $t7, $t1, -2    # i - 2
        addi $t9, $t1, -1    # i - 1
        move $t3, $t1        # j = i
     for_loop2:
        addi $t8, $t3, -1    #j - 1
        bge $t3, $t0 increment_i

        add $a0, $zero, $t9    # s.charAt(i - 1)
        lb $s1, input($a0)
        addi $a0, $zero, 0

        add $a0, $zero, $t3    # s.charAt(j)
        lb $s2, input($a0)
        addi $a0, $zero, 0

        beq $s1, $s2, else1    # if s.charAt(i - 1) == s.charAt(j), jump to else1
        bne $t1, $t6, else2    # if i != length - 1, jump to else2

        add $a0, $zero, $t7    # s.charAt(i - 2)
        lb  $s3, input($a0)
        addi $a0, $zero, 0

        beq $t0, 2, continue2       # if length == 2 
        beq $s1, $s3, else3         #if s.charAt(i - 1) == s.charAt(i - 2), jump to else3

 continue2:       
        sb $s1, result($s4)  # res += s.charAt(i - 1)
        addi $s4, $s4, 1        
        sb $s2, result($s4)  #  res += s.charAt(j)
        addi $s4, $s4, 1
        j print

   else3:
        sb $s2, result($s4)  # res += s.charAt(j)
        addi $s4, $s4, 1
        j print

   else2:
        sb $s1, result($s4)  # res = s.charAt(i - 1)
        addi $s4, $s4, 1    
        bne $t3, $t6, else4 # if j != length - 1 
        move $t1, $t8       # i = j - 1
        addi $t1, $t1, 1
        j for_loop
   else4:
        move $t1, $t3
        addi $t1, $t1, 1
        j for_loop

   else1:
        bne $t1, $t6, increment_j   # if i != length - 1
        sb $s1, result($s4)  # res = s.charAt(i - 1)
        addi $s4, $s4, 1 
        j print 
      increment_j:
          addi $t3, $t3, 1
          j for_loop2
      increment_i:
          addi $t1, $t1, 1
          j for_loop

   print:
       li $v0, 4
       la $a0, result
       syscall


exit:
        li $v0, 10
        syscall
...