Punteros y modelos de memoria
Hace un par de días sufrí en propias carnes algo que nadie jamás me había explicado hasta ese momento: La diferencia entre los punteros near y los punteros far. Resulta que un puntero far ocupa cuatro bytes porque guarda el segmento (2bytes) y el offset (otros 2bytes), mientras que un puntero near sólo ocupa dos bytes porque sólo guarda el offset.¿Qué significa esto? Que con un puntero near NO puedes acceder a otro segmento distinto al que estás usando. Curioso...
(Para los que no sepan de qué hablo: un puntero es mas o menos como una variable, pero en vez de guardar un valor (’2’, ’3’, "patata") guarda otra dirección de memoria (04E6,0000 por ejemplo)).
Otra cosa importante es el modelo de memoria elegido. Esto representa el modelo de "cómo" accederá a memoria el compilador. En TurboC podemos elegir entre Tiny, Small, Medium, Compact, Large y Huge. Estos se diferencian en los tamaños de los segmentos de código, datos y pila, y en el tipo de los punteros. Podría explicarlo en modo texto pero se ve más claro en una tabla:
SEGMENTOS | PUNTEROS | ||||
MODELO | CODIGO | DATOS | PILA | CODIGO | | DATOS | ||
Tiny | 64Kb | near | |||
Small | 64Kb | 64Kb | near | ||
Medium | 1Mb | 64Kb | far | near | |
Compact | 64Kb | 1Mb | near | far | |
Large | 1Mb | 1Mb | far | ||
Huge | 1Mb | 1Mb | far |
Por ejemplo, el modelo Medium se utiliza para programas pequeños que utilizan pocos datos, al contrario que el Compact, que es usado para programas pequeños que utilizan gran cantidad de datos.
Como ejemplo de lo "importante" (pasad por alto la trivialidad del programa de ejemplo xD) que puede llegar a ser esto (habérmelo leído antes me hubiera ahorrado una tarde de programas con comportamientos erráticos), os expongo el ejemplo que me trajo de cabeza a mí. Resulta que el compilador que usamos para esta asignatura, Borland TurboC (sí, algo actual y todo eso) sobre MS-DOS (idem) viene por defecto con el model Small. Y claro, para esto necesitabamos como mínimo Compact (aunque vamos de sobraos y lo recomendado era Huge)
El programa en cuestión consiste en acceder a la memoria de video y escribir directamente en ella para crear un rectángulo con un carácter y todas las variantes de color de carácter y color de fondo. El acceso a la memoria se realiza mediante un puntero, tal que así:
char *p = MK_FP(0xB800, 0x000)
donde MK_FP indica que queremos un puntero far (FP,Far Pointer) y 0xB800, 0x0000 indica el inicio del segmento 0xB800, que es el de video.
Así que, nos ponemos manos a la obra y compilamos/enlazamos/ejecutamos con varios modelos de memoria (esto se puede cambiar desde Options/Compiler/Model en el TurboC)
-Tiny, Small y Medium:
Los "efectos" son variados, desde un warning al compilar ("Conversión sospechosa de puntero"), warning al enlazar ("No hay pila"), error al ejecutar ("Instrucción no permitida") hasta autoabortos:
Bueno, al menos no me salta el antivirus como hace un par de años xD
-Compact, Large y Huge:
Ahora sí que se está accediendo al segmento "bueno" por ser un puntero far, y el resultado es justo el que esperábamos:
¿A que es mono? Pues casi lagrimeo un poco cuando descubrí que mi código era bonito y maravilloso pero que el error estaba en el modelo de memoria elegido. Ahora seguro que ya no se me vuelve a olvidar :D
8 comentarios
Mariella -
Oscar -
Te agradezco lo del código, realmente ando aprendiendo C++ (principiante) y tenía una duda con apuntadores y llegué aquí... y bueno siempre es bueno ver códigos.
Saludos
motagirl2 -
Lo de los canibalizadores es porque el cacho de código en cuestión era una práctica de la universidad, y no da gusto que tras pegarte el curro alguien llegue y presente el mismo código pero con su nombre...
Te lo envío al correo si quieres.
Oscar Rovira -
hubiera sido bueno tener el código.
Saludos.
p.d. no estoy muy de acuerdo con lo de los "canibalizadores" de código.
realmente hablas de un pequeño código y no de un programa y aún así y para irnos lejos y no hacer tan grande la p.d... Basta con ver linux GNU... un buen open source no?..
saludos
motagirl2 -
Tú -
Voy a revisar mis programillas con punteros, porque yo también programaba con el TurboC de borland, y no entiendo por qué no me petó nunca ninguno si por defecto te viene small.
P.D. Compact para mostrar el cuadro de coloreh? se pué ver el código fuente?
ajota -
effervescente -
Nos vemos :*