¿Cómo se organizan en memoria los "objetos" y las "clases" OOP en términos de lenguaje ensamblador?

13

¿Cómo se organizan los objetos en la memoria?

Por ejemplo, sé que una función es un fragmento de código en la memoria, que espera parámetros a través de la pila y / o los registros y maneja su propio marco de pila.

Pero los objetos son una estructura mucho más complicada. ¿Cómo se organizan? ¿Cada objeto tiene "enlaces" a los métodos y se pasa la dirección a ese método?

Sería genial ver una buena explicación de este tema.

UPD Hice la pregunta más exacta, y estoy principalmente interesado en escribir idiomas estáticamente.

Nikolai Golub
fuente
44
Puede variar enormemente entre diferentes idiomas, especialmente entre los idiomas de tipo dinámico y los de tipo estático. ¿Puede limitar su pregunta a los idiomas OO que más le interesan?
Bart van Ingen Schenau
He actualizado la pregunta, por lo que creo que los idiomas escritos dinámicamente son más difíciles de entender.
Nikolai Golub

Respuestas:

17

Si no hay un despacho dinámico (polimorfismo), los "métodos" son solo funciones azucaradas, quizás con un parámetro adicional implícito. En consecuencia, las instancias de clases sin comportamiento polimórfico son esencialmente C structs con el propósito de generar código.

Para el despacho dinámico clásico en un sistema de tipo estático, básicamente hay una estrategia predominante: vtables. Cada instancia obtiene un puntero adicional que se refiere a (una representación limitada de) su tipo, lo más importante: vtable: una matriz de punteros de función, uno por método. Como se conoce el conjunto completo de métodos para cada tipo (en la cadena de herencia) en tiempo de compilación, se pueden asignar índices consecutivos (0..N para N métodos) a los métodos e invocarlos buscando el puntero de función en vtable usando este índice (pasando nuevamente la referencia de instancia como parámetro adicional).

Para lenguajes más dinámicos basados ​​en clases, típicamente las propias clases son objetos de primera clase y cada objeto tiene una referencia a su objeto de clase. El objeto de clase, a su vez, posee los métodos de una manera dependiente del lenguaje (en Ruby, los métodos son una parte central del modelo de objetos, en Python son solo objetos de función con pequeños envoltorios a su alrededor). Por lo general, las clases también almacenan referencias a sus superclases y delegan la búsqueda de métodos heredados a esas clases para ayudar a la metaprogramación que agrega y altera los métodos.

Hay muchos otros sistemas que no se basan en clases, pero difieren significativamente, por lo que solo elegiré una alternativa de diseño interesante: cuando puede agregar nuevos (conjuntos de) métodos a todos los tipos a voluntad en cualquier parte del programa ( ej. clases de tipo en Haskell y rasgos en Rust), el conjunto completo de métodos no se conoce durante la compilación. Para resolver esto, uno crea una vtable por rasgo y los pasa cuando se requiere la implementación del rasgo. Es decir, código como este:

void needs_a_trait(SomeTrait &x) { x.method2(1); }
ConcreteType x = ...;
needs_a_trait(x);

se compila a esto:

functionpointer SomeTrait_ConcreteType_vtable[] = { &method1, &method2, ... };
void needs_a_trait(void *x, functionpointer vtable[]) { vtable[1](x, 1); }
ConcreteType x = ...;
needs_a_trait(x, SomeTrait_ConcreteType_vtable);

Esto también significa que la información de vtable no está incrustada en el objeto. Si desea referencias a una "instancia de un rasgo" que se comportará correctamente cuando, por ejemplo, se almacene en estructuras de datos que contienen muchos tipos diferentes, se puede crear un puntero grueso (instance_pointer, trait_vtable) . Esto es en realidad una generalización de la estrategia anterior.


fuente
5

Esta es la respuesta en el sentido del proverbio "si le das a un hombre un pez lo alimentas por un día, mientras que si le enseñas a pescar lo alimentas de por vida", ya que tu pregunta es muy amplia

1. investigar fuentes de información abiertas

Google para "programación orientada a objetos de ensamblaje" enumera muchos recursos relevantes diferentes.

Por ejemplo, la programación orientada a objetos en la asamblea, Ethan J. Eldridge, 15 de diciembre de 2011 llegó como tercer enlace y se ve bien

2. aprender del código escrito a mano existente

Puede ver cómo funciona al estudiar los códigos fuente escritos con algunos lenguajes ensambladores populares con OOP declarada explícitamente

3. Aprender de los patrones de código generados por los compiladores.

Puede ver cómo funciona al estudiar los archivos de lenguaje ensamblador intermedio producidos por los compiladores OOP de su elección. Los compiladores de C ++ y FreePascal se pueden configurar para que pueda ver cómo se ve la transcripción del código OOP de alto nivel en el código del lenguaje ensamblador

4. resuelve el rompecabezas con tu sentido común

Ahora es demasiado tarde ya que ya conoce las sugerencias de otras respuestas. Pero antes de que Internet fuera tan fácil de buscar y antes de que hubiera sitios donde pudiera obtener su respuesta sin ningún esfuerzo en varias horas de forma gratuita por parte de algún voluntario que lo aprendió de la manera difícil, el único método de trabajo disponible de forma gratuita para todos fue

Pregúntese: "¿cómo lo implementaría?"

Muy a menudo, después de varios días del proceso de pensamiento de fondo en su mente y después de descartar varios diseños de borrador en papel, descubrirá que la solución que encontró es muy similar a la solución que otros programadores idearon y ya implementaron


Ahora mi respuesta se basa en la opinión, no responde directamente a la pregunta de OP y los usuarios de alto rango de alta reputación pueden votarme libremente

xmojmr
fuente