stringtranslate.com

Lenguaje de programación de bajo nivel

Un lenguaje de programación de bajo nivel es un lenguaje de programación que proporciona poca o ninguna abstracción de la arquitectura del conjunto de instrucciones de una computadora ; Los comandos o funciones en el lenguaje son estructuralmente similares a las instrucciones de un procesador. Generalmente, esto se refiere a código de máquina o lenguaje ensamblador . Debido a la baja abstracción (de ahí la palabra) entre el lenguaje y el lenguaje de máquina, los lenguajes de bajo nivel a veces se describen como "cercanos al hardware". Los programas escritos en lenguajes de bajo nivel tienden a ser relativamente no portátiles , debido a que están optimizados para cierto tipo de arquitectura de sistema. [1] [2] [3] [4]

Los lenguajes de bajo nivel pueden convertirse a código de máquina sin un compilador o intérprete ( los lenguajes de programación de segunda generación [5] [6] utilizan un procesador más simple llamado ensamblador ) y el código resultante se ejecuta directamente en el procesador. Se puede hacer que un programa escrito en un lenguaje de bajo nivel se ejecute muy rápidamente, con una pequeña huella de memoria . Un programa equivalente en un lenguaje de alto nivel puede ser menos eficiente y utilizar más memoria. Los lenguajes de bajo nivel son simples, pero se consideran difíciles de usar debido a numerosos detalles técnicos que el programador debe recordar. En comparación, un lenguaje de programación de alto nivel aísla la semántica de ejecución de una arquitectura informática de la especificación del programa, lo que simplifica el desarrollo. [1]

Codigo de maquina

Panel frontal de una minicomputadora PDP-8/E. La fila de interruptores en la parte inferior se puede usar para alternar en un programa en lenguaje de máquina.

El código de máquina es la forma en que el código que se puede ejecutar directamente se almacena en una computadora. Consiste en instrucciones en lenguaje de máquina , almacenadas en la memoria, que realizan operaciones tales como mover valores dentro y fuera de ubicaciones de memoria, aritmética y lógica booleana, y probar valores y, según la prueba, ejecutar la siguiente instrucción en la memoria o ejecutar una instrucción en otro lugar.

El código de máquina generalmente se almacena en la memoria como datos binarios . Los programadores casi nunca escriben programas directamente en código de máquina; en cambio, escriben código en lenguaje ensamblador o lenguajes de programación de nivel superior. [1]

Aunque pocos programas están escritos en lenguajes de máquina, los programadores a menudo se vuelven expertos en leerlos trabajando con volcados de núcleo o depurando desde el panel frontal.

Ejemplo de una función en representación hexadecimal del código máquina x86-64 para calcular el enésimo número de Fibonacci , donde cada línea corresponde a una instrucción:

89f885 y siguientes74 2683 y siguientes 0276 1c89f9ba 01 00 00 00ser 01 00 00 008d 04 1683 f9 0274 0d89 d6c989c2f0b8 01 00 00c3

lenguaje ensamblador

Los lenguajes de segunda generación proporcionan un nivel de abstracción además del código de máquina. En los primeros días de la codificación en computadoras como TX-0 y PDP-1 , lo primero que hicieron los piratas informáticos del MIT fue escribir ensambladores. [7] El lenguaje ensamblador tiene poca semántica o especificación formal, siendo solo un mapeo de símbolos legibles por humanos, incluidas direcciones simbólicas, 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 llamado mnemotécnico. [8] Los ensambladores producen archivos de objetos que pueden vincularse con otros archivos de objetos o cargarse por sí solos.

La mayoría de los ensambladores proporcionan macros para generar secuencias comunes de instrucciones.

Ejemplo: la misma calculadora de números de Fibonacci que la anterior, pero en lenguaje ensamblador x86-64 usando la sintaxis de AT&T :

fib: movl %edi , %eax ; poner el argumento en %eax testl %edi , %edi ; ¿es cero? je .return_from_fib ; sí - devuelve 0, que ya está en %eax cmpl $2 , %edi ; ¿2 es mayor o igual que él? jbe .return_1_from_fib ; sí (es decir, es 1 o 2): devuelve 1 movl %edi , %ecx ; no, póngalo en %ecx, para usarlo como contador movl $1 , %edx ; el número anterior de la secuencia, que comienza como 1 movl $1 , %esi ; el número anterior a ese, que también comienza como 1 .fib_loop: leal ( %rsi , %rdx ), %eax ; poner la suma de los dos números anteriores en %eax cmpl $2 , %ecx ; ¿El contador es 2? je .return_from_fib ; sí, %eax contiene el resultado movl %edx , %esi ; haga que el número anterior sea el número anterior al anterior decl %ecx ; disminuir el contador movl %eax , %edx ; convierte el número actual en el número anterior jmp .fib_loop ; continúa .return_1_from_fib: movl $1 , %eax ; establezca el valor de retorno en 1 .return_from_fib: ret ; devolver                                                             

En este ejemplo de código, los registros del procesador x86-64 se nombran y manipulan directamente. La función carga su argumento de 32 bits de %ediacuerdo con la interfaz binaria de la aplicación System V para x86-64 y realiza su cálculo manipulando valores en los registros %eax, %ecx, %esiy %edihasta que finaliza y regresa. Tenga en cuenta que en este lenguaje ensamblador, no existe el concepto de devolver un valor. Una vez almacenado el resultado en el %eaxregistro, nuevamente de acuerdo con la interfaz binaria de la aplicación System V, la retinstrucción simplemente elimina el elemento superior de 64 bits de la pila y hace que la siguiente instrucción se obtenga de esa ubicación (esa instrucción suele ser la instrucción inmediatamente después del que llamó a esta función), con el resultado de la función almacenado en %eax. 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 ningún concepto de función); estos se definen mediante una interfaz binaria de aplicación , como System V ABI para un conjunto de instrucciones en particular.

Compare esto con la misma función en C :

fib int sin signo ( int sin signo n ) { if ( ! n ) { return 0 ; } más si ( n <= 2 ) { return 1 ; } else { unsigned int f_nminus2 , f_nminus1 , f_n ; for ( f_nminus2 = f_nminus1 = 1 , f_n = 0 ; ; - n ) { f_n = f_nminus2 + f_nminus1 ; si ( n <= 2 ) { return f_n ; } f_nmenos2 = f_nmenos1 ; } } }                                                         

Este código es similar en estructura al ejemplo en lenguaje ensamblador, pero existen diferencias significativas en términos de abstracción:

Estas abstracciones hacen que el código C sea compilable sin modificaciones en cualquier arquitectura para la que se haya escrito un compilador de C. El código del lenguaje ensamblador x86 es específico de la arquitectura x86-64 y la interfaz binaria de la aplicación System V para esa arquitectura.

Programación de bajo nivel en lenguajes de alto nivel.

A finales de los años 1960 y 1970, se introdujeron lenguajes de alto nivel que incluían cierto grado de acceso a funciones de programación de bajo nivel, como PL/S , BLISS , BCPL , ALGOL extendido y ESPOL (para sistemas grandes de Burroughs ) y C. . Un método para esto es el ensamblado en línea , en el que el código ensamblador está incrustado en un lenguaje de alto nivel que admite esta característica. Algunos de estos lenguajes también permiten directivas de optimización del compilador dependientes de la arquitectura para ajustar la forma en que un compilador usa la arquitectura del procesador de destino.

Aunque un lenguaje como C es de alto nivel, no abstrae por completo la capacidad de gestionar la memoria como otros lenguajes. [9] En un lenguaje de alto nivel como Python, el programador no puede acceder directamente a la memoria debido a las abstracciones entre el intérprete y la máquina. Por lo tanto, C puede permitir un mayor control al exponer herramientas de administración de memoria a través de herramientas como la asignación de memoria (malloc). [10]

Además, como se mencionó anteriormente, el siguiente bloque de C proviene del compilador GNU y muestra la capacidad de ensamblaje en línea de C. Según la documentación de GCC, esta es una copia simple y un código de adición. Este código muestra la interacción entre un lenguaje generalmente de alto nivel como C y su contraparte de nivel medio/bajo, el ensamblador. Aunque esto puede no convertir a C en un lenguaje nativo de bajo nivel, estas funciones expresan las interacciones de una manera más directa. [11]

int fuente = 1 ; int horario ;     asm ( "mov %1, %0 \n\t " "agregar $1, %0" : "=r" ( dst ) : "r" ( src ));         printf ( "%d \n " , horario de verano ); 

Referencias

  1. ^ abc "3.1: Estructura de programas de bajo nivel". Mano de obra LibreTexts . 2021-03-05 . Consultado el 3 de abril de 2023 .
  2. ^ "¿Qué es un lenguaje de bajo nivel?". Geeks para Geeks . 2023-11-19 . Consultado el 27 de abril de 2024 .
  3. ^ "¿Idioma de bajo nivel? Lo que necesita saber | Lenovo EE. UU.". www.lenovo.com . Consultado el 27 de abril de 2024 .
  4. ^ "Lenguajes de bajo nivel - Clasificación de lenguajes de programación y traductores - AQA - Revisión de informática de GCSE - AQA". BBC Tamaño del bocado . Consultado el 27 de abril de 2024 .
  5. ^ "Generación de lenguajes de programación". Geeks para Geeks . 2017-10-22 . Consultado el 27 de abril de 2024 .
  6. ^ "¿Qué es una generación de idiomas?". www.computerhope.com . Consultado el 27 de abril de 2024 .
  7. ^ Levy, Stephen (1994). Hackers: héroes de la revolución informática . Libros de pingüinos. pag. 32.ISBN 0-14-100051-1.
  8. ^ "Lenguaje de máquina/lenguaje ensamblador/lenguaje de alto nivel". www.cs.mtsu.edu . Consultado el 27 de abril de 2024 .
  9. ^ Kernighan, Brian W.; Ritchie, Dennis M. (2014). El lenguaje de programación C. Serie de software Prentice-Hall (2. ed., 52. edición impresa). Upper Saddle River, Nueva Jersey: Prentice-Hall PTR. ISBN 978-0-13-110362-7.
  10. ^ "malloc(3) - página del manual de Linux". man7.org . Consultado el 21 de abril de 2024 .
  11. ^ "Asm extendido (usando la colección de compiladores GNU (GCC))". gcc.gnu.org . Consultado el 27 de abril de 2024 .