5.7 Ciclo de la instrucción

El ciclo de la instrucción es la secuencia de pasos que realiza la Unidad de Control (UC) para ejecutar cada instrucción de un programa. Este proceso es fundamental para el funcionamiento de cualquier computadora, ya que involucra elementos clave como registros, buses de datos, direcciones y señales de control generadas por la UC.

Las microoperaciones que conforman el ciclo de instrucción se describen utilizando la notación de transferencia entre registros: destino \(\leftarrow\) origen.

La Figura 5.23 esquematiza el flujo general del ciclo de instrucción en VonSim8, distinguiendo claramente las dos etapas fundamentales: captación (Fetch) y ejecución (Execute). Esta representación visual facilita la comprensión de la secuencia lógica y la interacción entre componentes durante la ejecución de cada instrucción, aportando claridad didáctica al análisis del funcionamiento interno del procesador.

Flujo del ciclo de instrucción en VonSim8

Figura 5.23: Flujo del ciclo de instrucción en VonSim8

5.7.1 Etapa 1: Captación

Esta etapa es igual para todas las instrucciones. Su objetivo es leer la instrucción desde la memoria y cargarla en el Registro de Instrucciones (IR). Consta de tres microoperaciones:

  1. MAR \(\leftarrow\) IP La UC transfiere al Registro de Direcciones de Memoria (MAR) la dirección de la próxima instrucción, almacenada en el Puntero de Instrucción (IP) .

  2. MBR \(\leftarrow\) read(Memoria[MAR]) |4 IP \(\leftarrow\) IP + 1 La UC activa la señal de lectura para leer la instrucción ubicada en la dirección contenida en el MAR. El valor leído se guarda en el Registro de Datos de Memoria (MBR) y, al mismo tiempo, el IP se incrementa para apuntar a la siguiente instrucción u operando.

  3. IR \(\leftarrow\) MBR El contenido del MBR se transfiere al IR, dejando la instrucción lista para ser decodificada y ejecutada.

5.7.2 Etapa 2: Ejecución

En esta etapa, el decodificador de instrucciones interpreta el valor en el registro IR. A partir del código de operación, lee las microinstrucciones necesarias en la memoria de control para determinar el tipo de instrucción, la cantidad de operandos y el modo de direccionamiento.

Luego, estas microinstrucciones se envían a secuenciador, que genera las señales de control precisas para ejecutar la operación.

A continuación se detallan las instrucciones más comunes:

5.7.2.1 Instrucciones con dos operandos MOV, ADD, SUB y CMP:

  • Destino en registro (Rx)
    • Modo entre registros (Rx, Ry)
      1. La ejecución se realiza en un solo paso:
        • MOV: Rx \(\leftarrow\) Ry
        • ADD: Rx \(\leftarrow\) Rx + Ry | update(Flags)
        • SUB: Rx \(\leftarrow\) Rx - Ry | update(Flags)
        • CMP: Rx - Ry | update(Flags) (solo actualiza flags, no guarda el resultado)
    • Modo directo (Rx, [Dirección])
      1. MAR \(\leftarrow\) IP – Obtener dirección del operando fuente.
      2. MBR \(\leftarrow\) read(Memoria[MAR]) | IP \(\leftarrow\) IP + 1 – Leer la dirección desde memoria e incrementar IP.
      3. MAR \(\leftarrow\) MBR – Transferir la dirección al MAR.
      4. MBR \(\leftarrow\) read(Memoria[MAR]) – Obtener el dato.
      5. Ejecutar la operación:
        • MOV: Rx \(\leftarrow\) MBR
        • ADD: Rx \(\leftarrow\) Rx + MBR | update(Flags)
        • SUB: Rx \(\leftarrow\) Rx - MBR | update(Flags)
        • CMP: Rx - MBR | update(Flags)
    • Modo inmediato (Rx, Dato)
      1. MAR \(\leftarrow\) IP – Obtener dirección del dato inmediato.
      2. MBR \(\leftarrow\) read(Memoria[MAR]) | IP \(\leftarrow\) IP + 1 – Leer el dato e incrementar IP.
      3. Ejecutar la operación (igual que en el caso anterior).
    • Modo indirecto (Rx, [BL])
      1. MAR \(\leftarrow\) BL – Obtener dirección del dato desde el registro BL.
      2. MBR \(\leftarrow\) read(Memoria[MAR]) – Leer el dato.
      3. Ejecutar la operación (igual que en el caso anterior).
  • Destino en memoria ([Dirección] o [BL]) En este caso, el resultado de la operación se almacena en una dirección de memoria especificada en la instrucción o indicada por el contenido del registro BL.
    • Modo Directo ([Dirección], Ry)
      1. MAR \(\leftarrow\) IP – Obtener dirección destino.
      2. MBR \(\leftarrow\) read(Memoria[MAR]) | IP \(\leftarrow\) IP + 1 – Leer la dirección e incrementar IP.
      3. MAR \(\leftarrow\) MBR – Transferir dirección a MAR. Según la instrucción:
      • MOV:
        1. MBR \(\leftarrow\) Ry – Copiar Ry al MBR.
        2. write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.
      • ADD, SUB, CMP:
        1. MBR \(\leftarrow\) read(Memoria[MAR]) – Leer el dato.
        2. Ejecutar la operación:
          • ADD: MBR \(\leftarrow\) MBR + Ry | update(Flags)
          • SUB: MBR \(\leftarrow\) MBR - Ry | update(Flags)
          • CMP: MBR - Ry | update(Flags)
        3. Si es ADD o SUB: write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.
    • Modo Indirecto ([BL], Ry)
      1. MAR \(\leftarrow\) BL – Transferir dirección de destino (en BL) a MAR. Según la instrucción:
      • MOV:
        1. MBR \(\leftarrow\) Ry – Copiar Ry al MBR.
        2. write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.
      • ADD, SUB, CMP:
        1. MBR \(\leftarrow\) read(Memoria[MAR]) – Leer el dato.
        2. Ejecutar la operación (igual que en el caso anterior).
        3. Si es ADD o SUB: write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.
    • Modo Directo-Inmediato ([Dirección], Dato)
      1. MAR \(\leftarrow\) IP – Obtener dirección destino.
      2. MBR \(\leftarrow\) read(Memoria[MAR]) | IP \(\leftarrow\) IP + 1 – Leer dirección e incrementar IP.
      3. MAR \(\leftarrow\) IP | ri \(\leftarrow\) MBR – Preparar para leer el dato y guardar la dirección destino en un registro intermedio (ri).
      4. MBR \(\leftarrow\) read(Memoria[MAR]) | IP \(\leftarrow\) IP + 1 – Leer dato e incrementar IP. Según la instrucción:
      • MOV:
        1. MAR \(\leftarrow\) ri – Copiar dirección destino.
        2. write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.
      • ADD, SUB, CMP:
        1. MAR \(\leftarrow\) ri | id \(\leftarrow\) MBR – Cargar dirección destino y guardar el valor inmediato en id.
        2. MBR \(\leftarrow\) read(Memoria[MAR]) – Leer el valor actual de destino.
        3. Ejecutar la operación:
          • ADD: MBR \(\leftarrow\) MBR + id | update(Flags)
          • SUB: MBR \(\leftarrow\) MBR - id | update(Flags)
          • CMP: MBR - id | update(Flags)
        4. Si es ADD o SUB: write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.
    • Modo Indirecto-Inmediato ([BL], Dato)
      1. MAR \(\leftarrow\) IP – Obtener dirección del dato inmediato.
      2. MBR \(\leftarrow\) read(Memoria[MAR]) | IP \(\leftarrow\) IP + 1 – Leer dato e incrementar IP. Según la instrucción:
      • MOV:
        1. MAR \(\leftarrow\) BL – Copiar dirección de destino.
        2. write(Memoria[MAR]) \(\leftarrow\) MBR
      • ADD, SUB, CMP:
        1. MAR \(\leftarrow\) BL | id \(\leftarrow\) MBR – Cargar la dirección destino y guardar el valor inmediato en id.
        2. MBR \(\leftarrow\) read(Memoria[MAR]) – Leer el valor actual de destino.
        3. Ejecutar la operación (igual que en el caso anterior).
        4. Si es ADD o SUB: write(Memoria[MAR]) \(\leftarrow\) MBR – Escribir en memoria.

5.7.2.2 Instrucciones con un operando JMP y Jxx:

  • Salto a (Dirección) Tanto incondicional JMP como condicionales Jxx tienen estos pasos:
    1. MAR \(\leftarrow\) IP – Obtener la dirección del salto.
    2. MBR \(\leftarrow\) read(Memoria[MAR]); IP \(\leftarrow\) IP + 1 – Leer la dirección de destino e incrementar IP.
    Según la instrucción:
    • JMP:
      1. IP \(\leftarrow\) MBR
    • Jxx:
      1. IP \(\leftarrow\) MBR si se cumple la condición del flag xx; en caso contrario, continúa con la siguiente instrucción.

5.7.2.3 Instrucciones sin operandos

  • HLT:
    1. Detiene la ejecución de la CPU.

Al contabilizar los pasos del ciclo RTL, cada paso equivale a un ciclo de CPU. La sección siguiente (5.7.3) describe cómo formaliza este conteo para definir CPI y tiempo de CPU.

5.7.3 Estadísticas de CPU en VonSim8

En VonSim8 cada “paso” del ciclo RTL equivale a 1 ciclo de CPU. De este modo, el CPI de cada instrucción se obtiene sumando 3 ciclos fijos de captación (pasos 1–3) más los pasos de ejecución propios del modo de direccionamiento. La notación “|” indica microoperaciones concurrentes dentro del mismo paso (no suma ciclos). Con frecuencia configurada f (Hz), el tiempo de CPU viene dado por T_CPU = ciclos_totales / f.

En consecuencia:

  • Cada paso equivale a 1 ciclo.
  • La etapa de captación aporta \(n_{fetch}=3\) ciclos (pasos 1–3).
  • La etapa de ejecución aporta \(n_{execute}\) ciclos según el modo de direccionamiento y la instrucción (pasos 4, 5, …).

Definiciones y fórmulas:

  • CPI por instrucción: \[CPI_{instr} = n_{fetch} + n_{execute}\]
  • Tiempo por instrucción (con frecuencia configurada \(f_{CPU}\) en Hz): \[t_{instr} = \frac{CPI_{instr}}{f_{CPU}}\]
  • Para un programa de \(N\) instrucciones ejecutadas: \[CPI_{prog} = \frac{\sum_{k=1}^{N} CPI_k}{N} \quad;\quad t_{CPU} = \frac{\sum_{k=1}^{N} CPI_k}{f_{CPU}}\]

Ejemplos (contabilizando pasos tal como se listan en esta sección):

  • MOV rx, ry (entre registros): \(n_{fetch}=3\), \(n_{execute}=1\) \(\implies\) \(CPI=4\) y \(t_{instr}=4/f_{CPU}\).

  • MOV Rx, [Dirección] (registro ← memoria directa): pasos 4–8 \(\implies\) \(n_{execute}=5\) \(\implies\) \(CPI=3+5=8\), \(t_{instr}=8/f_{CPU}\).

  • JMP Dirección: pasos 4–6 \(\implies\) \(n_{execute}=3\) \(\implies\) \(CPI=3+3=6\), \(t_{instr}=6/f_{CPU}\). En saltos condicionales Jxx solo se cuentan los pasos realmente ejecutados (si no se toma el salto, no se ejecuta la carga de IP).

Notas:

  • La frecuencia \(f_{CPU}\) es configurable (1–10 Hz), por lo que el tiempo por ciclo es \(T=1/f_{CPU}\).

  • Estas métricas son las que muestra el panel “Estadísticas CPU” del simulador (ciclos totales, CPI y tiempo de CPU).


  1. “|”: microoperaciones concurrentes en el mismo paso (no agregan ciclos).↩︎