Page 1 of 1

Multitasking problem

Posted: Mon Jul 07, 2003 11:00 pm
by pepito
I am writing the process manager for my OS. By now I can switch from the kernel (ring 0) to a user task (ring 0).But my code fails when I enable paging.

Any idea?

Thank you

pepito

RE:Multitasking problem

Posted: Mon Jul 07, 2003 11:00 pm
by Neo
I could possibly help you further but I would need to see the source code for your process manager.

RE:Multitasking problem

Posted: Mon Jul 07, 2003 11:00 pm
by pepito
Thank you very much!

This is the code that runs well without paging enable:

The OS create a GDT at 0x3800 using code; it creates: null descriptor, lineal descriptor, kernel descriptors, LDT descriptors, and TSS descriptors. Then switch to protected mode.

Next, the OS enable paging (by now skiped), enable A20, map IRQ(es) to INT(es)...

Then, the OS create the first task:

mov ax, desc_TSS_ini ; First TSS descriptor
ltr ax

Finally, the OS creates an user task and jump to it:

mov ax, desc_lineal ; Lineal selector
mov gs, ax ; Load 'gs'

mov ebx, DWORD dir_TSS_ini ; Address to TSS(es)
add ebx, 104 ; Point to second TSS

mov [gs:ebx + 0x00], DWORD 0
mov [gs:ebx + 0x04], DWORD 0
mov [gs:ebx + 0x08], DWORD 0
mov [gs:ebx + 0x0C], DWORD 0
mov [gs:ebx + 0x10], DWORD 0
mov [gs:ebx + 0x14], DWORD 0
mov [gs:ebx + 0x18], DWORD 0
mov [gs:ebx + 0x1C], DWORD 0

lea eax, [tarea_usuario] ; Enter point
mov [gs:ebx + 0x20], eax ; 'eip'
mov [gs:ebx + 0x24], DWORD 0
mov [gs:ebx + 0x28], DWORD 0
mov [gs:ebx + 0x2C], DWORD 0
mov [gs:ebx + 0x30], DWORD 0
mov [gs:ebx + 0x34], DWORD 0

lea eax, [esp-512] ; User stack (temp)
mov [gs:ebx + 0x38], eax ; 'esp'
mov [gs:ebx + 0x3C], DWORD 0
mov [gs:ebx + 0x40], DWORD 0
mov [gs:ebx + 0x44], DWORD 0
mov [gs:ebx + 0x48], WORD desc_kernel_d ; 'es'
mov [gs:ebx + 0x4C], WORD desc_kernel_c ; 'cs'
mov [gs:ebx + 0x50], WORD desc_kernel_d ; 'ss'
mov [gs:ebx + 0x54], WORD desc_kernel_d ; 'ds'
mov [gs:ebx + 0x58], WORD desc_kernel_d ; 'fs'
mov [gs:ebx + 0x5C], WORD desc_kernel_d ; 'gs'
mov [gs:ebx + 0x60], DWORD 0
mov [gs:ebx + 0x64], DWORD 0

jmp desc_TSS_ini+8:0                        ; jump to user task

hlt

The user task just display a message:

tarea_usuario:

mov esi, mensaje_usuario
call mensaje_mp

jmp desc_TSS_ini:0
jmp tarea_usuario ; Repeat the task

This is all!

pepito

(sorry my poor english)

RE:Multitasking problem

Posted: Mon Jul 07, 2003 11:00 pm
by TripleFault
Can you describe the problem that you are having with a little more detail?  Also, are you sure that you are enabling paging correctly?
~ TripleFault !)

RE:Multitasking problem

Posted: Mon Jul 07, 2003 11:00 pm
by pepito
> Can you describe the problem that you are having with a little more detail?

My OS have a line of code that jump from the kernel to an user task:

jmp desc_TSS_ini+8:0

This line fails when I enable paging!

> Also, are you sure that you are enabling paging correctly?

I belive that I am enabling paging correctly.

pepito

RE:Multitasking problem

Posted: Mon Jul 07, 2003 11:00 pm
by pepito
Here is the code I am working on! The follow line is used to skip paging:

; TEMPORAL
jmp inicializar_AT
; TEMPORAL

CODE:

; ------------------------------------------
; ------------------------------------------
; Kernel MISIS 1.0. Multitarea. JAER Mex2003
; ------------------------------------------
; ------------------------------------------

; ---------------------------
; ---------------------------
; Objetos globales y externos
; ---------------------------
; ---------------------------

; ----------------------------------
; Constantes utilizadas en el kernel
; ----------------------------------

dir_GDT equ 0x3800 ; Dirección de la GDT (múltiplo 8)
dir_LDT_ini equ 0x34800 ; LDT de las tareas
dir_TSS_ini equ 0x35800 ; TSS de las tareas

dir_KERNEL equ 0x50000 ; Dirección al kernel
tam_KERNEL equ 0x50000 ; Tamaño del kernel

desc_lineal equ 8 ; Descriptor lineal
desc_kernel_c equ 16 ; Descriptor del kernel (código)
desc_kernel_d equ 24 ; Descriptor del kernel (datos)
desc_LDT_ini equ 32 ; 128 descriptores de LDT
desc_TSS_ini equ 1056 ; 128 descriptores de TSS
fin_GDT equ 2080 ; Final de la GDT

; --------------------------
; --------------------------
; Punto de entrada al kernel
; --------------------------
; --------------------------

[BITS 16] ; Inicialmente instrucciones de 16 bits

inicio: ; ------------------------------------
; Deshabilitar interrupciones externas
; ------------------------------------

cli

; ---------------------------------
; Actualizar registros de segmentos
; ---------------------------------

mov ax, cs ; Mover 'cs' a 'ax'
mov ds, ax ; Actualizar el segmento de datos

; --------------------------------
; Crear una pila de datos temporal
; --------------------------------

mov     ax, 0x9F00
mov     ss, ax
mov     sp, 0x1000

; ------------------------------------
; ------------------------------------
; Crear tabla de descriptores globales
; ------------------------------------
; ------------------------------------
; escribir una rutina 'agregar_entrada_GDT' (de cualquier tipo)

crear_GDT: mov     si, mensaje_paso_1
call    mensaje ; Desplegar mensaje de aviso

; ------------------------------
; Dirección a la GDT del sistema
; ------------------------------

mov ax, 0x380 ; Dirección a la GDT en 0x380(0)
mov gs, ax ; Copiarlo a 'gs'

; ---------------
; Descriptor nulo
; ---------------

mov [gs:0], WORD 0x0000 ; Limite 0-15
mov [gs:2], WORD 0x0000 ; Base 0-15
mov [gs:4], BYTE 0x00 ; Base 16-23
mov [gs:5], BYTE 0x00 ; Tipo, DPL...
mov [gs:6], BYTE 0x00 ; G, Tam-op, Limite 16-19.
mov [gs:7], BYTE 0x00 ; Base 31-24

; -----------------
; Descriptor lineal
; -----------------

mov [gs:0 + desc_lineal], WORD 0xFFFF
mov [gs:2 + desc_lineal], WORD 0x0000
mov [gs:4 + desc_lineal], BYTE 0x00
mov [gs:5 + desc_lineal], BYTE 0x92
mov [gs:6 + desc_lineal], BYTE 0xCF
mov [gs:7 + desc_lineal], BYTE 0x00

; -------------------------------
; Descriptor de código del kernel
; -------------------------------

mov eax, DWORD dir_KERNEL
mov ebx, DWORD tam_KERNEL - 1

mov [gs:0 + desc_kernel_c], bx
mov [gs:2 + desc_kernel_c], ax

shr eax, 16
shr ebx, 16

mov [gs:4 + desc_kernel_c], al
mov [gs:5 + desc_kernel_c], BYTE 0x9A
mov [gs:6 + desc_kernel_c], bl

or [gs:6 + desc_kernel_c], BYTE 0x40 ; G=0, 32Bits

mov [gs:7 + desc_kernel_c], ah

; ------------------------------
; Descriptor de datos del kernel
; ------------------------------

mov eax, DWORD dir_KERNEL
mov ebx, DWORD tam_KERNEL - 1

mov [gs:0 + desc_kernel_d], bx
mov [gs:2 + desc_kernel_d], ax

shr eax, 16
shr ebx, 16

mov [gs:4 + desc_kernel_d], al
mov [gs:5 + desc_kernel_d], BYTE 0x92
mov [gs:6 + desc_kernel_d], bl

or [gs:6 + desc_kernel_d], BYTE 0x40 ; G=0, 32Bits

mov [gs:7 + desc_kernel_d], ah

; -----------------------
; 128 descriptores de LDT
; -----------------------

mov ebx, DWORD desc_LDT_ini ; Primer descriptor LDT
mov ecx, DWORD dir_LDT_ini ; Primer de LDT

.agregar_ldtds         mov eax, ecx

mov [gs:0 + ebx], WORD 0x1F ; LDT de 4 descriptores (?)
mov [gs:2 + ebx], ax

shr eax, 16

mov [gs:4 + ebx], al
;mov [gs:5 + ebx], BYTE 0xE2 ; Presente, DPL=3, LDT
mov [gs:5 + ebx], BYTE 0x82 ; Presente, DPL=0, LDT
mov [gs:6 + ebx], BYTE 0x40 ; G=0, TO=32
mov [gs:7 + ebx], ah

add ecx, 32 ; Siguiente LDT
add ebx, 8 ; Siguinete descriptor LDT

cmp ebx, desc_LDT_ini + 0x400 ; = desc_TSS_ini
jb .agregar_ldtds

; -----------------------
; 128 descriptores de TSS
; -----------------------
; ebx = desc_TSS_ini

mov ebx, DWORD desc_TSS_ini ; Primer descriptor TSS
mov ecx, DWORD dir_TSS_ini ; Primer TSS

.agregar_tssds mov eax, ecx

mov [gs:0 + ebx], WORD 0x67 ; Tamaño del TSS
mov [gs:2 + ebx], ax ; Base 0-15

shr eax, 16

mov [gs:4 + ebx], al ; Base 16-23
;mov [gs:5 + ebx], BYTE 0xE9 ; Presente (?), DPL=3, TSS32
mov [gs:5 + ebx], BYTE 0x89 ; Presente (?), DPL=0, TSS32
mov [gs:6 + ebx], BYTE 0x00 ; G=0
mov [gs:7 + ebx], ah ; Base 24-31

add ecx, 104 ; Siguiente TSS
add ebx, 8 ; Siguinete descriptor TSS

cmp ebx, desc_TSS_ini + 0x400 ; = fin_GDT
jb .agregar_tssds

mov     si, mensaje_OK
call    mensaje

; -----------------------------------
; -----------------------------------
; Iniciar operación en Modo Protegido
; -----------------------------------
; -----------------------------------

activar_MP: mov     si, mensaje_paso_2
call    mensaje ; Desplegar mensaje de aviso

; ---------------------------------------------------------
; Actualizar el campo 'base' de la imagen del registro GDTR
; ---------------------------------------------------------

mov [gdtr], WORD fin_GDT - 1 ; Tamaño de la GDT
mov [gdtr + 2], DWORD dir_GDT ; Dirección real de la GDT

; -------------------------
; Cargar los registros GDTR
; -------------------------

lgdt [gdtr]         ; Cargar el registro GDTR

; ------------------------------------------------------
; Establecer el bit PE (modo protegido) del registro cr0
; ------------------------------------------------------

         mov eax, cr0            
         or al, 1 ; Establacer el bit PE del registro CR0
         mov cr0, eax ; Actualizar cr0

; -----------------------------------------------
; Forzar al procesador a cambiar a modo protegido
; -----------------------------------------------

jmp desc_kernel_c:inicio_MP

[BITS 32] ; Inicio de modo protegido en 32 bits!

inicio_MP: ; ------------------------------------------
; Actualizar todos los registros de segmento
; ------------------------------------------

mov ax, desc_kernel_d
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax

; --------------------------------------------------
; Actualizar el apuntador 'esp' a la cima de la pila
; --------------------------------------------------
; Limite de desc_kernel_d (!)

mov esp, 0x50000

mov esi, mensaje_OK
call mensaje_mp

; TEMPORAL
jmp inicializar_AT
; TEMPORAL

; -----------------------------
; -----------------------------
; Activar paginación de memoria
; -----------------------------
; -----------------------------

activar_PAG: mov esi, mensaje_paso_2a
call mensaje_mp

; ------------------------------------
; Cargar 'gs' con el descriptor lineal
; ------------------------------------

mov ax, desc_lineal ; Selector lineal
mov gs, ax ; Copiarlo a 'gs'

; -------------------------------------------------
; Primera entrada del directorio de páginas: Kernel
; -------------------------------------------------

mov eax, 0x2000 ; Dirección de la primera tabla de páginas
or eax, 0x0007 ; Nivel usuario, lectura/escritura, presente

mov ebx, 0x1000 ; Desplazamiento a la primera entrada
mov [gs:ebx], eax ; Insertar la entrada

; --------------------
; 1022 entradas libres
; --------------------

add ebx, 4 ; Avanzar a la segunda entrada
mov ecx, 0x3FE ; Establecer un contador en 1022 entradas

.llenar_dp mov [gs:ebx], DWORD 0 ; Insertar entrada nula
add ebx, 4 ; Siguiente entrada

loop .llenar_dp

; --------------------------------------------------------
; Última entada: Utilizada por el administardor de memoria
; --------------------------------------------------------

mov eax, 0x1000 ; Dirección del mismo directorio!
or eax, 0x0007 ; Nivel usuario, lectura/escritura, presente

mov [gs:ebx], eax ; Insertar la entrada

; ------------------------------------------
; Inicializar la tabla de páginas del kernel
; ------------------------------------------

mov ebx, 0x2000 ; Cargar 'ebx' con el desplazamiento a la tabla
mov ecx, 0x400 ; Establecer un contador en 1024 entradas

.llenar_tp_1 mov [gs:ebx], DWORD 0 ; Insertar entrada NULA
add ebx, 4 ; Siguiente entrada

loop .llenar_tp_1

; ---------------------------------------------------
; Mapear el primer MB (+1) del espacio de direcciones
; ---------------------------------------------------

mov ebx, 0x2000 ; Cargar 'ebx' con el desplazamiento a la tabla
mov edx, 0 ; Cargar 'edx' con la primera dirección

mov ecx, 0x101 ; Establecer un contador en 267 entradas (!)

.llenar_tp_2
or edx, 0x0007 ; Nivel usuario, lectura/escritura, presente
mov [gs:ebx], edx ; Insertar entrada
add ebx, 4 ; Siguiente entrada
add edx, 0x1000 ; Siguiente dirección

loop .llenar_tp_2

; -----------------------------------------------------
; Cargar CR3 con la dirección del directorio de páginas
; -----------------------------------------------------

xor eax, eax
mov eax, 0x1000
mov cr3, eax

; -----------------------------------------------
; Establecer el bit PG (paginar) del registro cr0
; -----------------------------------------------

         mov eax, cr0            
       or eax, 0x80000000 ; Establacer el bit PG del registro CR0              
       mov cr0, eax ; Actualizar cr0

; ----------------------------------------------
; Forzar al procesador a cambiar a modo paginado
; ----------------------------------------------

jmp activar_A20

; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------
; Activar la linea A20 para tener acceso a toda la memoria de la computadora.
; ---------------------------------------------------------------------------
; ---------------------------------------------------------------------------

activar_A20: mov esi, mensaje_OK
call mensaje_mp

; ...

; ---------------------------
; ---------------------------
; Inicializar área de trabajo
; ---------------------------
; ---------------------------

inicializar_AT: mov esi, mensaje_paso_3
call mensaje_mp

; --------------------------------------------------
; Inicializar en ceros el área de las LDT de usuario
; --------------------------------------------------

mov ebx, DWORD dir_LDT_ini ; Inicio del área de LTD(s)
mov ecx, 0x400 ; Establecer contador

.ini_1 mov [gs:ebx], DWORD 0x00000000 ; Inicializar 4 bytes
add ebx, 4

loop .ini_1

; --------------------------------------------------
; Inicializar en ceros el área de los TSS de usuario
; --------------------------------------------------

mov ebx, DWORD dir_TSS_ini ; Inicio del área de TSS(s)
mov ecx, 0xD00 ; Establecer contador

.ini_2 mov [gs:ebx], DWORD 0x00000000 ; Inicializar 4 bytes
add ebx, 4

loop .ini_2

mov esi, mensaje_OK
call mensaje_mp

; ------------------------------
; ------------------------------
; Iniciar el ambiente multitarea
; ------------------------------
; ------------------------------

primer_tarea: mov esi, mensaje_paso_4
call mensaje_mp

; ------------------------------------
; Cargar 'gs' con el descriptor lineal
; ------------------------------------

mov ax, desc_lineal ; Selector lineal
mov gs, ax ; Copiarlo a 'gs'

; --------------------------------------------------------
; Actualizar los DPL de los descriptor del kernel a ring 0
; --------------------------------------------------------

mov ebx, DWORD dir_GDT + desc_LDT_ini
mov [gs:ebx + 5], BYTE 0x82 ; Presente, DPL=0, LDT

mov ebx, DWORD dir_GDT + desc_TSS_ini
mov [gs:ebx + 5], BYTE 0x89 ; Presente, DPL=0, TSS32

; ---------------------------------------------------
; Cargar el registro de tareas con el TSS del sistema
; ---------------------------------------------------

mov ax, desc_TSS_ini ; 1er descriptor TSS
ltr ax

; ---------------------------------------------------
; Cargar el registro de la LDT con el descriptor nulo
; ---------------------------------------------------

mov ax, 0
lldt ax

mov esi, mensaje_OK
call mensaje_mp

; --------------------------------
; --------------------------------
; Fin de rutinas de inicialización
; --------------------------------
; --------------------------------

; ------------------------------------
; Re-habilitar interrupciones externas (ERROR)
; ------------------------------------

;sti ; Error (!)(?)

; -------------------------
; -------------------------
; Cargar e iniciar el shell
; -------------------------
; -------------------------

otra_tarea: ; ---------------------------------------
; Crear tarea de usuario y brincar a ella
; ---------------------------------------

mov ax, desc_lineal ; Selector lineal
mov gs, ax ; Copiarlo a 'gs'

mov ebx, DWORD dir_TSS_ini ; Dirección a los TSS(s)
add ebx, 104 ; Primer TSS de usuario

mov [gs:ebx + 0x00], DWORD 0
mov [gs:ebx + 0x04], DWORD 0
mov [gs:ebx + 0x08], DWORD 0
mov [gs:ebx + 0x0C], DWORD 0
mov [gs:ebx + 0x10], DWORD 0
mov [gs:ebx + 0x14], DWORD 0
mov [gs:ebx + 0x18], DWORD 0
mov [gs:ebx + 0x1C], DWORD 0x1000 ; PDBR (cr3)

lea eax, [tarea_usuario] ; Punto de entrada
mov [gs:ebx + 0x20], eax ; 'eip'
mov [gs:ebx + 0x24], DWORD 0
mov [gs:ebx + 0x28], DWORD 0
mov [gs:ebx + 0x2C], DWORD 0
mov [gs:ebx + 0x30], DWORD 0
mov [gs:ebx + 0x34], DWORD 0

lea eax, [esp-512] ; Apuntador de la pila
mov [gs:ebx + 0x38], eax ; 'esp' (?)
mov [gs:ebx + 0x3C], DWORD 0
mov [gs:ebx + 0x40], DWORD 0
mov [gs:ebx + 0x44], DWORD 0
mov [gs:ebx + 0x48], WORD desc_kernel_d ; 'es'
mov [gs:ebx + 0x4C], WORD desc_kernel_c ; 'cs'
mov [gs:ebx + 0x50], WORD desc_kernel_d ; 'ss'
mov [gs:ebx + 0x54], WORD desc_kernel_d ; 'ds'
mov [gs:ebx + 0x58], WORD desc_kernel_d ; 'fs'
mov [gs:ebx + 0x5C], WORD desc_kernel_d ; 'gs'
mov [gs:ebx + 0x60], DWORD 0
mov [gs:ebx + 0x64], DWORD 0

; -------------
; Iniciar tarea
; -------------

mov ecx, 0xFF ; Solo funciona 2 veces, ¿por que?

.ciclo jmp desc_TSS_ini+8:0

; Continua aquí después de ir a la tarea de usuario...

loop .ciclo

; ---------------
; Fin del sistema
; ---------------

cli
hlt

; -------------------------------------------------------------------------------------
; TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL
; -----------------
; -----------------
; Tarea del usuario
; -----------------
; -----------------

tarea_usuario: mov esi, mensaje_usuario
call mensaje_mp

jmp desc_TSS_ini:0

; Continua aquí después de ir al kernel...

jmp tarea_usuario ; IMPORTANTE: Repetir la tarea!

; TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL - TEMPORAL
; -------------------------------------------------------------------------------------

; -------------------
; -------------------
; Estructura de datos
; -------------------
; -------------------

; -----------------------------------
; Imagen de los registros GDTR e IDTR
; -----------------------------------

gdtr dw 0
dd 0

; -------------------------------------------------------
; Mensajes de aviso de paso del proceso de inicialización
; -------------------------------------------------------

mensaje_paso_1 db "Crear tabla GDT                        ", 0x00
mensaje_paso_2 db "Activar modo protegido                 ", 0x00
mensaje_paso_2a db "Paginar memoria                        ", 0x00
mensaje_paso_3 db "Inicializar area de trabajo            ", 0x00
mensaje_paso_4 db "Ambiente multitarea                    ", 0x00

mensaje_usuario db "1 2 3 4 5 6 7 8 9 0 1 ", 0x00

mensaje_OK   db "[OK]", 0x0D, 0x0A, 0x00

; -----------------------
; -----------------------
; Rutinas complementarias
; -----------------------
; -----------------------

; ----------------------------------------------------------
; mensaje: Despliega el primer mensaje de aviso en modo real (?)
; ----------------------------------------------------------

mensaje: cld        
lodsb ; Cargar 'ax' con 'ds:si' e incrementar 'si' en 1
or      al, al                  ; Verificar si 'al' es cero (fin de la cadena ASCIIZ)
jz      .listo ; Si 'al' es cero salir de la rutina
mov     ah, 0x0E                ; Servicio 0Eh (escribe en un teletipo)
int     0x10                    ; Exhibición de video
jmp     mensaje ; Siguiente caracter

.listo: ret

; ---------------------------------------------------------
; mensaje_mp: Desplaza el texto de la pantalla hacia arriba
; ---------------------------------------------------------

mensaje_mp: push eax
push ebx
push cx
push dx
push esi
push gs

; ---------------------------------------------
; Cargar 'gs' con el selector de memoria lineal
; ---------------------------------------------

mov ax, desc_lineal
mov gs, ax

; ---------------------------------------------------------
; Calcular la posición del cursor sobre la memoria de video
; ---------------------------------------------------------

xor eax, eax ; Limpiar 'eax'
call posicion_cursor ; Leer la posición actual del cursor
mov cx, ax ; Guardar la posición en 'cx'
shl eax, 1 ; Multiplicar todo por 2
lea ebx, [eax + 0xB8000] ; Cargar la posición en 'ebx'

.leer_desplegar: ; ----------------
; Leer el caracter
; ----------------

cld ; Procesar la cadena de izquierda a derecha (¿Donde va?)
lodsb ; Cargar 'al' con 'ds:esi' e incrementar 'esi'
or      al, al          ; Verificar si se llegó al fin de la cadena ASCIIZ
jz      .listo ; Si 'al' es cero salir de la rutina

; ----------------------------------------------
; Verificar si se llegó al limite de la pantalla
; ----------------------------------------------

cmp cx, 0x7D0 ; Se excedio el límite de la pantalla?
jb .continuar ; Antes se utilizaba 'jne'

call desplazar_texto

push ebx
mov bx, 0x0780 ; Nueva posición del cursor
call mover_cursor ; Mover el cursor
pop ebx

sub ebx, 0x0A0 ; Decrementar el apuntador de memoria
sub cx, 0x050 ; Decrementar el apuntador de pantalla

; ---------------------
; Caracteres especiales
; ---------------------

.continuar: cmp al, 0x0A
je .nueva_linea

cmp al, 0x0D
je .retorno_carro

; --------------------
; Imprimir el caracter
; --------------------

mov byte [gs:ebx], al ; Desplegar el caracter
inc ebx ; Siguiente caracter
mov byte [gs:ebx], 0x007 ; Aplicar atributos de texto
inc ebx ; Siguientes atributos
inc cx ; Contador de caracteres
jmp     .leer_desplegar

.nueva_linea: add ebx, 0xA0 ; 160 decimal
add cx, 0x50 ; 80 decimal
jmp     .leer_desplegar

.retorno_carro: mov ax, cx ; Posición actual
mov dl, 0x50 ; 80 decimal
div dl ; Dividir entre 80
shr ax, 8 ; Mover 'ah' a 'al'
sub cx, ax ; Restar el residuo a 'cx'
shl ax, 1 ; Multiplicar por 2
sub bx, ax ; Si se puede hacer así (!)
jmp     .leer_desplegar

.listo: ; ---------------------------------------
; Mover el caracter al final de la cadena
; ---------------------------------------

mov bx, cx ; Nueva posición del cursor
call mover_cursor ; Mover el cursor

pop gs
pop esi
pop dx
pop cx
pop ebx
pop eax

ret

posicion_cursor: push bx
push dx

xor bx, bx

mov dx, word 0x3D4 ; Numero de puerto (VGA)
mov al, byte 0x0F ; Indice: Byte bajo posición del cursor
out dx, al ; Enviar al puerto

mov dx, word 0x3D5 ; Numero de puerto (VGA datos)
in al, dx ; Leer del puerto
mov bl, al ; Guardar el valor en 'bx'

mov dx, word 0x3D4 ; Numero de puerto (VGA)
mov al, byte 0x0E ; Indice: Byte alto posición del cursor
out dx, al ; Enviar al puerto

mov dx, word 0x3D5 ; Numero de puerto (VGA datos)
in al, dx ; Leer del puerto
mov bh, al ; Guardar el valor en 'bx'

mov ax, bx ; Mover el resultado a 'ax'

pop dx
pop bx

ret

desplazar_texto: push ax
push ebx
push ecx
push dx
push gs

; ---------------------------------------------
; Cargar 'gs' con el selector de memoria lineal
; ---------------------------------------------

mov ax, desc_lineal
mov gs, ax

; --------------------------------------
; Desplazar el texto utilizando un ciclo
; --------------------------------------

mov ebx, 0x0B8000 ; Inicio de la memoria de video
mov ecx, 0x0780 ; Establecer contador en 80*24

; --------------------------------------------------------------
; Copiar cada caracter/atributo de la pantalla un renglón arriba
; --------------------------------------------------------------

.desplazar: mov dx, word [gs:ebx+0x0A0] ; Copiar en 'dx' el caracter/atributo que está 160 casillas adelante
mov [gs:ebx], dx ; Mover el caracter/atributo a la posición apuntada por 'gs:ebx'
inc ebx ; Incrementar 'ebx'
inc ebx ; Incrementar 'ebx'
loop .desplazar

; ----------------------
; Borrar la última línea
; ----------------------

mov ecx, 0x50 ; Establecer contador en 80

.borrar: mov [gs:ebx], word 0x0720 ; Escribir un espacio en la posición apuntada por 'gs:ebx'
inc ebx ; Incrementar 'ebx'
inc ebx ; Incrementar 'ebx'
loop .borrar

pop gs
pop dx
pop ecx
pop ebx
pop ax

ret

mover_cursor: push ax
push dx

mov dx, word 0x3D4 ; Numero de puerto (VGA)
mov al, byte 0x0F ; Indice: Byte bajo posición del cursor
out dx, al ; Enviar al puerto

mov dx, word 0x3D5 ; Numero de puerto (VGA datos)
mov al, bl ; Cargar 'al' con byte bajo
out dx, al ; Enviar al puerto

mov dx, word 0x3D4 ; Numero de puerto (VGA)
mov al, byte 0x0E ; Indice: Byte alto posición del cursor
out dx, al ; Enviar al puerto

mov dx, word 0x3D5 ; Numero de puerto (VGA datos)
mov al, bh ; Cargar 'al' con byte alto
out dx, al ; Enviar al puerto

pop dx
pop ax

ret

verificar_A20: ; ------------------------------------------------------
; Cargar 'fs' con el selector lineal que apunta a 0x0000
; ------------------------------------------------------

mov ax, desc_lineal
mov fs, ax ; Cargar 'fs' con el selector lineal

; --------------------------------------------------------
; Girar mientras no se agote el contador y, fs:0200 apunte
; a la misma dirección de memoria física que fs:100200
; --------------------------------------------------------

mov ax, 0 ; Inicializar 'ax' en cero

.verifiar: inc ax
mov word [fs:0x200], ax ; Mover un dato a fs:0x0200
cmp ax, [fs:0x100200] ; Comparar con fs:0x100200

loope .verifiar ; Girar mientras sean iguales

;  ZF -> Línea A20 desactivada
; !ZF -> Línea A20 activa

ret

RE:Multitasking problem

Posted: Tue Jul 08, 2003 11:00 pm
by pepito
Any idea?

RE:Multitasking problem

Posted: Tue Jul 08, 2003 11:00 pm
by common
Try creating your TSS and loading it with the correct cr3 value before you enable paging, not after.  You may also want to activate A20 before paging and before the TSS.

Also, make sure to clear the prefetch queue after you enable paging by performing a long jump (a normal jmp instruction won't cut it, you need to select the selector).

RE:Multitasking problem

Posted: Wed Jul 09, 2003 11:00 pm
by pepito
Thank you very much! I will do this changes.

pepito