¿Por qué este código de ensamblador hace más que simplemente lgdt?
Entonces, estoy comenzando el desarrollo de un kernel hobby x86_64 y encontré este código para cargar la GDT (Tabla de Descriptores Global), pero no entiendo qué hace.
load_gdt:
lgdt [rdi]
mov ax, 0x10
mov ss, ax
mov ds, ax
mov es, ax
mov rax, qword .trampoline
push qword 0x8
push rax
o64 retf
.trampoline:
ret
Sé que carga el descriptor de mi GDT desde el registro rdi (registro del primer parámetro de una llamada de función en el abi de sysv), pero no sé por qué tengo que establecer todos los registros de segmento en 0x10 y qué magia negra está haciendo el resto.
davy.ai
La función
load_gdt
carga la GDT (Tabla Global de Descriptores) utilizando la instrucciónlgdt
para cargar el descriptor de la GDT desde la ubicación de memoria indicada por el registrordi
.Después de esto, los registros de segmento (
ss
,ds
,es
) se establecen en0x10
. Esto se debe a que la GDT se inicializa con dos entradas, una para el segmento de código del kernel y otra para el segmento de datos del kernel, ambos con una dirección base de 0 y un límite de 0xFFFFFFFF. El valor0x10
corresponde al selector del segmento de código del kernel, que es la segunda entrada en la GDT.Las siguientes instrucciones configuran un “trampolín” para saltar al punto de entrada del kernel. El registro
rax
se establece en la ubicación de memoria de la etiquetatrampoline
y se coloca en la pila, junto con el valor0x8
. Esto configura la pila en preparación para un salto lejano al punto de entrada del kernel. Finalmente, la instrucciónretf
realiza el salto lejano al trampolín, que luego salta al punto de entrada del kernel.En resumen, este código configura la GDT y se prepara para el salto al punto de entrada del kernel. Los registros de segmento se establecen en el selector del segmento de código del kernel en la GDT, y se configura un trampolín para realizar el salto lejano al punto de entrada del kernel.