Preguntas: Moisés E. Ramírez G. | UTM |

Inicialmente las computadoras sólo procesaban números, sin embargo en la medida en que llegaron a estar comercialmente disponibles, se les utilizó para procesar texto. La mayoría de computadoras utilizan 8 bits para representar un carácter de acuerdo al código americano estándar para el intercambio de información (ASCII – American Standar Code for Information Interchange).

Un entero en MIPS utiliza 32 bits, que corresponde al tamaño de los registros, sin embargo utilizar 32 bits por carácter sería un desperdicio de memoria. Es por eso que además de las instrucciones para cargar y almacenar palabras, MIPS incluye instrucciones para cargar y almacenar bytes.

La instrucción lb (load byte) carga un byte desde la memoria colocándolo en los 8 bits mas a la derecha de un registro; y la instrucción sb (store byte) toma un byte de los 8 bits mas a la derecha de un registro y los coloca en la memoria.

Entonces, para copiar un byte de una localidad de memoria a otra se utilizaría:

   lb   $t0, 0 ($sp)       # Se lee el byte de la localidad fuente
   sb   $t0, 0($gp)      # Se escribe el byte en la localidad destino.

Los caracteres normalmente se combinan para crear cadenas, las cuales tienen un número variable de caracteres. Hay tres opciones para representar una cadena:

  1. La primera localidad de la cadena se reserva para que contenga la longitud de la misma,
  2. Una variable acompaña a la cadena para que contenga su longitud (como en una estructura), o
  3. La última posición de la cadena es indicada por un carácter especialmente utilizado para marcar el fin de la cadena.
El lenguaje C utiliza la última opción y reserva el byte con valor cero (carácter NULL en el código ASCII) para indicar el final de las cadenas.

Ejemplo: Compilando una función para cadenas. El procedimiento strcpy copia una cadena x en una cadena y usando el byte de terminación null :

    void strcpy ( char  x[ ], char   y[ ])
    {
        int i = 0;
        while( ( x[i] = y[i] ) !== 0 )        /* copia y prueba al byte */
             i = i + 1;
    }


Respuesta:
De acuerdo a la convención establecida, en $a0 está el comienzo del arreglo x y en $a1 está el comienzo del arreglo y. Para la variable i utilizaremos al registro $s0, que debe respaldarse en la pila antes de modificar su valor:

    strcpy:    
            sub    $sp, $sp, 4          # Hace espacio para un dato en la Pila
            sw    $s0, 0 ($sp)          # Salva a $s0

            add    $s0, $zero, $zero    # inicializa a i con cero

    L1:     add    $t1, $a1, $s0        # La dirección de y[i] esta en $t1
            add    $t2, $a0, $s0        # La dirección de x[i] esta en $t2

            lb    $t3, 0 ($t1)          # Obtiene un dato de y[i]
            sb    $t3, 0 ($t2)          # Lo copia en x[i]

            beq    $t3, $zero, L2       # Si el dato es NULL, sale del ciclo

            add    $s0, $s0, 1          # i = i + 1
            j    L1                     # otra iteración

    L2:     lw    $s0, 0 ($sp)        # Restaura el valor de $s0
            add    $sp, $sp, 4        # Ajusta al puntero de la Pila

            jr    $ra                 # Finaliza la rutina

En el ejemplo anterior, puesto que el procedimiento strcpy es un procedimiento aislado (que no invoca a otro procedimiento), su variable local (i) podría asociarse con un registro temporal, y con ello se evitaría el respaldo y restauración del registro $s0. En lo sucesivo, cuando encontremos procedimiento aislados, asociaremos sus variable locales con registros temporales.