simulador segmentación paginada

Iniciado por josperz, 23 Julio 2018, 02:37 AM

0 Miembros y 1 Visitante están viendo este tema.

josperz

buenas, alguno no tendrá un ejemplo a nivel de código o un simulador de segmentación paginada??

Serapis

¿Puedes indicar que necesitas más en específico?

josperz

Cita de: NEBIRE en 23 Julio 2018, 20:44 PM
¿Puedes indicar que necesitas más en específico?

específicamente eso, un simulador de administración de memoria por medio de segmentación paginada

Serapis

#3
Es que el tema resulta trivial...

Sea el caso del procesador 8086, el bus de datos es de 16bits, en tanto que el bus de direcciones es de 20bits.
Mientras que 16 bits direccionan 65.536 posiciones de memoria, 4 bits más (es decir 20bits), direccionan 1Mb.
Si divides 1Mb. entre los 64kb. tienes 16, que son el número de páginas que tiene 1Mb. 16 páginas son precisamente los valores que codifican 4bits.

Asi a las direcciones se les antepone el código de página:

pagina: Dirección16bits    
0000:0000.0000-0000.0000
Y ya con los 20 bits se obtiene la dirección absoluta.
La dirección de 16bits, es relativa en la página, es decir, va desde 0 hasta 65.535.
Pongamos que la página es la 5 y pongamos que la dirección en la pagina es 22.222,
la dirección real se calcula como::
nºpagina x 65.536 + direccion relativa
Y que por tanto, para el jemplo será:
5*65.536 + 22.222 = 327.680 + 22.222 = 349.902
Igualmente puede ponerse en binario (por ejemplo en la calculadora) y luego pasarlo a decimal
página 5: Dir relativa; 22.222
0101:0101.0110-1100.1110 = 349.902

Esto sería como tener un mazo de 16 cartas, donde cada una de ellas representara 64kb.
Esto de más arriba, sin embargo es la explicación ideal...
...es decir la entrada para poder empezar a entender como es realmente.

A la página se le llama segmento y a la dirección relativa, desplazamiento..
Puesto que los registros en el 8086, son de 16 bits, incluído el registro IP.
La solución adoptada, aunque ingeniosa estuvo limitando la accesibilidad a la memoria, dejando en hándicap al PC frente a otros procesadores... y así se crearon los llamados registros de segmento.
La dirección física se compone realmente de dos registros:
El de segmento, y uno de propósito general que formaliza el 'offset' (desplazmaiento dentro del segmento).
En la explicación ideal, si se mira bien, si se repara lo suficiente, presenta un problema y es que como toma 64kb.
exige que un bloque de un programa tenga que coincidir alojado exactamente en un segmento. Es decir resulta un problema si parte de un programa cae en un bloque y parte en otro, pués un único segmento no basta para acceder al programa.
Aprovechando que también los registros de segmento eran igualmente de 16 bits, se eligió otro modelo, y es el que explico a continuación:
El de segmento queda desplazado 4 posiciones hacia arriba (es como si fuera de 20,  donde los 4 bits de menor peso estuvieren a 0), pero naturalmente el resto de los bits de ese registro pueden tener un valor arbitrario (no solo los 4 bits de menor peso).
Esto permite que pueda ubicarse en cualquier punto de la memoria (congruente con 16) el comienzo del bloque de 64kb.
Pero ahora en vez de haber 16 páginas de 64kb. ahora hay 64k.páginas de 16 bytes.
Esto permite que haya muchos pares segmento:desplazamiento (4096 exactamente, 65536/16=4096) que apunten a una misma dirección de memoria.

Ejemplo:
A - Registro de segmento:  
1000.0010-0011.0101 = 33.333
1000.0010-0011.0101*16= 533.328
1000.0010-0011.0101-0000 nótese el desplazamiento a la izquierda de 4 bits.

B - desplazamiento:
0101.0110-1100.1110 =  22.222

C - Dirección física: 533.328 + 22.222 = 555.550

1000.0010-0011.0101-0000
------0101.0110-1100.1110
-----------------------------------
1000-0111.1010-0001.1110 = 555.550

Haz si quieres las cuentas en hexadecinal que cada nibble es una cifra, y se ve mejor...

Y si lo has seguido hasta aquí, te invito a que pongas los bits altos del registro de segmento a 1 y verifiques a qué dirección de memoria estaríamos accediendo???
Por lo demás el cálculo real sigue siendo el explicado en el razonamiento ideal...

En fin, no hace falta mucho código, simplemente un array y un par de 'registros'... y alguna funcionalidad de lectura y/o escritura...

Envió antes que caduque la sesión y me edito luego... con algo de código de ejemplo.

Código (vb) [Seleccionar]

' El integer de VB6 no es 'unsigned', así que lo emulamos...
Private Type UInteger
   Bajo        As Byte     ' bits 0-7   ' podría acederse de este modo fácilmente a AH y AL, etc...
   Alto        As Byte     ' bits 8-15
End Type


Private Const c_MegaByte = (2 ^ 20)                         ' 1Mb.
Private Const c_Pagina = (2 ^ 16)                           ' 64Kb.

' 1Mb. de memoria.
Private s_Memoria(0 To c_MegaByte - 1) As Byte


Private s_DirFisica             As Long

Private p_RegAX                 As UInteger  ' registros de 16 bits.
Private p_RegIP                 As UInteger
Private p_RegCS                 As UInteger



Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)



Private Property Get Segmento() As UInteger
    Segmento = p_RegCS
End Property
   Private Property Let Segmento(ByRef X As UInteger)
       p_RegCS = X
       Call CalculaDireccionFisica
   End Property

Private Property Get IP() As UInteger
    IP = p_RegIP
End Property
   Private Property Let IP(ByRef X As UInteger)
       p_RegIP = X
       Call CalculaDireccionFisica
   End Property

Private Property Get AX() As UInteger
    AX = p_RegAX
End Property
   Private Property Let AX(ByRef X As UInteger)
       p_RegAX = X
   End Property

Private Property Get DireccionFisica() As Long
   DireccionFisica = s_DirFisica
End Property


Private Sub CalculaDireccionFisica()
   Dim X As Long
   
   s_DirFisica = 0 ' al tener 4 bytes, primero los borramos todos...
   Call CopyMemory(s_DirFisica, ByVal VarPtr(p_RegCS), 2)
   Call CopyMemory(X, ByVal VarPtr(p_RegIP), 2)
   s_DirFisica = ((s_DirFisica * 16) + X)
End Sub


Private Function StringToUInteger(ByRef Txt As String) As UInteger
   Dim v As UInteger
   Dim k As Long
   
   k = Val(Txt)
   v.Bajo = (k And 255)
   v.Alto = (k \ 256)
   
   StringToUInteger = v
End Function



Private Sub Command1_Click()
   Segmento = StringToUInteger(Text1.Text)
   IP = StringToUInteger(Text2.Text)
   
   Text3.Text = DireccionFisica
End Sub

Private Sub Command2_Click()
   Dim v As UInteger
   
   AX = StringToUInteger(Text4.Text)
   
   s_Memoria(s_DirFisica) = AX.Bajo
   s_Memoria(s_DirFisica + 1) = AX.Alto
End Sub


Añade 3 textbox, con sendos labels, el textbox1 será el de 'segmento' y sí poner en el label, eñ textbox 2, será el desplazamiento, para el eejemplo la dirección IP, el tercer textbox, la dirección física.
Añade un bótón, introduce de entrada los valores de más arriba que puse d eejmplo: Segmento: 33.333 y desplazamiento 22.222, y a la vuelta en el textbox 3 tendrás el valor de la dirección física real.

Usa ese valor como índice en el array s_Memoria...

Solo resta indicar que si bien la memoria del 8086 son direcciones de 16bits... y el array está declarado en bytes... debemos acceder individualmente a cada byte (como señala el código dle 2º botón, o bien usar copymemory).

Añade un segundo boitón y un 4º textbox... con su label 'Valor', introduce un valor en el rango 0-65535 en el textbox4, y pulsa el botón 2, escribirá en la memoria dicho valor...

Puedes si quieres al iniciar el formulario, relenar con valores al azar el array y añadir un botón para leer de la memoria actual, el valor que contiene...
Podrías también añadir un avance del registro IP en 2 posiciones ...

En fin, como has sido parco en palabras, no he podido orientar el código convenientemente... si tratas de hacer algún emulador, ya tienes por donde tomarlo...