Articulo de referencia

Lenguaje de programación de bajo nivel

Un lenguaje de programación de bajo nivel es aquel que ofrece poca o ninguna abstracción de la arquitectura del conjunto de instrucciones , la memoria o el hardware físico subya...

Un lenguaje de programación de bajo nivel es aquel que ofrece poca o ninguna abstracción de la arquitectura del conjunto de instrucciones , la memoria o el hardware físico subyacente de un ordenador; los comandos o funciones del lenguaje son estructuralmente similares a las instrucciones de un procesador. Estos lenguajes proporcionan al programador un control total sobre la memoria del programa y las instrucciones del código máquina subyacente. Debido al bajo nivel de abstracción (de ahí el término "bajo nivel") entre el lenguaje y el lenguaje máquina, a veces se describe a los lenguajes de bajo nivel como "cercanos al hardware".

Código máquina

Panel frontal de una minicomputadora PDP-8/e . La fila de interruptores en la parte inferior se puede usar para introducir código máquina.

El código máquina , clasificado como un lenguaje de programación de primera generación , [ 1 ] [ 2 ] son ​​datos codificados y estructurados según la arquitectura del conjunto de instrucciones de una CPU . Las instrucciones implican operaciones como mover valores dentro y fuera de ubicaciones de memoria, lógica booleana, aritmética, comparación de valores y control de flujo (ramificaciones y saltos).

Los programadores casi nunca programan directamente en código máquina; en su lugar, utilizan un lenguaje ensamblador o un lenguaje de programación de alto nivel como C, C++, C#, etc. [ 3 ] Aunque pocos programas se escriben en lenguajes máquina, algunos programadores aprenden a leerlo a través de la experiencia con volcados de memoria y depuración.

lenguaje ensamblador

Un lenguaje ensamblador , clasificado como un lenguaje de programación de segunda generación , [ 1 ] [ 2 ] proporciona un nivel de abstracción sobre el código máquina. Un programa escrito en lenguaje ensamblador no es portable , debido a que está escrito y optimizado para una arquitectura particular. [ 3 ] [ 4 ] [ 5 ] [ 6 ]

El lenguaje ensamblador tiene poca semántica o especificación formal, siendo solo una correspondencia entre símbolos legibles por humanos, incluyendo direcciones simbólicas, y códigos de operación , direcciones , constantes numéricas, cadenas , etc. Normalmente, una instrucción de máquina se representa como una línea de código ensamblador, comúnmente llamada mnemónico . [ 7 ] Los ensambladores producen archivos objeto que pueden enlazarse con otros archivos objeto o cargarse de forma independiente. La mayoría de los ensambladores proporcionan macros para generar secuencias de instrucciones comunes.

En los primeros días de la programación en computadoras como TX-0 y PDP-1 , lo primero que hicieron los hackers del MIT fue escribir ensambladores. [ 8 ]

Lenguajes orientados a máquinas

Se han desarrollado varios lenguajes denominados lenguajes orientados a máquinas , lenguajes de nivel medio o lenguajes intermedios , y lenguajes de un cuarto de camino [ 9 ], tales como:

lenguaje de programación C

El lenguaje de programación C , un lenguaje de programación de tercera generación , [ 1 ] [ 2 ] se clasifica a veces como de alto o bajo nivel dependiendo de lo que se entienda por alto o bajo nivel. [ 13 ] La sintaxis de C es inherentemente de nivel superior a la de un lenguaje ensamblador, ya que un lenguaje ensamblador depende sintácticamente de la plataforma, mientras que la sintaxis de C es independiente de la plataforma. C admite la programación de bajo nivel ( acceso directo al hardware del ordenador ), pero otros lenguajes, a veces considerados de nivel superior a C, también pueden acceder al hardware directamente. Con C, los desarrolladores podrían necesitar manejar aspectos de nivel relativamente bajo que otros lenguajes abstraen (proporcionan soporte de nivel superior), como la gestión de memoria y la aritmética de punteros. Pero C puede codificar abstracciones que ocultan detalles como el acceso al hardware, la gestión de memoria y la aritmética de punteros, de modo que al menos una parte de un código base en C podría ser conceptualmente de alto nivel como si estuviera construido en cualquier otro lenguaje. Se debate si C se clasifica como un lenguaje de alto o bajo nivel, pero es de un nivel superior al de los lenguajes ensamblador (especialmente sintácticamente) y de un nivel inferior al de muchos otros lenguajes en algunos aspectos .

Aunque C no es independiente de la arquitectura, puede utilizarse para escribir código multiplataforma , si bien esto puede resultar técnicamente complejo. Un aspecto de C que facilita el desarrollo multiplataforma es la biblioteca estándar de C , que proporciona «una interfaz para objetos dependientes del sistema que, a su vez, es relativamente independiente del sistema». [ 14 ]

Comparación

A continuación se muestra el código máquina x86-64 de un algoritmo para calcular el n -ésimo número de Fibonacci , con valores en representación hexadecimal y cada línea correspondiente a una instrucción:

89 f8 85 y siguientes 74 26 83 y siguientes 02 76 1c 89 f9 ba 01 00 00 00 ser 01 00 00 00 8d 04 16 83 f9 02 74 0d 89 d6 ff c9 89 c2 eb f0 b8 01 00 00 c3 

El siguiente es el mismo algoritmo escrito en lenguaje ensamblador x86-64 usando la sintaxis de Intel . Los registros del procesador x86-64 se nombran y manipulan directamente. La función carga su argumento de 64 bits de rdiacuerdo con la interfaz binaria de la aplicación System V para x86-64 y realiza su cálculo manipulando valores en los registros rax, rcx, rsi, y rdihasta que haya terminado y regrese. Tenga en cuenta que en este lenguaje ensamblador, no existe el concepto de devolver un valor. Habiendo el resultado almacenado en el raxregistro, nuevamente de acuerdo con la interfaz binaria de la aplicación System V, la retinstrucción simplemente elimina el elemento superior de 64 bits en la pila y hace que la siguiente instrucción se obtenga de esa ubicación (esa instrucción suele ser la instrucción inmediatamente posterior a la que llamó a esta función), con el resultado de la función almacenado en rax. El lenguaje ensamblador x86-64 no impone ningún estándar para pasar valores a una función o devolver valores de una función (y de hecho, no tiene el concepto de una función); Estas se definen mediante una interfaz binaria de aplicación (ABI), como la ABI del sistema V para un conjunto de instrucciones específico.

fib: mov rax , rdi ; El argumento se almacena en rdi, lo ponemos en rax test rdi , rdi ; ¿Es el argumento cero? je .return_from_fib ; Sí - devuelve 0, que ya está en rax cmp rdi , 2 ; No - compara el argumento con 2 jbe .return_1_from_fib ; Si es menor o igual que 2, devuelve 1 mov rcx , rdi ; De lo contrario, lo ponemos en rcx, para usarlo como contador mov rdx , 1 ; El primer número anterior comienza como 1, lo ponemos en rdx mov rsi , 1 ; El segundo número anterior también comienza como 1, lo ponemos en rsi .fib_loop: lea rax , [ rsi + rdx ] ; Ponemos la suma de los dos números anteriores en rax cmp rcx , 2 ; ¿El contador es 2? je .return_from_fib ; Sí - rax contiene el resultado mov rsi , rdx ; No - convierte el primer número anterior en el segundo número anterior dec rcx ; Decrementa el contador mov rdx , rax ; Convierte el número actual en el primer número anterior jmp .fib_loop ; Continúa .return_1_from_fib: mov rax , 1 ; Establece el valor de retorno en 1 .return_from_fib: ret ; Regresa

A continuación se muestra el mismo algoritmo, pero en C. Su estructura es similar a la del ejemplo en lenguaje ensamblador, pero existen diferencias significativas en el nivel de abstracción:

  • El parámetro de entrada nes una abstracción que no especifica ninguna ubicación de almacenamiento en el hardware. En la práctica, el compilador de C sigue una de las muchas convenciones de llamada posibles para determinar una ubicación de almacenamiento para la entrada.
  • Las variables locales f_nminus2, f_nminus1, y f_nson abstracciones que no especifican ninguna ubicación de almacenamiento específica en el hardware. El compilador de C decide cómo almacenarlas realmente para la arquitectura de destino.
  • La función de retorno especifica el valor que se debe devolver, pero no determina cómo se devuelve. El compilador de C para cada arquitectura implementa un mecanismo estándar para devolver el valor. Los compiladores para la arquitectura x86-64 suelen (aunque no siempre) usar el raxregistro para devolver un valor, como en el ejemplo en lenguaje ensamblador (el autor del ejemplo en lenguaje ensamblador optó por usar la interfaz binaria de la aplicación System V para la convención x86-64, pero el lenguaje ensamblador no lo requiere).

Estas abstracciones permiten compilar el código C sin modificaciones para cualquier arquitectura compatible con un compilador C; mientras que el código ensamblador anterior solo se ejecuta en procesadores que utilizan la arquitectura x86-64.

entero sin signo fib ( entero sin signo n ) { if ( ! n ) { return 0 ; } else if ( n <= 2 ) { return 1 ; } else { entero sin signo f_nminus2 , f_nminus1 , f_n ; for ( f_nminus2 = f_nminus1 = 1 , f_n = 0 ; ; -- n ) { f_n = f_nminus2 + f_nminus1 ; if ( n <= 2 ) { return f_n ; } f_nminus2 = f_nminus1 ; f_nminus1 = f_n ; } } }

Programación de bajo nivel en lenguajes de alto nivel

Algunos lenguajes de alto nivel , como PL/S , BLISS , BCPL , ALGOL extendido , NEWP y C, pueden acceder a lenguajes de programación de bajo nivel. Un método para lograrlo es el ensamblaje en línea , en el que el código ensamblador se inserta en el código del lenguaje de alto nivel. Algunos de estos lenguajes también permiten directivas de optimización del compilador, dependientes de la arquitectura , para ajustar la forma en que el compilador utiliza la arquitectura del procesador de destino.

El siguiente bloque de código C del compilador GNU C (GCC) demuestra su característica de ensamblaje en línea. [ 15 ]

int src = 1 ; int dst ;asm ( "mov %1, %0 \n\t " "add $1, %0" : "=r" ( dst ) : "r" ( src ));printf ( "%d \n " , dst );

Referencias

  1. 1 2 3 "Generación de lenguajes de programación" . GeeksforGeeks . 22-10-2017 . Recuperado el 27-04-2024 .
  2. 1 2 3 "¿Qué es una generación de lenguajes?" . www.computerhope.com . Consultado el 27-04-2024 .
  3. 1 2 "3.1: Estructura de programas de bajo nivel" . Workforce LibreTexts . 2021-03-05 . Recuperado el 2023-04-03 .
  4. "¿Qué es un lenguaje de bajo nivel?" . GeeksforGeeks . 19-11-2023 . Consultado el 27-04-2024 .
  5. "¿Lenguaje de bajo nivel? Lo que necesitas saber | Lenovo EE." . www.lenovo.com . Archivado del original el 24/07/2024 . Consultado el 27/04/2024 .
  6. "Lenguajes de bajo nivel: clasificación de lenguajes de programación y traductores - AQA - Repaso de informática GCSE - AQA" . BBC Bitesize . Consultado el 27 de abril de 2024 .
  7. "Lenguaje de máquina/Lenguaje ensamblador/Lenguaje de alto nivel" . www.cs.mtsu.edu . Archivado del original el 14 de diciembre de 2024. Consultado el 27 de abril de 2024 .
  8. Levy, Stephen (1994). Hackers: Héroes de la revolución informática . Penguin Books. pág. 32. ISBN  0-14-100051-1.
  9. Sammet, Jean (octubre de 1971). "Breve panorama de los lenguajes utilizados para la implementación de sistemas" . ACM SIGPLAN Notices . 6 (9): 1– 19. doi : 10.1145/942596.807055 .
  10. Hay, RE; Rulifson, JF MOL940: Especificación preliminar para un lenguaje orientado a máquinas similar a ALGOL para el SDS 940 (PDF) (Informe técnico). Instituto de Investigación de Stanford .
  11. Wichmann, BA (19 de enero de 1999). "PL516, un lenguaje ensamblador tipo Algol para el DDP-516" (PDF) .
  12. Sapper, Gerd R. (1971). "El lenguaje de programación PS440 como herramienta para implementar un sistema de tiempo compartido". Actas del simposio SIGPLAN sobre lenguajes para la implementación de sistemas . Nueva York, NY, EE. UU.: Association for Computing Machinery. doi : 10.1145/800234.807058 .
  13. Jindal, G.; Khurana, P.; Goel, T. (enero de 2013). "Estudio comparativo de los lenguajes de programación C, Objective C y C++". Revista Internacional de Tendencias Avanzadas en Ciencias de la Computación e Ingeniería . 2 (1): 203.
  14. Kernighan, B. ; Ritchie, D. (1988). El lenguaje de programación C, 2.ª edición . pág. 163. 
  15. "Ensamblador extendido (usando la colección de compiladores GNU (GCC))" . gcc.gnu.org . Consultado el 27 de abril de 2024 .

Bibliografía

  • Zhirkov, Igor (2017). Programación de bajo nivel: C, ensamblador y ejecución de programas en la arquitectura Intel 64. California: Apress. ISBN 978-1-4842-2402-1.