Saltar al contenido principal
LibreTexts Español

2.5: Diseñar un lenguaje ensamblador

  • Page ID
    80641
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Al diseñar un lenguaje ensamblador, un lenguaje para manipular una CPU, hay 3 preocupaciones principales:

    1. Transferencia de datos de la memoria principal a la memoria interna a la CPU (registros o pila de operando).
    2. El conjunto de operaciones que puede realizar la ALU sobre los datos, por ejemplo sumar, restar y, desplazar, etcétera.
    3. Una forma de proporcionar control de programa, por ejemplo para implementar estructuras de tipo branch (if) y loops (for or while) en un programa. Normalmente la estructura de control será proporcionada por una operación de sucursal.

    Estas tres grandes preocupaciones, y cómo se abordan en el lenguaje ensamblador, serán discutidas en las siguientes secciones. En la última sección de este capítulo se darán algunos programas que ilustrarán cómo se escribirá un programa en este lenguaje ensamblador.

    2.5.1 Transferencia de datos de la memoria principal a la memoria interna de la CPU

    La cantidad de memoria directamente accesible a un programador en la CPU (por ejemplo, registros) es muy limitada. En el caso de la arquitectura de una dirección, solo una ranura de memoria, la $ac, es directamente utilizada por un programador. Por lo tanto, los programas necesitan depender de la memoria principal para almacenar instrucciones y datos del programa.

    Para transferir elementos de la memoria de datos al $ac se utilizan las instrucciones add, sub y stor.

    Para las instrucciones add y sub, el segundo operando de la instrucción es la etiqueta o dirección de memoria del valor a recuperar de la memoria y enviado a la ALU. Entonces, por ejemplo, para cargar un valor en el $ac desde una ubicación de memoria etiquetada A se usaría el siguiente código.

    clac
    add A
    

    Tenga en cuenta que el $ac siempre debe establecerse en 0 (usando el clac) antes de cargar un valor en el $ac, o el valor almacenado en el $ac será el resultado de agregar el valor en la ubicación de memoria A con el valor actual en el $ac.

    Para la instrucción stor, el segundo operando es la etiqueta o dirección de memoria en la que stor el valor del $ac. Por ejemplo, para almacenar el valor en el $ac a la memoria en la dirección en la etiqueta B, se usaría el siguiente código.

    stor B
    

    2.5.2 Conjunto de operaciones ALU válidas

    La siguiente consideración es el conjunto de operaciones que la ALU puede realizar sobre los datos de entrada. Esta lista depende de la complejidad de la ALU. El ALU en esta computadora es muy sencillo, y así solo apoyará las operaciones add y sub.

    2.5.3 Control de programas (ramificación)

    Para hacer cualquier programa útil, se deben soportar las construcciones if y loop. En la CPU de una dirección implementada esto se logra mediante la operación Branch-IF-Equal-Zero (beqz). Para esta operación, si el $ac es 0, el programa se ramificará a la dirección de memoria de texto que está contenida en la sentencia branch. Esta dirección puede ser una etiqueta que represente la dirección, o el valor numérico de la dirección de sucursal. Entonces en la siguiente instrucción, el programa se ramificará a la dirección de la etiqueta EndLoop si el valor en el $ac es 0.

    beqz EndLoop
    

    A menudo se usa una sentencia branch incondicional, pero se puede simular configurando primero el $ac en 0 antes de la sentencia branch. La siguiente instrucción implementa una rama incondicional.

     clac
     beqz StartLoop
    

    2.5.4 Instrucciones del ensamblador

    Con base en los criterios de la sección anterior, se define un conjunto mínimo de instrucciones de ensamblador para crear programas útiles. Estas instrucciones son suficientes para crear programas útiles, y al final de este capítulo se mostrarán varios ejemplos.

    • En esta instrucción se puede utilizar una etiqueta o la dirección real del valor. Así, si la etiqueta A hace referencia a la dirección dm de 5, las siguientes dos instrucciones son las mismas.
      add A 
      add 5
      
    • addi immediate - Agrega el valor inmediato en esta instrucción al $ac. El valor inmediato es un valor entero de 8 bits entre -128... 127
      $ac <- $ac + immediate
      

      A continuación se muestra un ejemplo de una instrucción addi que agrega 15 al valor en el $ac.

      addi 15
      
    • beqz [etiqueta/dirección] — La instrucción beqz cambia el valor en el Contador de Programas ($pc) a la dirección de memoria de texto en la instrucción si el valor en el $ac es 0. En esta CPU, el $pc siempre especifica la siguiente instrucción a ejecutar, por lo que esto tiene el efecto de cambiar la siguiente instrucción a ejecutar a la dirección en la instrucción. Esto se llama rama de programa, o simplemente rama.
      $pc <- address IF $ac is 0
      

      A continuación se muestra un ejemplo de la instrucción beqz que se bifurca a la dirección 16 si el $ac es 0:

      beqz 16
      
    • clac — La instrucción clac establece el $ac en 0. Esto podría hacerse con un conjunto de operaciones stor y sub, por lo que la instrucción es principalmente por conveniencia.
      $ac <- 0
      
    • sub [etiqueta/dirección] - Restar un valor de la memoria de datos a la corriente $ac.
      $ac <- $ac - dm[address]
      

      En esta instrucción se puede utilizar una etiqueta o la dirección real del valor. Así, si la etiqueta A hace referencia a la dirección dm de 5, las siguientes dos instrucciones son las mismas.

      sub A
      sub 5
      
    • subi inmediato - Sub el valor inmediato en esta instrucción a los $ac. El valor inmediato es un valor entero de 8 bits entre -128... 128.
      $ac <- $ac - immediate
      

      A continuación se muestra un ejemplo de una instrucción subi que suma 15 al valor en $ac.

      subi 15
      
    • stor [etiqueta/dirección] — Almacena el valor actual en el $ ac a la memoria de datos.
      dm[address] <- $ac
      

      En esta instrucción se puede utilizar una etiqueta o la dirección real del valor. Así, si la etiqueta A hace referencia a la dirección dm de 5, las siguientes dos instrucciones son las mismas.

      stor A
      stor 5
      
    • noop — esta afirmación no hace nada. Al ejecutar esta sentencia no se cambia el valor de ninguna memoria o registros (excepto el $pc) en el sistema. Se incluye para que la memoria de texto pueda establecerse en 0 y ejecutarse sin cambiar el estado interno de la computadora.

    This page titled 2.5: Diseñar un lenguaje ensamblador is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Charles W. Kann III via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.