Pero los 4 bits adicionales siguen siendo los supuestos por el procesador al multiplicar por 0x10, ¿no?
No. Por eso son precisos dos registros..
Uno indica el segmento (por ejemplo CS) y el otro el desplazamiento (por ejemplo IP)
Además no vale cualquier pareja de registros. Cada registro de segmento admite unos específicos. Esto tiene que ver con la arquitectura del procesador.
Entonces es una convencion historica... lo supuse, en realidad me parecia poco eficiente considerando otras posibilidades.
Me atrevo a afirmar que el ser humano sacrifica su propio rendimiento por comodidad. Nuestra voluntad en contra de ella misma.
Bueno, es una licencia decirlo así...
El que inventa algo, lo hace como considera mejor (sea mejor por la economía, por los medios disponibles o por cualquier otra razón) en ese preciso momento.
Es muy fácil criticar 20, 50, ...x años después que hubiera sido mejor de esta u otra manera. Cuanto todo estaba oscuro y no había nada en lo que basarse para empezar, cualquier paso dado será el primero, si luego resulta problemático se supone que aprenderán y mejorarán.
1234h:0004h y
1233h:0014h
Calculando las direcciones:
12340h+04h=12344h y
12330h+14h=12344h
Segun Wikipedia: ...
Imagina que el sistema operativo carga los datos de un proceso A en el segmento 1233h y lo marca como pertenenciente al proceso A.
Luego, el segmento inmediatamente siguiente es 1234h, e imaginemos que aqui se cargan los datos de un proceso B.
Si el proceso A accede a sus datos, ¿no estaria accediendo a los datos del proceso B tambien?
A estas alturas (si leíste el enlace de mi anterior mensaje) ya sabes que hay 4096 pares de combinaciones para referirse a una misma dirección, es decir se estarían refiriendo al mismo segmento.
Ahora bien tu partes de una suposición (digamos) errónea... El sistema operativo, cuando asigna un segmento a un proceso, lo marca como ocupado (lleva control de ello en una estructura de datos), luego no va a asignar a otro proceso el mismo (o parcialmente el mismo) segmento.
Hay muchos algoritmos para el manejo de la memoria... Cuando funcionan bien se les supone libre de dichos errores. es lo mismo que si tu tuvieras un array y en un índice guardaras tal o cual dato y más adelante por error lo sobrescribieras por otro dato, sin pretender borrar el que estaba ahí antes. Se supone que cuando ese programa salga a la luz, habrás corregido el error, tan pronto te dieras cuenta...
Tiene que haber una manera de resolver esto, sin embargo no se me ocurre mas nada aparte del problema.
Básicamente se recurre a estructuras de árbol.
Hay varias estrategias, te expongo brevemente algunas ideas:
Al principio el árbol tiene (idealmente) toda la memoria libre, que ha particionado en x tamaño y asigna cada parte a un nodo de un árbol binario. Cada nodo tiene un estado para indicar libre u ocupado y si está ocupado cuanto está ocupado. En este árbol binario, solo los nodos terminales mantiene los datos, los nodos internos podrían considerarse como enrutadores rápidos, solo dispondran de datos muy simples que podrían (interesa que así sea) reflejar el total, pero sin disponer de las direcciones, datos que solo recáe en los nodos terminales.
Luego un proceso se inicia y requiere x espacio, entonces el árbol busca un nodo que disponga de ese tamaño. Si el nodo raíz indica que ese tamaño existe, revisa si su hijo izquierdo para ver si lo contiene, si no el hijo derecho. Y así va sucesivamente descendiendo hasta el primer nodo que diga tener ese espacio libre, el nodo padre señala señala siempre el espacio libre de sus dos hijos, de modo que no hace falta explorar una rama si un padre declara que en su descendencia no hay memoria libre.
El nodo terminal proporciona la dirección física donde comienza ese espacio y la cantidad disponible.
Un S.O. podria asignar todo el espacio que señala que controla el nodo o bien podría asignar solo la imprescindible ocupada, con lo que partiría el nodo en dos nodos, a la derecha el nodo con la dirección y el tamaño ocupado, al que marca ocupado y a la derecha el resto de memoria que ocupa ese padre, con la dirección y cantidad libre... como se ha tomado x memoria, a cada padre subiendo va descontando ese dato de 'libre'.
Si no basta un solo nodo para satisfacer la memoria requerida buscará si hay nodos contiguos con suficiente memoria libre, lo que complica la estructura, pués debe ser eficiente en cuanto a búsquedas. Pero ya sabemos que para eso basta consultar a algún padre...
Una de las operaciones de este tipo de estructuras debe ser la capacidad de mover datos de un lado de la memoria a otro precisamente para unificar memoria libre dispersa.
Inversamente a cuando se ocupa la memoria, cuando se libera, se accede al nodo hijo cuya memoria está contenido, se le marca libre e informa ascendentemente de la cantidad añadida.
Estos algoritmos tienen que hilar muy fino, pués el rendimiento de todo el sistema puede depender de su eficacia.
...y en definitiva el S.O. no va a entregar a sendos procesos un mismo espacio de memoria. Ten en cuenta además que los procesadores de hoy día disponen de muchas más intrucciones diseñadas explícitamente para el S.O. que hace 20, 30 ó 40 años.