tutorial - qué función ejecuta set_gfx_mode en c++?
¿Cómo se hacen las bibliotecas de bajo nivel? (6)
Cuando voy y hago una aplicación de C ++, generalmente uso bibliotecas como SDL o WxWidgets etc. Pero si tuviera que hacer una biblioteca, ¿necesitaría usar una biblioteca para hacer una biblioteca? ¿O puedo hacer que toda la biblioteca esté basada en el código C ++ principal, es esto posible?
Mi punto es que debe haber un punto en el que una biblioteca no tenga nada en que basarse, por lo que las únicas cosas que puede usar son el núcleo C ++.
¿Estoy en lo cierto con esta teoría? Si no, ¿cómo se hacen realmente las bibliotecas de bajo nivel?
(Sé que esta es una pregunta amplia, pero soy una persona muy curiosa que necesita respuestas y esto es algo que me ha molestado).
Cuando voy y hago una aplicación de C ++, generalmente uso bibliotecas como SDL o wxWidgets, etc. Pero si tuviera que hacer una biblioteca, ¿necesitaría usar una biblioteca para hacer una biblioteca? ¿O puedo hacer que toda la biblioteca esté basada en el código C ++ principal, es esto posible?
Sí.
Mi punto es que debe haber un punto en el que una biblioteca no tenga nada en que basarse y, por lo tanto, las únicas cosas que puede usar son el núcleo C ++.
No.
C y C ++ son ejemplos de lenguajes de tercera generación . Como tales, intentan ocultar muchos detalles de implementación a nivel de sistema. Subyacente a la capa del lenguaje de programación de tercera generación (3GL) se encuentra un lenguaje de programación de segunda generación (2GL), como el ensamblaje x86 ; debajo de esto tenemos instrucciones de código de máquina.
Como ya se ha , puede implementar una biblioteca de C ++ en C ++ puro. Sin embargo, las bibliotecas del sistema (especialmente aquellas para controlar dispositivos) pueden estar y, a menudo, se escriben en un ensamblador. Y, en general, una biblioteca también podría escribirse en COBOL o Fortran o incluso en Brainfuck .
Son los procesos de ensamblador / compilador / vinculador los que realmente convierten los códigos 2GL/3GL
en una library
que se puede vincular en C ++.
Aquí hay un pequeño ejemplo de un programa en C, blah.c
, que no se enlaza con bibliotecas de tiempo de ejecución estándar, pero aún se las arregla para imprimir cosas utilizando una función en una biblioteca propietaria, libfoo.a,
escrita en el x86 assembler
:
blah.c:
/*-----------------------------------------------
blah.c
Invokes some assembly
------------------------------------------------*/
void _start()
{
char sz[]={"oOoook/n"};
foo(sz,sizeof(sz));
byebye();
}
foo.asm:
;----------------------------------------------------------------------------
;Some foo assembly: exposes system write & exit
;----------------------------------------------------------------------------
SECTION .text
global foo
global byebye
foo:
push ebp
mov ebp,esp
mov edx, [ebp+12]
mov ecx, [ebp+8]
mov ebx,1
mov eax,4 ;syscall for __NR_write
int 0x80 ;service interrupt
mov esp,ebp
pop ebp
mov eax,0
ret
byebye:
mov ebx,0
mov eax,1 ;syscall for __NR_exit
int 0x80 ;service interrupt
ret
Y así es como está construido:
$ nasm -felf -ofoo.o foo.asm
$ ar rs libfoo.a foo.o
$ gcc -L. -oblah blah.c -lfoo -nostartfiles -nostdlib -nodefaultlibs
$ ./blah
oOoook
$
Como se puede ver, la biblioteca hace uso de llamadas al sistema (en este caso, al kernel de linux
); lo que por cierto, también puede ser implementado por terceros.
En el núcleo, las bibliotecas son solo colecciones de clases. Pueden basarse en otras bibliotecas para ampliarlas o proporcionar el núcleo a una biblioteca nueva por completo. Podría crear su propia biblioteca simplemente utilizando el código C ++, por ejemplo, una biblioteca de gráficos que aprovecha la API de Windows, una biblioteca de chat / comunicaciones que amplía las bibliotecas de socket disponibles, etc. Tiene razón al decir que las bibliotecas utilizan el C ++ básico. funcionalidad
Hay tres tipos de bibliotecas:
- bibliotecas que hace llamadas al sistema
- Bibliotecas que implementan llamadas a funciones extranjeras.
- bibliotecas que pueden escribirse o reescribirse en el núcleo C ++ (por ejemplo, excluyendo la extensión asm)
Las bibliotecas que realizan llamadas al sistema generalmente no pueden escribirse en el lenguaje en sí, ya que depende de las particularidades de la convención de llamadas al sistema, que generalmente implica realizar una captura o interrupción en el kernel, para provocar un cambio a un anillo de privilegios más bajo . No hay facilidad en C ++ puro para generar una trampa / interrupción; la API del sistema operativo normalmente utiliza extensiones de ensamblaje para hacerlo.
La segunda categoría son las bibliotecas que realizan o reciben convenciones de llamadas extranjeras; Podría decirse que la llamada al sistema es una subcategoría de esto, pero la llamada al sistema es claramente diferente, ya que la llamada al sistema requiere un interruptor de llamada de privilegio, mientras que las llamadas externas no lo hacen. La convención de llamadas extranjeras normalmente también se escribe en asamblea.
Todas las demás bibliotecas que no impliquen cambio de anillo o convención de llamada extranjera siempre se pueden escribir en C ++; aunque a veces no lo son, generalmente con fines de rendimiento (por ejemplo, la biblioteca de matemáticas se incluye en esta categoría).
En cualquier caso, las bibliotecas que caen dentro de las dos categorías anteriores generalmente también tienen un gran cuerpo de código escrito en C ++ puro que no hace más que envolver la API de la llamada al sistema / llamada extranjera en una forma que sea más familiar para las herramientas y programadores de C ++. (por ejemplo, archivos de encabezado y otras utilidades de conveniencia).
Las bibliotecas de bajo nivel acceden a los recursos del hardware y del sistema a través de las bibliotecas proporcionadas por el sistema operativo. El propio sistema operativo y los controladores cargados por él utilizan el ensamblaje y leen / escriben las direcciones de memoria predefinidas para modificar el estado de la CPU y comunicarse con el hardware.
Una biblioteca que solo depende de C++ solo puede ser una biblioteca de utilidad, ya que cualquier comunicación con el hardware o usuario implicaría un ensamblaje o una biblioteca adicional. Un ejemplo de una biblioteca C ++ pura sin dependencias sería una biblioteca matemática, ya que no requiere E / S ni acceso a hardware.
Las bibliotecas no son más que otro código con el que puedes vincular tu código. No hay nada mágico o especial en ellos. Puedes tomar las funciones que has escrito y convertirlas en una biblioteca. Entonces la pregunta realmente es: ¿puedes hacer cosas de bajo nivel solo en C ++ o tienes que hacer algo más? Bueno, ahí es donde entra la respuesta de Lie Ryan. Puedes escribir tu programa, haz lo que quieras, solo con el código C ++. Puede hacer llamadas al sistema y puede vincular en otros idiomas (ensamblaje, por ejemplo) que hacen cosas que no pueden hacer en C ++ pero que deben hacer.
Al final, todo esto se reduce a código de máquina y hardware. Cualquier lenguaje o método deseado o requerido para obtener ese código de máquina o algo funcionalmente igual, está dentro del ámbito de las posibilidades. Quizás no siempre sea lo más inteligente usar innecesariamente asm o no usar una llamada al sistema, etc.
Hay grandes cantidades de bibliotecas de código abierto que son similares a las que se mencionan, en las que puede simplemente mirar el código para ver cómo lo hicieron. Y no hay nada que diga que la manera en que una entidad implementó algo es la única manera de hacerlo.
SDL y wxWidgets son bibliotecas que abstraen los detalles de los sistemas subyacentes.
Para proporcionar una funcionalidad similar (gráficos, sonido, entrada), necesitaría codificar directamente contra la API de Windows en Windows, Cocoa en Mac OS X y en Unix, directamente contra POSIX API y X11 (usando XCB , Xlib o protocolo sin formato X11).