Data General Nova es una serie de minicomputadoras de 16 bits lanzadas al mercado por la empresa estadounidense Data General . La familia Nova fue muy popular en la década de 1970 y llegó a vender decenas de miles de unidades.
El primer modelo, conocido simplemente como "Nova", se lanzó en 1969. [1] El Nova estaba empaquetado en una única carcasa de montaje en bastidor de 3U y tenía suficiente potencia informática para manejar la mayoría de las tareas sencillas. El Nova se hizo popular en los laboratorios científicos de todo el mundo. Al año siguiente le siguió el SuperNOVA , que funcionaba aproximadamente cuatro veces más rápido, lo que lo convirtió en el mini más rápido durante varios años.
Introducida durante un período de rápido progreso en el diseño de circuitos integrados (o "microchip"), la línea pasó por varias actualizaciones durante los siguientes cinco años, introduciendo el 800 y el 1200, el Nova 2, el Nova 3 y, finalmente, el Nova 4. También se presentó una implementación de un solo chip como microNOVA en 1977, pero no tuvo un uso generalizado ya que el mercado se movió hacia nuevos diseños de microprocesadores. Fairchild Semiconductor también presentó una versión de microprocesador del Nova en 1977, el Fairchild 9440 , pero también tuvo un uso limitado en el mercado.
La línea Nova fue reemplazada por la serie Eclipse de Data General , que era similar en la mayoría de los aspectos pero que agregó compatibilidad con memoria virtual y otras funciones requeridas por los sistemas operativos modernos . Una actualización de 32 bits de la serie Eclipse dio como resultado la serie Eclipse MV de la década de 1980.
Edson de Castro fue el gerente de producto de la pionera PDP-8 de Digital Equipment Corporation (DEC) , una computadora de 12 bits ampliamente conocida como la primera minicomputadora verdadera. [2] También dirigió el diseño de la PDP-8/I mejorada, que utilizó circuitos integrados tempranos en lugar de transistores individuales. [3]
Durante el proceso de fabricación del PDP-8/I, de Castro había estado visitando a fabricantes de placas de circuitos que estaban haciendo rápidos avances en la complejidad de las placas que podían ensamblar. De Castro concluyó que el 8/I podría producirse utilizando un ensamblaje totalmente automatizado en placas grandes, lo que habría sido imposible solo un año antes. Otros dentro de DEC se habían acostumbrado a las placas más pequeñas utilizadas en las máquinas anteriores y estaban preocupados por rastrear los problemas cuando había muchos componentes en una sola placa. [a] Para el 8/I, se tomó la decisión de quedarse con placas pequeñas, utilizando el nuevo encapsulado de " chip invertido " para una modesta mejora en la densidad. [3]
Durante el período en el que se estaba desarrollando el PDP-8, la introducción del ASCII y su importante actualización en 1967 condujeron a una nueva generación de diseños con longitudes de palabra que eran múltiplos de 8 bits en lugar de múltiplos de 6 bits como en la mayoría de los diseños anteriores. Esto llevó a diseños de gama media que trabajaban con longitudes de palabra de 16 bits en lugar de las líneas actuales de 12 y 18 bits de DEC. De Castro estaba convencido de que era posible mejorar el PDP-8 construyendo una CPU de minicomputadora de 16 bits en una única placa cuadrada de 15 pulgadas. [4] [5]
En 1967, de Castro comenzó un nuevo proyecto de diseño conocido como "PDP-X", que incluía varias características avanzadas. Entre ellas, se encontraba un único diseño subyacente que podía utilizarse para construir plataformas de 8, 16 y 32 bits. [6] Esto progresó hasta el punto de producir varios documentos detallados de arquitectura. Ken Olsen no apoyó este proyecto, ya que sentía que no ofrecía suficientes ventajas sobre el PDP-8 de 12 bits y el PDP-9 de 18 bits . Finalmente, se canceló en la primavera de 1968. [4]
La cancelación del PDP-X impulsó a De Castro a considerar la posibilidad de abandonar DEC para construir un sistema por su cuenta. No estaba solo; a finales de 1967, se formó un grupo de ingenieros con ideas afines para considerar la posibilidad de construir una máquina de este tipo. El grupo incluía a Pat Green, un gerente de división; Richard Sogge, otro ingeniero de hardware; y Henry Burkhardt III, un ingeniero de software. [7] A diferencia del PDP-X, el nuevo esfuerzo se centró en una única máquina que pudiera sacarse al mercado rápidamente, ya que De Castro sentía que el concepto del PDP-X era demasiado ambicioso para una pequeña empresa emergente . [8]
Tras discutirlo con los demás en DEC, el concepto inicial condujo a una máquina de 8 bits que sería menos costosa de implementar. [9] El grupo comenzó a hablar con Herbert Richman, un vendedor de Fairchild Semiconductor que conocía a los demás a través de sus contactos con DEC. En ese momento, Fairchild estaba luchando con Texas Instruments y Signetics en el mercado de TTL en rápido crecimiento y estaban introduciendo nuevas fábricas que permitían diseños más complejos. La última serie 9300 de Fairchild permitía hasta 96 puertas por chip, y la habían utilizado para implementar una serie de chips de 4 bits como contadores binarios y registros de desplazamiento . [10]
El uso de estos circuitos integrados redujo el número total de circuitos integrados necesarios para implementar una unidad lógica aritmética (ALU) completa, el componente matemático central de una CPU, lo que permitió la expansión de un diseño de 8 bits a uno de 16 bits. Esto requirió la expansión de la CPU de una única placa de circuito impreso de 15 x 15 pulgadas (38 cm × 38 cm) a dos, pero un diseño de este tipo seguiría siendo significativamente más barato de producir que el 8/I, al tiempo que seguiría siendo más potente y basado en ASCII. Una tercera placa albergaba los circuitos de entrada/salida y un sistema completo normalmente incluía otra placa con 4 kB de memoria de acceso aleatorio . Un sistema completo de cuatro tarjetas cabía en un único chasis de montaje en bastidor. [5]
Las placas se diseñaron de manera que pudieran conectarse entre sí mediante una placa base de circuito impreso , con un cableado manual mínimo, lo que permitió que todas las placas se construyeran de manera automatizada. Esto redujo enormemente los costos con respecto a 8/I, que consistía en muchas placas más pequeñas que debían conectarse entre sí en la placa base, que a su vez estaba conectada entre sí mediante envoltura de cable . La construcción de placas más grandes también hizo que el Nova fuera más confiable, lo que lo hizo especialmente atractivo para entornos industriales o de laboratorio. [5]
El nuevo diseño utilizó una arquitectura de carga y almacenamiento simple [4] que resurgiría en los diseños RISC en la década de 1980. Debido a que la complejidad de un flip-flop se estaba reduciendo rápidamente a medida que se implementaban en chips, el diseño compensó la falta de modos de direccionamiento del diseño de carga y almacenamiento agregando cuatro acumuladores de propósito general , en lugar del registro único que se encontraría en ofertas similares de bajo costo como la serie PDP. [4]
A finales de 1967, Richman presentó al grupo al abogado Fred Adler, que tenía su base en Nueva York, quien comenzó a buscar varias fuentes de financiación para conseguir capital inicial. En 1968, Adler había cerrado un importante acuerdo de financiación con un consorcio de fondos de capital de riesgo del área de Boston, que accedieron a proporcionar una inversión inicial de 400.000 dólares estadounidenses y una segunda cantidad de 400.000 dólares estadounidenses disponible para aumentar la producción. De Castro, Burkhart y Sogge abandonaron DEC y fundaron Data General (DG) el 15 de abril de 1968. Green no se unió a ellos, ya que consideraba que la empresa era demasiado arriesgada, y Richman no se unió hasta que el producto estuvo en funcionamiento más tarde ese mismo año. [5]
El trabajo en el primer sistema llevó alrededor de nueve meses, y los primeros esfuerzos de ventas comenzaron ese noviembre. Tuvieron un poco de suerte porque la Conferencia Conjunta de Computadoras de Otoño se había retrasado hasta diciembre de ese año, por lo que pudieron traer una unidad funcional a San Francisco, donde ejecutaron una versión de Spacewar!. [ 11] DG lanzó oficialmente el Nova en 1969 a un precio base de US$3.995 (equivalente a US$33.193 en 2023), publicitándolo como "el mejor ordenador pequeño del mundo". [12] El modelo básico no era muy útil de fábrica, y agregarle8kW (16 kB ) de RAM en forma de memoria central normalmente elevaba el precio a US$7.995 . [13] En contraste, un 8/I con4kW (6 kB ) tenía un precio de 12.800 dólares estadounidenses . [14]
La primera venta se realizó a una universidad de Texas, y el equipo fabricó a mano un ejemplar que se envió en febrero. Sin embargo, esto se produjo en medio de una huelga en la industria aérea y la máquina nunca llegó. Enviaron un segundo ejemplar, que llegó rápidamente porque la huelga ya había terminado, y en mayo finalmente se entregó también el original. [15]
El sistema tuvo éxito desde el principio: el modelo número 100 se vendió después de seis meses [16] y el número 500 después de 15 meses [13] . Las ventas se aceleraron a medida que se introdujeron nuevas versiones y en 1975 la empresa tenía ventas anuales de 100 millones de dólares [17] .
Ken Olsen había predicho públicamente que DG fracasaría, pero con el lanzamiento del Nova quedó claro que eso no iba a suceder. En ese momento, varias otras compañías también estaban hablando de introducir diseños de 16 bits. Olsen decidió que estos presentaban una amenaza para su línea de 18 bits, así como para la de 12 bits, y comenzó un nuevo esfuerzo de diseño de 16 bits. [18] Esto surgió en 1970 como el PDP-11 , un diseño mucho más complejo que era tan diferente del PDP-X como lo era el Nova. Los dos diseños compitieron fuertemente en el mercado. [4]
Los rumores sobre el nuevo sistema de DEC llegaron a DG poco después de que Nova comenzara a comercializarse. En la primavera de 1970 contrataron a un nuevo diseñador, Larry Seligman, para que adelantara cualquier posible máquina que se estuviera construyendo. Se habían producido dos cambios importantes desde que se diseñó Nova: uno fue que Signetics había introducido el 8260, un CI de 4 bits que combinaba un sumador, XNOR y AND, lo que significaba que la cantidad de chips necesarios para implementar la lógica básica se reducía aproximadamente tres veces. Otro fue que Intel estaba promocionando agresivamente las memorias basadas en semiconductores, prometiendo 1024 bits en un solo chip y funcionando a velocidades mucho más altas que la memoria central. [18]
El nuevo diseño de Seligman aprovechó ambas mejoras. Para empezar, los nuevos circuitos integrados permitieron que la ALU se ampliara a un ancho de banda completo de 16 bits en las mismas dos tarjetas, lo que le permitió realizar operaciones matemáticas y lógicas en un solo ciclo y, por lo tanto, hizo que el nuevo diseño fuera cuatro veces más rápido que el original. Además, se utilizó una nueva memoria de núcleo más pequeña que mejoró el tiempo de ciclo de los 1200 ns del original a 800 ns, lo que ofrece una mayor velocidad de procesamiento.1/3 Mejora. El rendimiento podría mejorarse aún más reemplazando el núcleo con memoria de solo lectura ; al carecer del ciclo de lectura y escritura del núcleo, se podría acceder a esta en 300 ns para un aumento espectacular del rendimiento. [16]
La máquina resultante, conocida como SuperNOVA , se lanzó en 1970. Aunque los modelos iniciales todavía usaban núcleo, todo el diseño se basó en la premisa de que estarían disponibles memorias de semiconductores más rápidas y la plataforma podría hacer un uso completo de ellas. Esta se introdujo más tarde el mismo año como SuperNOVA SC , con memoria de semiconductores (SC). La memoria de rendimiento mucho mayor permitió que la CPU, que estaba sincronizada con la memoria, aumentara aún más la velocidad para funcionar a un tiempo de ciclo de 300 ns (3,3 MHz). Esto la convirtió en la minicomputadora más rápida disponible durante muchos años. [19] Inicialmente, la nueva memoria también era muy cara y se calentaba, por lo que no se usó ampliamente. [20]
Como demostración del poder de su tecnología de matriz de puertas Micromatrix , en 1968 Fairchild diseñó el prototipo 4711, una ALU de 4 bits de un solo chip. [10] [21] El diseño nunca estuvo pensado para la producción en masa y era bastante costoso de producir. La introducción del Signetics 8260 en 1969 los obligó a hacerlo; tanto Texas Instruments como Fairchild introdujeron sus propias ALU de 4 bits en 1970, la 74181 y la 9341, respectivamente. A diferencia del 8260, los nuevos diseños ofrecían todas las funciones lógicas comunes y reducían aún más el número de chips. [10]
Esto llevó a DG a considerar el diseño de una nueva CPU que utilizara estos circuitos integrados más integrados. Como mínimo, esto reduciría la CPU a una sola tarjeta, ya sea para el Nova básico o para el SuperNOVA. Surgió un nuevo concepto en el que un solo chasis podría albergar cualquiera de las dos máquinas simplemente intercambiando la placa de circuito de la CPU. Esto permitiría a los clientes comprar el sistema de menor costo y luego actualizarlo en cualquier momento. [22]
Mientras Seligman trabajaba en la SuperNOVA, la empresa recibió una carta de Ron Gruner en la que decía: "He leído sobre su producto, he leído sus anuncios y voy a trabajar para usted. Y estaré en sus oficinas en una semana para hablar con usted sobre eso". [22] Fue contratado en el acto. Gruner quedó a cargo de la máquina de bajo costo mientras Seligman diseñaba una versión de alto rendimiento similar. [22]
El modelo de bajo costo de Gruner se lanzó en 1970 como Nova 1200 , el 1200 se refería al uso de la memoria central de 1200 ns del Nova original. Presentaba una ALU de 4 bits basada en un solo chip 74181 y, por lo tanto, era esencialmente un Nova reempaquetado. El SuperNOVA de cuatro ALU reempaquetado de Seligman se lanzó en 1971 como Nova 800 , lo que resultó en un nombre algo confuso donde el modelo de número más bajo tiene un mayor rendimiento. [22] Ambos modelos se ofrecieron en una variedad de casos, el 1200 con siete ranuras, el 1210 con cuatro y el 1220 con catorce.
En ese momento, el PDP-11 finalmente estaba a la venta. Ofrecía una arquitectura de conjunto de instrucciones mucho más rica que la deliberadamente simple del Nova. La mejora continua en los diseños de circuitos integrados, y especialmente su relación precio-rendimiento , estaba erosionando el valor de las instrucciones simplificadas originales. Seligman fue puesto a cargo del diseño de una nueva máquina que fuera compatible con el Nova y que al mismo tiempo ofreciera un entorno mucho más rico para aquellos que lo quisieran. Este concepto se envió como la serie Eclipse de Data General , que ofrecía la capacidad de agregar circuitos adicionales para adaptar el conjunto de instrucciones a cargas de trabajo científicas o de procesamiento de datos. El Eclipse tuvo éxito al competir con el PDP-11 en el extremo superior del mercado. [23]
Casi al mismo tiempo, empezaron a surgir rumores sobre una nueva máquina de 32 bits de DEC. DG decidió que tenían que tener un producto similar y Gruner quedó a cargo de lo que se convirtió en el Proyecto Fountainhead. Dado el alcance del proyecto, acordaron que todo el esfuerzo debería manejarse fuera del sitio y Gruner eligió una ubicación en Research Triangle Park en Carolina del Norte . Este diseño se volvió muy complejo [24] y finalmente fue cancelado años después.
Mientras se realizaban estos esfuerzos, continuaban los trabajos en la línea Nova.
El 840, que se presentó por primera vez en 1973, también incluía un nuevo sistema de memoria paginada que permitía direcciones de hasta 17 bits. Un índice desplazaba la dirección base hacia la memoria más grande de 128 kword. En realidad, instalar tanta memoria requería un espacio considerable; el 840 se enviaba en una gran caja de 14 ranuras.
La siguiente versión fue la Nova 2 , cuyas primeras versiones se comercializaron en 1973. La Nova 2 era esencialmente una versión simplificada de las máquinas anteriores, ya que el aumento de la densidad de chips permitió reducir el tamaño de la CPU. Mientras que la SuperNOVA utilizaba tres placas de 15×15" para implementar la CPU y su memoria, la Nova 2 incluía todo esto en una única placa. La ROM se utilizaba para almacenar el código de arranque, que luego se copiaba en el núcleo cuando se activaba el interruptor de "carga de programa". Había versiones disponibles con cuatro ("2/4"), siete y diez ("2/10") ranuras.
El Nova 3 de 1975 añadió dos registros más, utilizados para controlar el acceso a una pila integrada. El procesador también se volvió a implementar utilizando componentes TTL , lo que aumentó aún más el rendimiento del sistema. El Nova 3 se ofreció en versiones de cuatro ranuras (Nova 3/4) y de doce ranuras (Nova 3/12).
Parece que Data General originalmente pretendía que el Nova 3 fuera el último de su línea, planeando reemplazar al Nova con las máquinas Eclipse posteriores. [ cita requerida ] Sin embargo, la demanda continua llevó a una máquina Nova 4 introducida en 1978, esta vez basada en cuatro ALU de segmento de bits AMD Am2901 . Esta máquina fue diseñada desde el principio para ser tanto el Nova 4 como el Eclipse S/140, con un microcódigo diferente para cada uno. También estaba disponible un coprocesador de punto flotante, que ocupaba una ranura separada. Una opción adicional permitía el mapeo de memoria, lo que permitía a los programas acceder a hasta 128 kwords de memoria mediante conmutación de bancos . A diferencia de las máquinas anteriores, el Nova 4 no incluía una consola en el panel frontal y, en su lugar, incluía una ROM que contenía código de máquina que permite que un terminal emule una consola cuando sea necesario. [25] : 87
Hubo tres versiones diferentes del Nova 4: el Nova 4/C, el Nova 4/S y el Nova 4/X. El Nova 4/C era una implementación de una sola placa que incluía toda la memoria (16 o 32 kwords). El Nova 4/S y el 4/X usaban placas de memoria separadas. El Nova 4/X tenía la unidad de administración de memoria (MMU) incorporada habilitada para permitir el uso de hasta 128 kwords de memoria. La MMU también estaba instalada en el Nova 4/S, pero estaba deshabilitada por firmware. Tanto el 4/S como el 4/X incluían un "prefetcher" para aumentar el rendimiento al buscar hasta 11 instrucciones de la memoria antes de que fueran necesarias. [25] : 5
Data General también produjo una serie de implementaciones de microNOVA en un solo chip del procesador Nova. Para permitir que encajara en un chip de encapsulado dual en línea (DIP) de 40 pines, el bus de direcciones y el bus de datos compartían un conjunto de 16 pines. Esto significaba que las lecturas y escrituras en la memoria requerían dos ciclos y que, como resultado, la máquina funcionaba aproximadamente a la mitad de la velocidad del Nova original. [26]
El primer chip de la serie fue el mN601 , de 1977. Se vendió como CPU para otros usuarios, como chipset completo para aquellos que querían implementar un ordenador, como ordenador completo en una única placa con 4 kB de RAM y como modelo completo de gama baja del Nova. [26] Una versión mejorada del diseño, el mN602 de 1979 , redujo todo el chipset a un único VLSI . Se ofreció en dos máquinas, la microNOVA MP/100 y la microNOVA MP/200, de mayor tamaño .
El microNOVA fue posteriormente reempaquetado con un monitor en una carcasa estilo PC con dos disquetes como el Enterprise . El Enterprise se comercializó en 1981, ejecutando RDOS , pero la introducción del IBM PC el mismo año hizo que la mayoría de las otras máquinas desaparecieran bajo el radar. [27]
El Nova influyó en el diseño de los ordenadores Xerox Alto (1973) [28] y Apple I (1976) [29] , y su arquitectura fue la base de la serie Computervision CGP (Computervision Graphics Processor). Se ha informado de que su diseño externo fue la inspiración directa para el panel frontal del microordenador MITS Altair (1975).
Data General siguió el éxito del Nova original con una serie de diseños más rápidos. La familia de sistemas Eclipse se introdujo más tarde con un conjunto de instrucciones compatible con versiones anteriores, y la serie MV amplió aún más el Eclipse hasta una arquitectura de 32 bits para competir con el DEC VAX . El desarrollo de la serie MV se documentó en el popular libro de Tracy Kidder de 1981, The Soul of a New Machine . Data General se convertiría más tarde en un proveedor de servidores y matrices de almacenamiento basados en procesadores Intel, y finalmente fue adquirida por EMC .
Hay un grupo diverso pero apasionado de personas en todo el mundo que restauran y preservan los sistemas Data General originales de 16 bits. [30] [31]
A diferencia del PDP-8 , el Nova tenía una arquitectura de carga y almacenamiento . Tenía cuatro registros acumuladores de 16 bits , dos de los cuales (2 y 3) podían usarse como registros de índice . Había un contador de programa de 15 bits y un registro de acarreo de un solo bit . Al igual que con el PDP-8, el direccionamiento de página actual + cero era central. No había registro de pila , pero los diseños posteriores de Eclipse utilizarían una dirección de memoria de hardware dedicada para esta función.
Los primeros modelos de Nova procesaban las operaciones matemáticas en serie en paquetes de 4 bits, utilizando una única unidad lógica de procesamiento (ALU) de 74181 bitslice . Un año después de su introducción, este diseño se mejoró para incluir una unidad matemática paralela completa de 16 bits utilizando cuatro 74181, diseño que se conoce como SuperNova. Las versiones futuras del sistema agregaron una unidad de pila y multiplicación/división por hardware.
El Nova 4 / Eclipse S/140 se basó en cuatro ALU de segmento de bit AMD 2901 , con microcódigo en memoria de solo lectura , y fue el primer Nova diseñado solo para memoria principal DRAM , sin provisión de memoria de núcleo magnético .
Los primeros modelos estaban disponibles con 8 K palabras de memoria de núcleo magnético como opción, una opción que prácticamente todo el mundo tenía que comprar, lo que elevaba el coste del sistema a 7.995 dólares.
Esta placa de memoria central estaba organizada de manera planar como cuatro grupos de cuatro bancos, cada banco transportaba dos conjuntos de núcleos en una matriz de 64 por 64; por lo tanto, había 64 x 64 = 4096 bits por conjunto, x 2 conjuntos daban 8192 bits, x 4 bancos daban 32768 bits, x 4 grupos daban un total de 131072 bits, y esto dividido por el tamaño de palabra de máquina de 16 bits daba 8192 palabras de memoria.
El núcleo de esta placa de memoria de 8K palabras ocupaba una "placa sobre placa" ubicada centralmente, de 5,25" de ancho por 6,125" de alto, y estaba cubierto por una placa protectora. Estaba rodeado por los circuitos de lectura-escritura-reescritura del controlador de soporte necesarios. Todo el núcleo y la electrónica de soporte correspondiente encajaban en una única placa estándar de 15 x 15 pulgadas (380 mm). Se podían admitir hasta 32K de RAM de dicho núcleo en una caja de expansión externa. La ROM de semiconductores ya estaba disponible en ese momento, y los sistemas sin RAM (es decir, solo con ROM) se hicieron populares en muchos entornos industriales. Las máquinas Nova originales funcionaban a aproximadamente 200 kHz , pero su SuperNova fue diseñada para funcionar a hasta 3 MHz cuando se usaba con una memoria principal de semiconductores especial.
La placa base estandarizada y las señales de E/S crearon un diseño de E/S simple y eficiente que facilitó la interconexión de dispositivos de E/S programadas y de canal de datos con Nova en comparación con las máquinas de la competencia. Además de su estructura de bus de E/S dedicada, la placa base de Nova tenía pines de envoltura de cables que se podían usar para conectores no estándar u otros fines especiales.
El formato de las instrucciones se podía clasificar en tres grandes grupos: 1) manipulación de registro a registro, 2) referencia de memoria y 3) entrada/salida. Cada instrucción estaba contenida en una palabra. La manipulación de registro a registro era casi como la de RISC en cuanto a su eficiencia de bits; y una instrucción que manipulaba datos de registro también podía realizar pruebas, desplazamientos e incluso elegir descartar el resultado. Las opciones de hardware incluían una unidad de multiplicación y división de números enteros, una unidad de punto flotante (precisión simple y doble) y gestión de memoria .
El primer Nova venía con un intérprete BASIC en cinta perforada . A medida que el producto fue creciendo, Data General desarrolló muchos lenguajes para los ordenadores Nova, que se ejecutaban en una variedad de sistemas operativos consistentes. Data General ofrecía FORTRAN IV , ALGOL , Extended BASIC, Data General Business Basic , Interactive COBOL y varios ensambladores. Los proveedores externos y la comunidad de usuarios ampliaron la oferta con Forth , Lisp , BCPL , C , ALGOL y otras versiones propietarias de COBOL y BASIC .
Las instrucciones de máquina implementadas a continuación son el conjunto común implementado por todos los procesadores de la serie Nova. Algunos modelos específicos solían implementar instrucciones adicionales y algunas instrucciones eran proporcionadas por hardware opcional.
Todas las instrucciones aritméticas se ejecutaban entre acumuladores. Para las operaciones que requerían dos operandos, uno se tomaba del acumulador de origen y otro del acumulador de destino, y el resultado se depositaba en el acumulador de destino. Para las operaciones con un solo operando, el operando se tomaba del registro de origen y el resultado reemplazaba al registro de destino. Para todos los códigos de operación con un solo operando, se permitía que los acumuladores de origen y destino fueran los mismos, y la operación funcionaba como se esperaba.
Todas las instrucciones aritméticas incluían un bit de "no carga" que, cuando se activaba, suprimía la transferencia del resultado al registro de destino; esto se utilizaba junto con las opciones de prueba para realizar una prueba sin perder el contenido existente del registro de destino. En lenguaje ensamblador, agregar un '#' al código de operación activaba el bit de no carga.
La CPU contenía un registro de un solo bit llamado bit de acarreo, que después de una operación aritmética contendría el acarreo del bit más significativo. El bit de acarreo podía establecerse en un valor deseado antes de realizar la operación utilizando un campo de dos bits en la instrucción. El bit podía establecerse, borrarse o complementarse antes de realizar la instrucción. En lenguaje ensamblador, estas opciones se especificaban añadiendo una letra al código de operación: 'O' — establecer el bit de acarreo; 'Z' — borrar el bit de acarreo; 'C' — complementar el bit de acarreo; nada — dejar el bit de acarreo solo. Si también se especificaba el bit sin carga, el valor de acarreo especificado se utilizaría para el cálculo, pero el registro de acarreo real permanecería inalterado.
Todas las instrucciones aritméticas incluían un campo de dos bits que podía utilizarse para especificar una opción de desplazamiento, que se aplicaría al resultado antes de que se cargara en el registro de destino. Se podía especificar un desplazamiento de un solo bit hacia la izquierda o hacia la derecha, o se podían intercambiar los dos bytes del resultado. Los desplazamientos eran circulares de 17 bits, con el bit de acarreo "a la izquierda" del bit más significativo. En otras palabras, cuando se realizaba un desplazamiento a la izquierda, el bit más significativo del resultado se desplazaba hacia el bit de acarreo, y el contenido anterior del bit de acarreo se desplazaba hacia el bit menos significativo del resultado. Los intercambios de bytes no afectaban al bit de acarreo. En lenguaje ensamblador, estas opciones se especificaban añadiendo una letra al código de operación: 'L' — desplazamiento a la izquierda; 'R' — desplazamiento a la derecha, 'S' — intercambio de bytes; nada — no realizar un desplazamiento o intercambio.
Todas las instrucciones aritméticas incluían un campo de tres bits que podía especificar una prueba que se debía aplicar al resultado de la operación. Si la prueba daba como resultado verdadero, se saltaba la siguiente instrucción en la línea. En lenguaje ensamblador, la opción de prueba se especificaba como un tercer operando de la instrucción. Las pruebas disponibles eran:
Las instrucciones aritméticas reales fueron:
Un ejemplo de instrucciones aritméticas, con todas las opciones utilizadas, es:
ADDZR# 0 , 2 , SNC
Esto se decodifica como: borrar el bit de acarreo; sumar el contenido de AC2 (acumulador 2) a AC0; desplazar circularmente el resultado un bit a la derecha; probar el resultado para ver si el bit de acarreo está establecido y omitir la siguiente instrucción si es así. Descartar el resultado después de realizar la prueba. En efecto, esto suma dos números y prueba para ver si el resultado es par o impar.
El conjunto de instrucciones de Nova contenía un par de instrucciones que transferían el contenido de la memoria a los acumuladores y viceversa, dos instrucciones de transferencia de control y dos instrucciones que probaban el contenido de una ubicación de memoria. Todas las instrucciones de referencia de memoria contenían un campo de dirección de ocho bits y un campo de dos bits que especificaba el modo de direccionamiento de la memoria. Los cuatro modos eran:
Obviamente, el modo 0 sólo era capaz de direccionar las primeras 256 palabras de memoria, dado el campo de dirección de ocho bits. Esta porción de memoria se denominaba "página cero". Las palabras de memoria de página cero se consideraban valiosas para los programadores de lenguaje ensamblador de Nova debido a la pequeña cantidad disponible; sólo las ubicaciones de página cero podían ser direccionadas desde cualquier parte del programa sin recurrir al direccionamiento indexado, que requería ocupar el acumulador 2 o 3 para usarlo como registro de índice. En lenguaje ensamblador, una directiva ".ZREL" hacía que el ensamblador colocara las instrucciones y palabras de datos que lo seguían en la página cero; una directiva ".NREL" colocaba las siguientes instrucciones y palabras de datos en la memoria "normal". Los modelos posteriores de Nova agregaron instrucciones con campos de direccionamiento extendidos, que superaron esta dificultad (con una penalización de rendimiento).
El ensamblador calculaba automáticamente los desplazamientos relativos para el modo 1, aunque también era posible escribirlos explícitamente en la fuente. Si una instrucción de referencia de memoria hacía referencia a una dirección de memoria en el espacio .NREL pero no había ningún especificador de modo, se asumía el modo 1 y el ensamblador calculaba el desplazamiento entre la instrucción actual y la ubicación referenciada, y lo colocaba en el campo de dirección de la instrucción (siempre que el valor resultante encajara en el campo de 8 bits).
Las dos instrucciones de carga y almacenamiento fueron:
Ambas instrucciones incluían un bit "indirecto". Si este bit estaba activado (en lenguaje ensamblador, se agregaba una '@' al código de operación), se asumía que el contenido de la dirección de destino era una dirección de memoria en sí misma y se hacía referencia a esa dirección para realizar la carga o el almacenamiento.
Las dos instrucciones de transferencia de control fueron:
Al igual que en el caso de las instrucciones de carga y almacenamiento, las instrucciones de salto contenían un bit indirecto, que también se especificaba en el ensamblador utilizando el carácter '@'. En el caso de un salto indirecto, el procesador recuperaba el contenido de la ubicación de destino y utilizaba el valor como la dirección de memoria a la que saltar. Sin embargo, a diferencia de las instrucciones de carga y almacenamiento, si la dirección indirecta tenía establecido el bit más significativo, realizaría un ciclo adicional de indirección. En los procesadores de la serie Nova anteriores al Nova 3, no había límite en la cantidad de ciclos de indirección; una dirección indirecta que se referenciara a sí misma daría como resultado un bucle de direccionamiento indirecto infinito, en el que la instrucción nunca se completaría. (Esto podía ser alarmante para los usuarios, ya que en esta condición, al presionar el interruptor STOP en el panel frontal no se producía ningún efecto. Era necesario reiniciar la máquina para romper el bucle).
Las dos instrucciones de la prueba de memoria fueron:
Al igual que en el caso de las instrucciones de carga y almacenamiento, había un bit indirecto que realizaba un único nivel de direccionamiento indirecto. Estas instrucciones eran extrañas porque, en los Novas con memoria de núcleo magnético, la instrucción se ejecutaba dentro de la propia placa de memoria. Como era común en ese momento, las placas de memoria contenían un circuito de "escritura diferida" para resolver el problema de lectura destructiva inherente a la memoria de núcleo magnético. Pero el mecanismo de escritura diferida también contenía una mini unidad aritmética, que el procesador usaba para varios propósitos. Para las instrucciones ISZ y DSZ, el incremento o decremento ocurría entre la ubicación de memoria que se estaba leyendo y la escritura diferida; la CPU simplemente esperaba a que se le dijera si el resultado era cero o distinto de cero. Estas instrucciones eran útiles porque permitían usar una ubicación de memoria como un contador de bucle sin ocupar un acumulador, pero eran más lentas que ejecutar las instrucciones aritméticas equivalentes.
Algunos ejemplos de instrucciones de referencia de memoria:
LDA 1 , CONTAR
Transfiere el contenido de la ubicación de memoria etiquetada COUNT al acumulador 1. Suponiendo que COUNT está en el espacio .NREL, esta instrucción es equivalente a: LDA 1,1,(COUNT-(.+1)) donde '.' representa la ubicación de la instrucción LDA.
JSR@ 0 , 17
Salta indirectamente a la dirección de memoria especificada por el contenido de la ubicación 17, en el espacio de la página cero, y deposita la dirección de retorno en el acumulador 3. Este era el método estándar para realizar una llamada al sistema RDOS en los primeros modelos Nova; el mnemónico del lenguaje ensamblador ".SYSTM" se tradujo así.
JMP0,3
Salta a la ubicación de memoria cuya dirección está contenida en el acumulador 3. Este era un medio común de regresar de una llamada de función o subrutina, ya que la instrucción JSR dejaba la dirección de retorno en el acumulador 3.
ESTADO 0 , 3 , - 1
Almacene el contenido del acumulador 0 en la ubicación que es uno menos que la dirección contenida en el acumulador 3.
CONTEO DSZ
Disminuye el valor en la ubicación etiquetada como COUNT y omite la siguiente instrucción si el resultado es cero. Como en el caso anterior, si se supone que COUNT está en el espacio .NREL, esto es equivalente a: DSZ 1,(COUNT-(.+1))
Los Novas implementaron un modelo canalizado para la interconexión con dispositivos de E/S. En el modelo, se esperaba que cada dispositivo de E/S implementara dos indicadores, denominados "Ocupado" y "Hecho", y tres registros de datos y control, denominados A, B y C. Las instrucciones de E/S estaban disponibles para leer y escribir los registros, y para enviar una de las tres señales al dispositivo, denominadas "inicio", "borrado" y "pulso". En general, el envío de una señal de inicio iniciaba una operación de E/S que se había configurado cargando valores en los registros A/B/C. La señal de borrado detenía una operación de E/S y borraba cualquier interrupción resultante. La señal de pulso se utilizaba para iniciar operaciones auxiliares en subsistemas complejos, como operaciones de búsqueda en unidades de disco. Los dispositivos sondeados generalmente movían datos directamente entre el dispositivo y el registro A. Los dispositivos DMA generalmente usaban el registro A para especificar la dirección de memoria, el registro B para especificar la cantidad de palabras que se transferirían y el registro C para los indicadores de control. El canal 63 hacía referencia a la CPU misma y se utilizaba para diversas funciones especiales.
Cada instrucción de E/S contenía un campo de número de canal de seis bits, un campo de cuatro bits para especificar qué registro leer o escribir y un campo de dos bits para especificar qué señal se debía enviar. En lenguaje ensamblador, la señal se especificaba añadiendo una letra al código de operación: 'S' para iniciar, 'C' para borrar, 'P' para pulsar y nada para no tener señal. Los códigos de operación eran:
Además, había cuatro instrucciones disponibles para probar el estado de un dispositivo:
Al iniciar un dispositivo, se activaba su indicador de ocupado. Cuando se completaba la operación solicitada, normalmente el dispositivo borraba su indicador de ocupado y activaba su indicador de terminado; la mayoría de los dispositivos tenían su mecanismo de solicitud de interrupción conectado al indicador de terminado, por lo que activar el indicador de terminado provocaba una interrupción (si las interrupciones estaban habilitadas y el dispositivo no estaba enmascarado).
Estas instrucciones realizaban diversas funciones de control y estado de la CPU. Todas ellas eran, en realidad, mnemónicos abreviados para las instrucciones de E/S en el canal 63, el canal de E/S autorreferencial de la CPU.
Desde el punto de vista del hardware, el mecanismo de interrupción era relativamente simple, pero también menos flexible que las arquitecturas de CPU actuales. La placa base admitía una única línea de solicitud de interrupción, a la que se conectaban todos los dispositivos capaces de interrumpir. Cuando un dispositivo necesitaba solicitar una interrupción, activaba esta línea. La CPU tomaba la interrupción tan pronto como completaba la instrucción actual. Como se indicó anteriormente, se esperaba que un dispositivo activara su indicador de E/S "terminado" cuando solicitaba una interrupción, y la convención era que el dispositivo borraría su solicitud de interrupción cuando la CPU ejecutaba una instrucción de borrado de E/S en el número de canal del dispositivo.
La CPU esperaba que el sistema operativo colocara la dirección de su rutina de servicio de interrupción en la dirección de memoria 1. Cuando un dispositivo interrumpía, la CPU hacía un salto indirecto a través de la dirección 1, colocando la dirección de retorno en la dirección de memoria 0 y deshabilitando más interrupciones. El manejador de interrupciones entonces ejecutaba una instrucción INTA para descubrir el número de canal del dispositivo que interrumpía. Esto funcionaba generando una señal de "reconocimiento" en la placa base. La señal de reconocimiento estaba cableada en un formato de cadena de margaritas a través de la placa base, de modo que pasaba por cada placa en el bus. Se esperaba que cualquier dispositivo que solicitara una interrupción bloqueara la propagación posterior de la señal de reconocimiento por el bus, de modo que si dos o más dispositivos tenían interrupciones pendientes simultáneamente, solo el primero vería la señal de reconocimiento. Ese dispositivo respondía entonces colocando su número de canal en las líneas de datos en el bus. Esto significaba que, en el caso de solicitudes de interrupción simultáneas, el dispositivo que tenía prioridad se determinaba por cuál estaba físicamente más cerca de la CPU en la caja de tarjetas.
Después de que se hubiera procesado la interrupción y la rutina de servicio hubiera enviado al dispositivo una orden de borrado de E/S, este reanudaba el procesamiento normal habilitando las interrupciones y luego regresando a través de un salto indirecto a través de la dirección de memoria 0. Para evitar que una interrupción pendiente interrumpiera inmediatamente antes del salto de retorno (lo que haría que se sobrescribiera la dirección de retorno), la instrucción INTEN tenía un retraso de un ciclo de instrucción. Cuando se ejecutaba, las interrupciones no se habilitaban hasta después de que se ejecutara la siguiente instrucción, que se esperaba que fuera la instrucción JMP@ 0.
La rutina de servicio de interrupción del sistema operativo normalmente realizaba un salto indexado utilizando el número de canal recibido, para saltar a la rutina de manejo de interrupciones específica para el dispositivo. Había algunos dispositivos, en particular el circuito de detección de falla de energía de la CPU, que no respondían a la instrucción INTA. Si la INTA devolvía un resultado de cero, la rutina de servicio de interrupción tenía que sondear todos los dispositivos que no respondían a la INTA utilizando las instrucciones SKPDZ/SKPDN para ver cuál interrumpía.
El sistema operativo podía gestionar en cierta medida el orden de las interrupciones estableciendo una máscara de interrupción mediante la instrucción MSKO. Esto tenía por objeto permitir que el sistema operativo determinara qué dispositivos podían interrumpir en un momento dado. Cuando se emitía esta instrucción, se transmitía una máscara de interrupción de 16 bits a todos los dispositivos de la placa base. Dependía del dispositivo decidir qué significaba realmente la máscara para él; por convención, se suponía que un dispositivo enmascarado no debía activar la línea de interrupción, pero la CPU no tenía medios para hacer cumplir esto. La mayoría de los dispositivos enmascarables permitían seleccionar el bit de máscara mediante un puente en la placa. Había dispositivos que ignoraban la máscara por completo.
En los sistemas que tenían memoria de núcleo magnético (que retenía su contenido sin alimentación), era posible recuperarse de un corte de energía. Un circuito de detección de falla de energía en la CPU emitía una interrupción cuando se detectaba la pérdida de la alimentación principal que llegaba a la computadora; a partir de este punto, la CPU tenía un breve período de tiempo hasta que un capacitor en la fuente de alimentación perdía su carga y la energía a la CPU fallaba. Este tiempo era suficiente para detener la E/S en progreso, emitiendo una instrucción IORST, y luego guardar el contenido de los cuatro acumuladores y el bit de acarreo en la memoria. Cuando la energía regresaba, si el interruptor de llave del panel frontal de la CPU estaba en la posición LOCK, la CPU se iniciaba y realizaba un salto indirecto a través de la dirección de memoria 2. Se esperaba que esta fuera la dirección de una rutina de servicio del sistema operativo que recargaría los acumuladores y el bit de acarreo, y luego reanudaría el procesamiento normal. Dependía de la rutina de servicio averiguar cómo reiniciar las operaciones de E/S que se habían abortado por el corte de energía.
Como era la convención de la época, la mayoría de los modelos Nova proporcionaban una consola en el panel frontal para controlar y supervisar las funciones de la CPU. Los modelos anteriores al Nova 3 se basaban en un diseño de panel frontal canónico, como se muestra en la foto del panel del Nova 840 a la derecha. El diseño contenía un interruptor de encendido con llave, dos filas de lámparas de visualización de datos y direcciones, una fila de interruptores de entrada de datos y una fila de interruptores de función que activaban varias funciones de la CPU cuando se presionaban. Las lámparas de dirección siempre mostraban el valor actual del contador de programa, en binario. Las lámparas de datos mostraban varios valores según la función de la CPU que estuviera activa en ese momento. A la izquierda de la lámpara de datos más a la izquierda, una lámpara adicional mostraba el valor actual del bit de acarreo. En la mayoría de los modelos, las lámparas eran lámparas incandescentes que estaban soldadas al tablero del panel; reemplazar las lámparas quemadas era una pesadilla para los ingenieros de servicio de campo de Data General.
Cada uno de los interruptores de datos controlaba el valor de un bit en un valor de 16 bits y, según la convención de Data General, estaban numerados del 0 al 15 de izquierda a derecha. Los interruptores de datos proporcionaban entrada a la CPU para varias funciones y también podían ser leídos por un programa en ejecución utilizando la instrucción de lenguaje ensamblador READS. Para reducir el desorden del panel y ahorrar dinero, los interruptores de función se implementaron como interruptores momentáneos bidireccionales. Cuando se levantaba la palanca del interruptor de función, se activaba la función cuyo nombre estaba impreso sobre el interruptor en el panel; cuando se presionaba la palanca hacia abajo, se activaba la función cuyo nombre aparecía debajo del interruptor. La palanca del interruptor volvía a una posición neutral cuando se soltaba.
En referencia a la foto del Nova 840, los primeros cuatro interruptores desde la izquierda realizaban las funciones EXAMINAR y DEPOSITAR para los cuatro acumuladores. Al presionar EXAMINAR en uno de ellos, las luces de datos mostraban el valor actual del acumulador en binario. Al presionar DEPOSITAR, se transfería el valor binario representado por los ajustes actuales de los interruptores de datos al acumulador.
Yendo hacia la derecha, el siguiente interruptor era el interruptor RESET/STOP. Al presionar STOP, la CPU se detenía después de completar la instrucción actual. Al presionar RESET, la CPU se detenía inmediatamente, borraba una cantidad de registros internos de la CPU y enviaba una señal de reinicio de E/S a todos los dispositivos conectados. El interruptor a la derecha de este era el interruptor START/CONTINUE. Al presionar CONTINUE, la CPU reanudaba la ejecución en la instrucción que señalaba actualmente el contador de programa. Al presionar START, se transfería el valor establecido actualmente en los interruptores de datos 1 a 15 al contador de programa y luego comenzaba la ejecución desde allí.
Los dos interruptores siguientes proporcionaban acceso de lectura y escritura a la memoria desde el panel frontal. Al pulsar EXAMINE se transfería el valor establecido en los interruptores de datos 1 a 15 al contador de programa, se obtenía el valor en la ubicación de memoria correspondiente y se mostraba su valor en las luces de datos. Al pulsar EXAMINE NEXT se incrementaba el contador de programa y luego se realizaba una operación de examen en esa ubicación de memoria, lo que permitía al usuario pasar por una serie de ubicaciones de memoria. Al pulsar DEPOSIT se escribía el valor contenido en los interruptores de datos en la ubicación de memoria indicada por el contador de programa. Al pulsar DEPOSIT NEXT primero se incrementaba el contador de programa y luego se depositaba en la ubicación de memoria indicada.
La función INST STEP hacía que la CPU ejecutara una instrucción en la ubicación actual del contador del programa y luego se detuviera. Dado que el contador del programa se incrementaba como parte de la ejecución de la instrucción, esto permitía al usuario ejecutar un programa paso a paso. MEMORY STEP, un nombre inapropiado, hacía que la CPU ejecutara un solo ciclo de reloj y se detuviera. Esto era de poca utilidad para los usuarios y, por lo general, solo lo utilizaba el personal de servicio de campo para realizar diagnósticos.
PROGRAM LOAD era el mecanismo que se utilizaba habitualmente para arrancar un Nova. Cuando se activaba este interruptor, hacía que la ROM de arranque de 32 palabras se asignara a las primeras 32 palabras de la memoria, establecía el contador de programa en 0 e iniciaba la CPU. La ROM de arranque contenía código que leía 256 palabras (512 bytes) de código desde un dispositivo de E/S seleccionado en la memoria y luego transfería el control al código de lectura. Los interruptores de datos 8-15 se utilizaban para indicar a la ROM de arranque desde qué canal de E/S arrancar. Si el interruptor 0 estaba desactivado, la ROM de arranque suponía que el dispositivo era un dispositivo sondeado (por ejemplo, el lector de cinta de papel) y ejecutaba un bucle de entrada sondeada hasta que se hubieran leído 512 bytes. Si el interruptor 0 estaba activado, la ROM de arranque suponía que el dispositivo era un dispositivo con capacidad DMA e iniciaba una transferencia de datos DMA. La ROM de arranque no era lo suficientemente inteligente como para posicionar el dispositivo antes de iniciar la transferencia. Esto era un problema al reiniciar después de una falla; Si el dispositivo de arranque era una unidad de disco, sus cabezales probablemente habían quedado en un cilindro aleatorio. Tuvieron que ser reposicionados en el cilindro 0, donde RDOS escribió el bloque de arranque de primer nivel, para que la secuencia de arranque funcionara. Convencionalmente, esto se hacía haciendo que la unidad pasara en ciclos por su secuencia de carga, pero los usuarios que se frustraban con el tiempo de espera (hasta 5 minutos dependiendo del modelo de unidad) aprendieron cómo ingresar desde el panel frontal un código de E/S de "recalibración" de la unidad y ejecutarlo en un solo paso, una operación que le tomaba a un usuario experimentado solo unos segundos.
El interruptor de encendido era un interruptor con llave de 3 posiciones marcadas como OFF, ON y LOCK. En la posición OFF se eliminaba toda la energía de la CPU. Al girar la llave a ON se aplicaba energía a la CPU. Sin embargo, a diferencia de las CPU actuales, la CPU no se iniciaba automáticamente cuando se aplicaba energía; el usuario tenía que usar PROGRAM LOAD o algún otro método para iniciar la CPU e iniciar la secuencia de arranque. Al girar el interruptor a LOCK se desactivaban los interruptores de función del panel frontal; al girar el interruptor a LOCK y quitar la llave, el usuario podía hacer que la CPU fuera resistente a la manipulación. En sistemas con memoria de núcleo magnético, la posición LOCK también habilitaba la función de recuperación automática de falla de energía. La llave se podía quitar en las posiciones OFF o LOCK.
El Nova 1200 ejecutó las instrucciones de acceso a la memoria central (LDA y STA) en 2,55 microsegundos (μs). El uso de memoria de solo lectura ahorró 0,4 μs. Las instrucciones del acumulador (ADD, SUB, COM, NEG, etc.) tardaron 1,55 μs, MUL 2,55 μs, DIV 3,75 μs, ISZ 3,15-4,5 μs. [32] En el posterior Eclipse MV/6000, LDA y STA tardaron 0,44 μs, ADD, etc. tardaron 0,33 μs, MUL 2,2 μs, DIV 3,19 μs, ISZ 1,32 μs, FAD 5,17 μs, FMMD 11,66 μs. [33]
Este es un ejemplo de programación mínima en lenguaje ensamblador Nova. Está diseñado para ejecutarse en RDOS e imprime la cadena “ Hola, mundo ” en la consola.
; un programa "hola, mundo" para Nova que ejecuta RDOS ; utiliza la llamada al sistema PCHAR .titl hello .nrel .ent start inicio: dochar: lda 0 , @ pmsg ; cargar ac0 con el siguiente caracter, mov# 0 , 0 , snr ; probar ac0; omitir si no es cero (no cargar el resultado) jmp done .systm .pchar ; imprimir primero jmp er ; omitir si es correcto movs 0 , 0 ; intercambiar bytes .systm .pchar ; imprimir segundo jmp er ; omitir si es correcto isz pmsg ; apuntar al siguiente caracter jmp dochar ; dar la vuelta de nuevo hecho: .systm ; salida normal .rtn er: .systm ; salida de error .ertn halt pmsg: . + 1 ; puntero al primer carácter de la cadena ; tenga en cuenta que los bytes se empaquetan de derecha a izquierda de manera predeterminada ; <15><12> denota un par CR LF. .txt / Hola , mundo. < 15 >< 12 >/ 0 ; marca palabra para finalizar la cadena .fin inicio
Los modelos básicos de Nova no tenían capacidad de multiplicación y división incorporada en el hardware, para mantener los precios competitivos. La siguiente rutina multiplica dos palabras de 16 bits para producir un resultado de palabra de 16 bits (se ignora el desbordamiento). Demuestra el uso combinado de ALU op, shift y test (skip). Tenga en cuenta que cuando esta rutina es llamada por jsr
, AC3 contiene la dirección de retorno . Esto es utilizado por la instrucción de retorno jmp 0,3
. Una forma idiomática de borrar un acumulador es sub 0,0
. Se pueden organizar otras instrucciones individuales para cargar un conjunto específico de constantes útiles (por ejemplo, -2, -1 o +1).
mpy: ; multiplica AC0 <- AC1 * AC2, por Toby Thain sub 0 , 0 ; borrar resultado mbit: movzr 1 , 1 , szc ; desplazar multiplicador, probar lsb add 2 , 0 ; 1: sumar multiplicando movzl 2 , 2 , szr ; desplazar y probar cero jmp mbit ; no cero, hacer otro bit jmp 0 , 3 ; regresar
La siguiente rutina imprime el valor de AC1 como un número binario de 16 dígitos en la consola RDOS. Revela más peculiaridades del conjunto de instrucciones de Nova. Por ejemplo, no hay instrucción para cargar un valor "inmediato" arbitrario en un acumulador (aunque las instrucciones de referencia de memoria sí codifican dicho valor para formar una dirección efectiva). Los acumuladores generalmente deben cargarse desde ubicaciones de memoria inicializadas (por ejemplo, n16
). Otras máquinas contemporáneas, como la PDP-11 , y prácticamente todas las arquitecturas modernas, permiten cargas inmediatas, aunque muchas, como ARM, restringen el rango de valores que se pueden cargar inmediatamente.
.systm
Debido a que la macro de llamada RDOS implementa una jsr
, AC3 se sobrescribe con la dirección de retorno de la .pchar
función. Por lo tanto, se necesita una ubicación temporal para preservar la dirección de retorno del llamador de esta función. Para una rutina recursiva o de reentrada, se debe utilizar una pila, hardware si está disponible, software si no lo está. La instrucción de retorno se convierte en , jmp @ retrn
que aprovecha el modo de direccionamiento indirecto de Nova para cargar la PC de retorno.
Las definiciones constantes al final muestran dos características del ensamblador: el radio del ensamblador es octal por defecto ( 20
= dieciséis), y las constantes de caracteres podrían codificarse como, por ejemplo "0
, .
pbin: ; imprime AC1 en la consola como 16 dígitos binarios, por Toby Thain sta 3 , retrn ; guardar dirección de retorno lda 2 , n16 ; configurar contador de bits loop: lda 0 , chr0 ; cargar ASCII '0' movzl 1 , 1 , szc ; obtener el siguiente bit en el acarreo inc 0 , 0 ; aumentar a '1' .systm .pchar ; AC0-2 preservado jmp err ; si hay error inc 2 , 2 , szr ; aumentar contador jmp loop ; repetir nuevamente si no es cero lda 0 , spc ; generar un espacio .systm .pchar jmp err ; si hay error jmp @ retrn spc: " ;eso es un espacio chr0: "0 n16: -20 retrn: 0
La Canadian Broadcasting Corporation de Montreal utilizó el Nova 1200 para la automatización de la reproducción de canales hasta finales de los años 1980. Luego fue reemplazado por unidades Nova 4 renovadas que estuvieron en uso hasta mediados de los años 1990.