Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
ndice
ndice
1.- Introduccin ................................................... 2
2.- La arquitectura del microprocesador Intel 80386 ......................... 3
2.1.- Registros de propsito general ..................................... 3
2.2.- Registros de segmento ......................................... 3
2.3.- Flags y puntero de instruccin .................................... 4
2.4.- Registros de control .......................................... 4
2.5.- Registros de direccin del sistema .................................. 5
2.6.- Registros de testeo y depuracin.................................... 5
3.- El acceso a los puertos de E/S ....................................... 6
4.- Las interrupciones ............................................... 7
5.- Librera del kernel ............................................... 9
5.1.- Monitor de arranque ......................................... 13
5.1.1.- _monitor.................................................... 13
5.2.- Modo protegido ............................................ 13
5.2.1.- _level0 ..................................................... 13
5.3.- Acceso a memoria........................................... 14
5.3.1.- _phys_copy .................................................. 14
5.3.2.- _check_mem ................................................. 16
5.3.3.- _mem_rdw .................................................. 18
5.4.- Acceso a puertos ............................................ 19
5.4.1.- _in_byte .................................................... 19
5.4.2.- _in_word .................................................... 19
5.4.3.- _out_byte ................................................... 19
5.4.4.- _out_word ................................................... 20
5.4.5.- _port_read ................................................... 20
5.4.6.- _port_read_byte ............................................... 21
5.4.7.- _port_write .................................................. 21
5.4.8.- _port_write_byte .............................................. 22
5.5.- Acceso a ram de vdeo ........................................ 23
5.5.1.- _mem_vid_copy ............................................... 23
5.5.2.- _vid_vid_copy ................................................ 24
5.6.- Manejo de mensajes ......................................... 24
5.6.1.- _cp_mess ................................................... 27
5.7.- Manejo de interrupciones ...................................... 29
5.7.1.- _lock ...................................................... 29
5.7.2.- _unlock ..................................................... 29
5.7.3.- _reset ...................................................... 29
5.7.4.- _enable_irq .................................................. 30
5.7.5.- _disable_irq .................................................. 31
5.7.6.- _bios_13 .................................................... 33
Introduccin
1.- Introduccin
Algo importante que hay que saber es que el ncleo (tambin llamado kernel) de Minix interacciona
directamente con el hardware del sistema. Esta interaccin comprende bsicamente el acceso a memoria
principal, el acceso a los puertos de entrada/salida y el manejo de las interrupciones.
Para poder llevar a cabo estos diferentes tipos de interacciones con el hardware se han desarrollado
una serie de funciones, escritas en su mayora en lenguaje ensamblador, siendo las restantes escritas en
lenguaje de alto nivel C.
Este conjunto de funciones conforman una librera denominada KLIB. Las funciones de esta librera
se reparten entre dos ficheros llamados klib.s y misc.c, en el primero se incluyen aquellas escritas en
ensamblador y en el segundo aquellas escritas en lenguaje C.
Algunos de nuestros lectores se estarn preguntando el porqu del uso del lenguaje ensamblador.
Pues bien, la utilizacin de lenguaje de bajo nivel para la realizacin de esta librera se debe principalmente a
dos razones:
1. Optimizacin: las rutinas implementadas proporcionan operaciones que forman parte del ncleo
del sistema operativo y son, por tanto, utilizadas muy frecuentemente. Por esta razn es de vital
importancia la eficiencia con que se ejecutan estas funciones, eficiencia que ser maximizada
con el uso del ensamblador. Ejemplos pueden ser las rutinas de copia de mensajes o las rutinas
de acceso a memoria.
2. Imposibilidad de utilizar lenguajes de alto nivel: no debido a que no existan lenguajes de alto
nivel que proporcionen acceso a recursos de bajo nivel (memoria, puertos o interrupciones), sino
debido a que Minix no fue escrito para estos compiladores.
El klib se encuentra en el kernel, en la capa inferior, interaccionando directamente con el hardware.
Ofrece sus servicios a los drivers y a los otros mdulos del kernel.
Init
Proceso
de usuario
Administrador
de memoria
Tarea
de disco
Proceso
de usuario
Administrador
de archivos
Tarea
de terminal
Tarea
de reloj
Proceso
de usuario
Servidor
de red
Tarea
de sistema
Administracin de procesos
Tarea
de Ethernet
Arquitectura 80386
16 15
87
[AH]
[BH]
[CH]
[DH]
AX
BX
CX
DX
[AL]
[BL]
[CL]
[DL]
SP
BP
SI
DI
31
16 15
EAX
EBX
ECX
EDX
Acumulador
Base
Contador
Datos
ESP
EBP
ESI
EDI
CS
DS
SS
ES
FS
GS
Segmento de cdigo
Segmento de datos
Segmento de pila
Segmento Extra
Segmento Adicional 1
Segmento Adicional 2
Arquitectura 80386
16 15
IP
Flags
EIP
Puntero de instruccin
EFlags Registro de flags
Dentro del registro de flags se han aadido nuevos bits de flag. En la siguiente figura podemos ver en
qu posicin, dentro del registro de flags, se ubican los diferentes bits:
31
16
VM
15
RF
0
NT
IOPL
OF
DF
IF
TF
SF
ZF
AF
PF
CF
En la tabla que a continuacin les ofrecemos aparecen los nombres completos para cada bit. Seguro
que ms de un nombre les es familiar, sin embargo hay algunos que necesitan una descripcin. Esta aparece
despus de la tabla.
Bit
0
2
4
6
7
8
9
Flag
CF
PF
AF
ZF
SF
TF
IF
Nombre
Carry Flag
Parity Flag
Auxiliary Carry Flag
Zero Flag
Sign Flag
Trap Flag
Interrupt Enable Flag
Bit
10
11
12/13
14
16
17
Flag
DF
OF
IOPL
NT
VM
RF
Nombre
Direction Flag
Overflow Flag
Input/Output Privilege Level Flag
Nested Task Flag
Virtual 8086 Mode Flag
Resume Flag
Arquitectura 80386
Registro asociado
Tamao del registro
GDTR
32 (base) +16 (limite) bits
IDTR
32 (base) +16 (limite) bits
LDTR
16 (selector) bits
TR
16 (selector) bits
Utilidad
Direccin 0 de breakpoint lineal
Direccin 1 de breakpoint lineal
Direccin 2 de breakpoint lineal
Direccin 3 de breakpoint lineal
Reservado por Intel
Reservado por Intel
Estado del breakpoint
Control del breakpoint
Control del testeo
Estado del testeo
Acceso a puertos
Fichero klib386.c
Fichero klib386.c
En la siguiente tabla se muestra como se asignan los niveles de interrupcin a los distintos perifricos:
Solo AT
IRQ8
IRQ9
IRQ10
IRQ11
IRQ12
IRQ13
IRQ14
IRQ15
IRQ3
IRQ4
IRQ5
IRQ6
IRQ7
Descripcin
Temporizador
Teclado
Canal de E/S
Reloj de tiempo Real
software redirigido a IRQ2
Reservado
Reservado
Reservado
Coprocesador matemtico
Controlador de disco duro
Reservado
COM1 y COM3 ( COM2 y COM4 en el AT)
COM2 y COM4 ( COM1 y COM3 en el AT)
Disco duro ( LPT2 en el AT)
Controlador de disquete
LPT1
El 8259 posee tres registros de un byte que controlan y gestionan las ocho (o diecisis) lneas de
interrupcin hardware, pero a nosotros slo nos interesa el registro de mscara de interrupciones (IMR). El 8259
emplea este registro para averiguar si una interrupcin de un determinado nivel est permitida en cualquier
momento. Para desactivar interrupciones hardware concretas, se enva un patrn de bits al puerto 21h
(INT_CTLMASK), que es la direccin del registro de mscaras de interrupcin (IMR). El registro de mscara
del segundo chip 8259 del AT se sita en el puerto A1h (INT2_CTLMASK). En este patrn de bits, se ponen a
uno los bits que corresponden a los nmeros de interrupcin que se desea enmascarar.
Fichero klib386.c
! Fichero klib.s
#include <minix/config.h>
#if _WORD_SIZE == 2
#include "klib88.s"
#else
#include "klib386.s"
#endif
Minix es un sistema operativo preparado para trabajar tanto en ordenadores con tamao de palabra
de 16 bits (8086, 8088, 80286) como para los de tamao de palabra de 32 bits (80386 y superiores). Para
mantener la compatibilidad con ambas clases de PC en el fichero klib.s se comprueba el tamao de la palabra
del ordenador. Si el tamao es 16 bits se incluyen las funciones de soporte para sistemas de 16 bits que se
encuentran en el fichero klib88.s. Si el tamao no es 16 bits (se supone que es 32), se incluye el fichero
klib386.s donde estn las rutinas de soporte para sistemas que funcionan con palabra de 32 bits.
En este trabajo nos centraremos en las funciones de soporte para sistemas de 32 bits. En total son 23
funciones que hemos clasificado en los siguientes mdulos para mayor comprensin:
klib386.s
monitor de
arranque (2.1)
modo
protegido (2.2)
manejo de
memoria
manejo de
mensajes (2.6)
acceso a
memoria (2.3)
acceso a
puertos (2.4)
acceso a mem.
de vdeo (2.5)
10
Fichero klib386.c
Mdulo
2.1
2.2
2.3
2.4.
2.5.
2.6
2.7
Funcin
_monitor
_level0
_phys_copy
_check_mem
_mem_rdw
_in_byte
_in_word
_out_byte
_out_word
_port_read
_port_read_byte
_port_write
_port_write_byte
_mem_vid_copy
_vid_vid_copy
_cp_mess
_lock
_unlock
_reset
_enable_irq
_disable_irq
_bios_13
Descripcin
Finaliza Minix y retorna al monitor
Invoca una funcin en nivel 0
Copia datos de una posicin de memoria a cualquier otra
Revisa un bloque de memoria y devuelve el tamao vlido
Copia una palabra de segmento:desplazamiento
Lee un byte de un puerto de E/S
Lee una palabra de un puerto de E/S
Escribe un byte a un puerto de E/S
Escribe una palabra a un puerto de E/S
Transfiere datos de un puerto (el controlador de disco) a memoria
Igual que _port_read pero byte a byte
Transfiere datos de memoria a un puerto (el controlador de disco)
Igual que _port_write pero byte a byte
Copia datos desde la memoria a la ram de vdeo
Copia datos desde la ram de vdeo a la ram de vdeo
Copia mensajes de una fuente a un destino
Inhabilita las interrupciones
Habilita las interrupciones
Vuelve a arrancar el sistema
Habilita una irq del controlador 8259
Inhabilita una irq del controlador 8259
Realiza una llamada al servicio 13h de la BIOS para E/S a disco
Antes de pasar directamente a detallar cada una de las funciones anteriores, explicaremos conceptos
comunes a todas ellas. En primer lugar se mostrar se mostrar el paso de parmetros a funciones y luego se
mostrar la estructura general de las mismas.
1. Paso de parmetros a funciones
El primer hecho a considerar es que en lenguaje ensamblador es el propio programador o, en
su defecto, el ensamblador, el que debe controlar el paso de parmetros a funciones. Para ello debe
guardar dichos parmetros en la pila o en registros antes de realizar la llamada a la funcin y una vez
dentro de la misma debe recuperar esos valores.
En las funciones que se muestran a continuacin el paso de parmetros se realiza a travs de
la pila de la forma que se muestra a continuacin.
Antes de la llamada a la funcin se ubican en la pila los parmetros a pasar a sta.
SP
Parmetro3
Parmetro2
Parmetro1
11
Fichero klib386.c
SP
EIP
Parmetro1
Parmetro2
Parmetro3
registro2
registro1
SP
EIP
2
Parmetro1
Parmetro2
Parmetro3
SP
registro2
registro1
EIP
2
Parmetro1
Parmetro2
Parmetro3
12
Valor de la macro
Fichero klib386.c
Salvar registros1
CUERPO
FUNCIN
Restaurar registros1
Retornar 2
(1) Los nicos registros que se salvan y restauran de la pila si se van a utilizar, son ebx, esi, edi, esp, los
registros de segmento (CS, DS, ES) y el bit de direccin del registro de flags. El registro EIP siempre es
guardado en la pila por la instruccin CALL que llama la funcin en cuestin.
(2) Si hay que retornar un valor este se devuelve en el registro EAX.
13
Fichero klib386.c
eax, (_reboot_code)
esp, (_mon_sp)
dx, SS_SELECTOR
ds, dx
es, dx
fs, dx
gs, dx
ss, dx
edi
esi
ebp
! retornar al monitor
eax, 4(esp)
(_level0_func), eax
LEVEL0_VECTOR
14
Fichero klib386.c
nmero de
bytes < 101?
ubicacin de los
datos en la fuente
NO
copiar de 0 a 3 bytes
para alinear bytes de
inicio
(1)
(2)
copiar todas las
palabras posibles
copiar de 0 a 9 bytes
(3)
copiar de 0 a 3 bytes
para terminar la copia
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FIN
(1) Este es un valor emprico, que indica que por debajo del mismo no es rentable realizar el proceso
intentando copiar palabra a palabra, sino que es ms eficiente realizar la copia byte a byte.
15
(1)
(2)
(3)
Fichero klib386.c
Los tres parmetros indican la direccin fuente de los datos a copiar, la direccin destino de dichos
datos a copiar y el nmero de bytes a copiar respectivamente. Todos los parmetros son del tipo unsigned
long int.
4 + 4 + 4 + 4 ! 4 + 4 + 4
es edi esi eip src dst len
.align
_phys_copy:
cld
push
push
push
16
! direccin de las oper. con ristras hacia adelante
esi
edi
es
mov
mov
eax, FLAT_DS_SELECTOR
es, ax
! establecer los selectores de segmento
mov
mov
mov
esi, PC_ARGS(esp)
! esi direccin fuente (ds:esi)
edi, PC_ARGS+4(esp)
! edi direccin destino (es:edi)
eax, PC_ARGS+4+4(esp) ! eax cantidad de bytes a copiar
cmp
jb
mov
neg
and
sub
rep
eseg movsb
mov
shr
rep
eseg movs
and
pc_small:
xchg
rep
eseg movsb
pop
pop
pop
ret
eax, 10
pc_small
ecx, esi
ecx
ecx, 3
eax, ecx
ecx, eax
ecx, 2
eax, 3
ecx, eax
es
edi
esi
16
Fichero klib386.c
5.3.2.- _check_mem
Esta funcin se invoca en el momento de iniciarse Minix para chequear un bloque de memoria. Esta
funcin realiza una prueba sencilla con cada decimosexto byte, pues chequear todos los bytes sera muy
costoso, usando dos patrones que prueban cada bit con valores tanto 0 como 1 (vase en el cdigo
TEST1PATTERN y TEST2PATTERN).
Los parmetros indican la direccin fsica del bloque de memoria a chequear y el tamao de dicho
bloque respectivamente. Si el tamao del bloque es cero entonces hay que chequear todo.
=
=
=
=
=
16
4
0x55
0xAA
4 + 4 + 4
ds ebx eip
ebx
ds
ax, FLAT_DS_SELECTOR
ds, ax
eax,
ebx,
ecx,
ecx,
!
!
!
!
!
eax direccin
ebx eax
ecx tamao de
ecx nmero de
es decir, nmero
dl patrn 1
escribir el patrn 1 en memoria
volver a escribirlo en dl
deben coincidir si la memoria actual esta OK
si son diferentes, hay un fallo en la memoria
CHKM_ARGS(esp)
eax
CHKM_ARGS+4(esp)
CM_LOG_DENSITY
cm_loop:
movb
xchgb
xchgb
cmpb
jnz
dl, TEST1PATTERN
dl, (eax)
dl, (eax)
dl, TEST1PATTERN
cm_exit
!
!
!
!
!
movb
xchgb
xchgb
add
cmpb
dl, TEST2PATTERN
dl, (eax)
dl, (eax)
eax, CM_DENSITY
dl, TEST2PATTERN
loopz
cm_loop
eax, ebx
ds
ebx
cm_exit:
sub
pop
pop
ret
17
Fichero klib386.c
copiar patrn 1 en
memoria
leer patrn 1 de
memoria
coincide valor
escrito con
leido?
copiar patrn 2 en
memoria
leer patrn 2 de
memoria
coincide valor
escrito con
leido?
se ha testeado la
zona completa?
FIN
18
Fichero klib386.c
5.3.3.- _mem_rdw
Devuelve una palabra de 16 bits de cualquier lugar de la memoria. El resultado se rellena con ceros
dentro del registro EAX de 32 bits. Es una funcin muy especfica para los procesadores Intel.
El primer parmetro indica el segmento base y el segundo un puntero al desplazamiento a aadir a
dicho segmento.
! PUBLIC u16_t mem_rdw(U16_t segment, u16_t *offset);
.align 16
_mem_rdw:
mov
cx, ds
! salvar registro ds
mov
mov
ds, 4(esp)
eax, 4+4(esp)
! ds segmento
! eax desplazamiento
movzx
eax, (eax)
mov
ret
ds, cx
! restablecer ds
! retornar
19
Fichero klib386.c
16
edx, 4(esp)
eax, eax
dx
!
!
!
!
5.4.2.- _in_word
Lee una palabra sin signo del puerto de E/S indicado y devuelve dicho valor.
! PUBLIC unsigned in_word(port_t port);
.align
_in_word:
mov
sub
o16 in
ret
16
edx, 4(esp)
eax, eax
dx
!
!
!
!
5.4.3.- _out_byte
Escribe un valor, que convierte a byte, al puerto indicado.
Los parmetros que se pasan a la funcin son el puerto destino y el valor de 8 bits a escribir en dicho
puerto.
! PUBLIC void out_byte(port_t port, u8_t value);
.align
_out_byte:
mov
movb
outb
ret
16
edx, 4(esp)
al, 4+4(esp)
dx
!
!
!
!
20
Fichero klib386.c
5.4.4.- _out_word
Escribe un valor, de tamao palabra, al puerto indicado.
Los parmetros que se pasan a la funcin son el puerto destino y el valor de 16 bits a escribir en
dicho puerto.
! PUBLIC void out_word(Port_t port, U16_t value);
.align
_out_word:
mov
mov
o16 out
ret
16
edx, 4(esp)
eax, 4+4(esp)
dx
!
!
!
!
5.4.5.- _port_read
Transfiere informacin de un puerto (el controlador de disco) a memoria.
El primer parmetro indica el puerto del que se van a leer los datos, el segundo parmetro la
direccin de destino en la que se van a escribir los datos y el ltimo parmetro indica la cantidad de bytes a
copiar.
! PUBLIC void port_read(port_t port, phys_bytes destination, unsigned bytcount);
PR_ARGS =
!
4 + 4 + 4
es edi eip
! 4 + 4 + 4
port dst len
.align 16
_port_read:
cld
push
edi
push
es
mov
mov
mov
mov
mov
shr
rep
o16 ins
pop
pop
! salvar registros
ecx, FLAT_DS_SELECTOR
es, cx
edx,
edi,
ecx,
ecx,
PR_ARGS(esp)
PR_ARGS+4(esp)
PR_ARGS+4+4(esp)
1
!
!
!
!
edx
edi
ecx
ecx
! leer todo
es
edi
! restablecer registros
ret
! retornar
21
Fichero klib386.c
5.4.6.- _port_read_byte
Transfiere informacin de un puerto (el controlador de disco) a memoria, byte a byte.
El primer parmetro indica el puerto del que se van a leer los datos, el segundo parmetro la
direccin de destino en la que se van a escribir los datos y el ltimo parmetro indica la cantidad de bytes a
copiar.
! PUBLIC void port_read_byte(port_t port, phys_bytes destination,
!
unsigned bytcount);
PR_ARGS_B =
!
4 + 4 + 4
es edi eip
! 4 + 4 + 4
port dst len
_port_read_byte:
cld
push
edi
push
es
! salvar registros
mov
mov
ecx, FLAT_DS_SELECTOR
es, cx
mov
mov
mov
rep
insb
edx, PR_ARGS_B(esp)
! edx puerto que se va a leer
edi, PR_ARGS_B+4(esp)
! edi direccin de destino
ecx, PR_ARGS_B+4+4(esp) ! ecx cantidad de bytes
pop
pop
es
edi
! leer todo
! restablecer registros
ret
! retornar
5.4.7.- _port_write
Transfiere informacin de memoria a un puerto (el controlador de disco).
El primer parmetro indica el puerto en el que se van a escribir los datos, el segundo parmetro la
direccin de destino de la que se van a leer los datos y el ltimo parmetro indica la cantidad de bytes a
copiar.
! PUBLIC void port_write(port_t port, phys_bytes source, unsigned bytcount);
PW_ARGS =
!
4 + 4 + 4
es edi eip
! 4 + 4 + 4
port src len
.align 16
_port_write:
cld
push
esi
push
ds
mov
mov
mov
mov
mov
shr
rep
o16 outs
pop
pop
! salvar registros
ecx, FLAT_DS_SELECTOR
ds, cx
edx,
esi,
ecx,
ecx,
PW_ARGS(esp)
PW_ARGS+4(esp)
PW_ARGS+4+4(esp)
1
!
!
!
!
edx
esi
ecx
ecx
! escribir todo
ds
esi
! restablecer registros
ret
! retornar
22
Fichero klib386.c
5.4.8.- _port_write_byte
Transfiere informacin byte a byte de memoria a un puerto (el controlador de disco).
El primer parmetro indica el puerto en el que se van a escribi r los datos, el segundo parmetro la
direccin de destino de la que se van a leer los datos y el ltimo parmetro indica la cantidad de bytes a
copiar.
! PUBLIC void port_write_byte(port_t port, phys_bytes source,
!
unsigned bytcount);
PW_ARGS_B =
!
4 + 4 + 4
es edi eip
! 4 + 4 + 4
port src len
_port_write_byte:
cld
push
esi
push
ds
! salvar registros
mov
mov
ecx, FLAT_DS_SELECTOR
ds, cx
mov
mov
mov
rep
outsb
edx, PW_ARGS_B(esp)
esi, PW_ARGS_B+4(esp)
ecx, PW_ARGS_B+4+4(esp)
pop
pop
ds
esi
! restablecer registros
ret
! retornar
23
Fichero klib386.c
Contador = min
(bytes a copiar,
vid_size-edi)
NO
origen = 0?
copiar datos de
origen en el destino
NO
copiar blank_color
en el destino
Todos los
bytes copiados?
S
FIN
24
Fichero klib386.c
4 + 4 + 4 + 4 ! 4 + 4 + 4
es edi esi eip src dst ct
_mem_vid_copy:
push
esi
push
edi
push
es
mov
mov
mov
mov
cld
mvc_loop:
and
mov
mov
sub
cmp
jbe
mov
0:
sub
shl
test
jz
mvc_copy:
rep
o16 movs
jmp
mvc_blank:
mov
rep
o16 stos
!jmp
esi, MVC_ARGS(esp)
!
edi, MVC_ARGS+4(esp) !
edx, MVC_ARGS+4+4(esp)!
es, (_vid_seg)
!
!
edi, (_vid_mask)
ecx, edx
eax, (_vid_size)
eax, edi
ecx, eax
0f
ecx, eax
edx, ecx
edi, 1
esi, esi
mvc_blank
esi origen
edi destino
edx cantidad
el destino es el segmento de vdeo
aseguramos que la direccin es hacia delante
eax, (_blank_color)
mvc_test
mvc_test:
shr
test
jnz
edi, 1
edx, edx
mvc_loop
mvc_done:
pop
pop
pop
es
edi
esi
! restablecer registros
ret
! retornar
5.5.2.- _vid_vid_copy
Copia un bloque dentro de la memoria de vdeo misma. Esto se utiliza para desplazar, insertar o
borrar caracteres y lneas en pantalla. Esta rutina es algo ms complicada ya que tiene que tener en cuenta el
hecho de que los bloques origen y destino pueden solaparse, para lo cual hemos creado el siguiente diagrama
donde se muestran cmo debe ser la copia segn sea la direccin origen (ESI) menor que la direccin destino
(EDI) o viceversa.
25
Fichero klib386.c
X
X
A
B
C
D
E
Correcto
B
C
D
C
D
Incorrecto
Actualizaciones
Actualizaciones
Actualizaciones
ESI
EDI
B
Actualizaciones
EDI
Incorrecto
Los tres parmetros son desplazamientos y cantidades de la memoria vdeo basadas en caracteres
(tamao palabra). Se copian tanto caracteres como indique el tercer parmetro desde un lugar de la memoria
de vdeo a otro dentro de la misma.
! PUBLIC void vid_vid_copy(unsigned src, unsigned dst, unsigned count);
VVC_ARGS
!
4 + 4 + 4 + 4 ! 4 + 4 + 4
es edi esi eip src dst ct
_vid_vid_copy:
push
esi
push
edi
push
es
mov
mov
mov
mov
cmp
jb
! salvar registros
esi, VVC_ARGS(esp)
!
edi, VVC_ARGS+4(esp) !
edx, VVC_ARGS+4+4(esp)!
es, (_vid_seg)
!
esi, edi
!
vvc_down
26
esi origen
edi destino
edx contador
el destino es el segmento de vdeo
copiamos hacia delante o hacia atrs?
Fichero klib386.c
vvc_up:
cld
vvc_uploop:
and
and
mov
mov
sub
cmp
jbe
mov
0:
mov
sub
cmp
jbe
mov
0:
sub
shl
shl
rep
eseg o16 movs
shr
shr
test
jnz
jmp
vvc_down:
std
lea
lea
vvc_downloop:
and
and
mov
lea
cmp
jbe
mov
0:
lea
cmp
jbe
mov
0:
sub
shl
shl
rep
eseg o16 movs
shr
shr
test
jnz
cld
!jmp
vvc_done:
pop
pop
pop
esi,
edi,
ecx,
eax,
eax,
ecx,
0f
ecx,
(_vid_mask)
(_vid_mask)
edx
(_vid_size)
esi
eax
eax
eax,
eax,
ecx,
0f
ecx,
(_vid_size)
edi
eax
eax
! ecx contador
! eax tamao bloque de vdeo
edx, ecx
esi, 1
edi, 1
esi, 1
edi, 1
edx, edx
vvc_uploop
vvc_done
esi, -1(esi)(edx*1)
edi, -1(edi)(edx*1)
esi,
edi,
ecx,
eax,
ecx,
0f
ecx,
eax,
ecx,
0f
ecx,
edx,
esi,
edi,
(_vid_mask)
(_vid_mask)
edx
1(esi)
eax
eax
1(edi)
eax
eax
ecx
1
1
! ecx contador
esi, 1
edi, 1
edx, edx
vvc_downloop
vvc_done
es
edi
esi
! restablecer registros
ret
! retornar
27
Fichero klib386.c
nmero de
bytes < 101?
ubicacin de los
datos en la fuente
NO
copiar de 0 a 3 bytes
para alinear bytes de
inicio
(1)
(2)
copiar de 0 a 3 bytes
para alinear bytes de
final
(3)
copiar de 0 a 9 bytes
FIN
28
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(1)
(2)
(3)
Fichero klib386.c
Los parmetros son los siguientes: el primero indica el nmero del proceso emisor del mensaje; el
segundo indica una direccin de memoria en clicks (para mquinas Intel un click=256 bytes); el tercero indica
el desplazamiento en bytes que hay que aadirle al parmetro anterior; el cuarto indica la direccin destino del
mensaje a copiar, tambin en clicks; y el quinto es el desplazamiento en bytes que hay que aadirle al
parmetro anterior. Y cul es el tamao del mensaje a copiar? Este es un parmetro fijo definido en la
constante Msize que para mquinas con palabra de 32 bits es de 9 palabras.
!
!
!
!
!
!
CM_ARGS =
!
4 + 4 + 4 + 4 + 4
es ds edi esi eip
.align
_cp_mess:
cld
push
push
push
push
16
! 4 + 4 + 4 + 4 + 4
proc scl sof dcl dof
! salvar registros
mov
mov
mov
eax, FLAT_DS_SELECTOR
ds, ax
es, ax
! inicializamos registros de segmento
mov
shl
add
mov
shl
add
esi,
esi,
esi,
edi,
edi,
edi,
mov
stos
add
mov
rep
movs
eax, CM_ARGS(esp)
esi, 4
ecx, Msize - 1
pop
pop
pop
pop
es
ds
edi
esi
CM_ARGS+4(esp)
CLICK_SHIFT
CM_ARGS+4+4(esp)
CM_ARGS+4+4+4(esp)
CLICK_SHIFT
CM_ARGS+4+4+4+4(esp)
!
!
!
!
!
!
!
!
!
!
esi
esi
esi
edi
edi
edi
direccin
direccin
direccin
direccin
direccin
direccin
fuente en clicks
fuente en bytes
fuente completa en bytes
destino en clicks
destino en bytes
destino completa en bytes
! copiar el mensaje
ret
29
Fichero klib386.c
5.7.2.- _unlock
Anlogamente a la funcin anterior sta vuelve a habilitar las interrupciones de la CPU.
! PUBLIC void unlock();
.align 16
_unlock:
sti
ret
5.7.3.- _reset
Esta funcin restablece el procesador cargando el registro de la tabla de descriptores de
interrupciones del procesador con un apuntador nulo y ejecutando a continuacin una interrupcin software.
Esto tiene el mismo efecto que un reset de hardware.
! PUBLIC void reset();
_reset:
lidt
int
.sect .data
idt_zero:
.sect .text
(idt_zero)
3
.data4 0, 0
30
Fichero klib386.c
5.7.4.- _enable_irq
Esta funcin es algo complicada: opera en el nivel de los chips controladores de interrupciones para
habilitar interrupciones de hardware individuales.
colocar en CL la
mscara para habili-tar
IRQ solicitado1
NO 8259 master
IRQ
8?
S 8259 slave
Leer IMR
Leer IMR
establecer a 0 el bit
adecuado del IMR
establecer a 0 el bit
adecuado del IMR
Copiar el resultado en
el IMR
Copiar el resultado en
el IMR
FIN
(1): debe realizarse de tal forma que cuando se quiera habilitar la IRQ 12, por ejemplo, se habilite la IRQ 4 del
esclavo, es decir, el rango es IRQ = [8, 15] equivalente a IRQ = [0, 7] del 8259 que acta como esclavo.
31
Fichero klib386.c
ah, ~1
ah, cl
cl, 8
enable_8
INT_CTLMASK
al, ah
INT_CTLMASK
popf
ret
.align 4
enable_8:
inb
andb
outb
INT2_CTLMASK
al, ah
INT2_CTLMASK
popf
ret
! al IMR
! al mscara & IMR
! bit=0 en el chip 8259 slave
! restablecemos registro de flags
! retornar
5.7.5.- _disable_irq
Anlogamente a la funcin anterior esta sirve para deshabilitar interrupciones hardware individuales.
El nico parmetro que necesita esta funcin es el nmero de irq y retorna verdadero y si la
interrupcin no estaba todava deshabilitada.
32
Fichero klib386.c
colocar en CL la
mscara para inhabilitar IRQ solicitado1
NO 8259 master
S 8259 slave
IRQ
8?
Leer IMR
Leer IMR
IRQ ya
desactivada?
SI
NO
establecer a 1 el bit
adecuado del IMR
IRQ ya
desactivada?
NO
FIN
Copiar el resultado en
el IMR
establecer a 1 el bit
adecuado del IMR
Copiar el resultado en
el IMR
FIN
33
SI
Fichero klib386.c
Para habilitar interrupciones hardware con irq menor que 8 tambin se podra haber usado la
siguiente combinacin de las funciones _out_byte e _in_byte:
out_byte(INT_CTLMASK, in_byte(INT_CTLMASK) | (1 << irq));
16
ecx, 4(esp)
ah, 1
ah, cl
cl, 8
disable_8
INT_CTLMASK
al, ah
dis_already
al, ah
INT_CTLMASK
! already disabled?
eax, 1
INT2_CTLMASK
al, ah
dis_already
al, ah
INT2_CTLMASK
! already disabled?
eax, 1
eax, eax
! already disabled
5.7.6.- _bios_13
Esta funcin no es compleja en s, sino el marco en el que est ubicada. Pasamos a explicarlo: Minix
no utiliza normalmente los servicios de E/S que le ofrece la BIOS, sino que define sus propios drivers para
acceder a los dispositivos. Sin embargo, en los ordenadores que no son completamente compatibles con el
estndar IBM PC, debe utilizar sta para tal fin.
El marco de esta funcin engloba slo al disco duro. Cuando ste no es AT, Minix debe utilizar el
servicio 13 de la bios para poder leer y escribir en el mismo. El cdigo de que realiza dicha tarea se encuentra
en el fichero bios_wini.c.
Como paso previo, para poder realizar esta tarea, es necesario restablecer todos los registros y tablas
del procesador al estado en el que se encontraban antes de que Minix se cargase (estado que fue salvado por el
monitor). Una vez finalizada la operacin de disco es necesario realizar el proceso inverso que deja el estado
del procesador tal como se encontraba antes del acceso a disco. Ambas tareas las lleva a cabo la funcin
bios_13.
34
Fichero klib386.c
tiempo de compilacin
tiempo de ejecucin
Arranque de la BIOS
#if ENABLE_AT_WINI
{ "at",
at_winchester_task
#endif
},
#if ENABLE_BIOS_WINI
{ "bios",
bios_winchester_task
#endif
},
#if ENABLE_ESDI_WINI
{ "esdi",
esdi_winchester_task
#endif
},
#if ENABLE_XT_WINI
{ "xt",
xt_winchester_task
#endif
};
35
*task;
},
Fichero klib386.c
inb
movb
inb
push
mov
and
outb
movb
outb
INT2_CTLMASK
ah, al
INT_CTLMASK
eax
eax, (_irq_use)
eax, ~[1<<CLOCK_IRQ]
INT_CTLMASK
al, ah
INT2_CTLMASK
mov
push
eax, cr0
eax
mov
mov
xchg
eax, SS_SELECTOR
ss, ax
esp, (_mon_sp)
mov
mov
mov
mov
push
push
o16 jmpf
ds, ax
es, ax
fs, ax
gs, ax
cs
return
16+2*4+5*2+2*4(esp)
return:
o16 pop
o16 pop
o16 pop
o16 pop
o16 pop
lgdt
jmpf
(_Ax)
(_Bx)
(_Cx)
(_Dx)
(_Es)
(_gdt+GDT_SELECTOR)
CS_SELECTOR:csinit
csinit: mov
mov
mov
mov
mov
mov
xchg
lidt
andb
36
!
!
!
!
eax, DS_SELECTOR
ds, ax
es, ax
fs, ax
gs, ax
ss, ax
esp, (_mon_sp)
! volver a intercambiar punteros de pila
(_gdt+IDT_SELECTOR)
! volver a cargar la tabla de descr. de interrup.
(_gdt+TSS_SELECTOR+DESC_ACCESS), ~0x02 ! pone a cero el bit de ocupado
! de la TSS
mov
ltr
ax, TSS_SELECTOR
ax
pop
mov
eax
cr0, eax
pop
eax
pop
outb
movb
outb
eax
INT_CTLMASK
al, ah
INT2_CTLMASK
popf
pop
pop
pop
pop
ret
ebx
edi
esi
ebp
.sect .bss
.define _Ax,
.comm _Ax,
.comm _Bx,
.comm _Cx,
.comm _Dx,
.comm _Es,
.sect .text
37
Fichero klib386.c
Fichero misc.c
Direccin en binario
Direccin en clicks
256
0000 0001
512
0000 0010
1024
0000 0100
256
8
En un ordenador compatible con los IBM PC puede haber dos o tres regiones de memoria no
continuas.
SHADOW
SHADOW_MAX
SHADOW_BASE
EXTENDIDA
ext_memsize
EM_BASE
BAJA
low_memsize
38
Fichero misc.c
La BIOS informa al monitor de arranque el tamao del intervalo ms bajo, que los usuarios del PC
conocen como memoria ordinaria, y el del intervalo de memoria que comienza encima del rea de la ROM
(memoria extendida). A su vez, el monitor pasa los valores como parmetros de arranque, que son
interpretados por cstart y se escriben en low_memsize y ext_memsize durante el arranque. La tercera regin es
la memoria sombra, en la que puede copiarse la ROM de la BIOS para mejorar el rendimiento, ya que la
memoria ROM normalmente es ms lenta que la RAM.
Mem_init slo es invocada por la funcin principal main, cuando se inicia Minix. Su funcin es la
inicializar las tablas donde se almacenan el tamao y la base de cada una de las tres zonas de memoria
anteriores.
#define EM_BASE
0x100000L
#define SHADOW_BASE 0xFA0000L
#define SHADOW_MAX 0x060000L
39
Fichero misc.c
6.2.- env_parse
Esta rutina tambin se usa durante el inicio del sistema.
El monitor de arranque puede pasar cadenas arbitrarias como DPETH0=300:10 a Minix en los
parmetros de arranque. Env_parse trata de encontrar una cadena cuyo primer campo coincida con su primer
argumento, y luego extraer el campo solicitado. Los comentarios del cdigo explican el uso de la funcin, que
se proporciona principalmente para ayudar al usuario que desea agregar nuevos controladores que tal vez
requieran parmetros. El ejemplo DPETH0 se usa para pasar informacin de configuracin a un adaptador
de Ethernet cuando se incluye apoyo de red durante la compilacin de Minix.
PUBLIC int env_parse(env, fmt, field, param, min, max)
char *env;
/* variable de entorno a inspeccionar */
char *fmt;
/* template to parse it with */
int field;
/* field number of value to return */
long *param;
/* address of parameter to get */
long min, max;
/* minimum and maximum values for the parameter */
{
char *val, *end;
long newpar;
int i = 0, radix, r;
if ((val = k_getenv(env)) == NIL_PTR) return(EP_UNSET);
if (strcmp(val, "off") == 0) return(EP_OFF);
if (strcmp(val, "on") == 0) return(EP_ON);
r = EP_ON;
for (;;) {
while (*val == ' ') val++;
if (*val == 0) return(r);
if (*fmt == 0) break;
/* not a number */
if (i == field) {
/* The field requested. */
if (newpar < min || newpar > max) break;
*param = newpar;
r = EP_SET;
}
}
}
badenv:
printf("Bad environment setting: '%s = %s'\n", env, k_getenv(env));
panic("", NO_NUM);
/*NOTREACHED*/
}
40
Fichero misc.c
#endif /* DEBUG */
41
Preguntas interesantes
7.- Cuestiones
1) Por qu crees que la librera est escrita en ensamblador?
Hay dos razones:
a) hay una mejora en el rendimiento (en el tiempo de ejecucin),
b) Minix no se escribi para compiladores de alto nivel como Turbo C, Borland C, ... que realizan
operaciones de bajo nivel.
2) Cules son las cuatro categoras principales de interrupciones?
Interrupciones en respuesta a algn acontecimiento, tal como la pulsacin de una tecla (interrupcin
hardware).
Interrupciones generadas por la CPU debido a alguna anomala en el programa, como una divisin
por cero (excepciones).
Interrupciones generadas por programas, por ejemplo las llamadas al sistema (interrupciones
software).
Interrupciones que requieren intervencin inmediata de la CPU, como una cada de voltaje
(interrupciones no enmascarables).
3) A qu se debe la existencia de las funciones port_read_byte y port_write_byte?
Estas funciones se han aadido para que sean usadas en aquellos dispositivos perifricos antiguos
que nicamente pueden realizar transferencias desde memoria al puerto y viceversa, en unidades de byte.
4) Bajo qu circunstancias se utiliza la rutina _bios_13 y cul es su funcin?
Se utiliza cuando el disco duro del PC no sigue el estndar establecido en el IBM PC, y se requiere
acceder a las rutinas de la bios para acceder al disco.
Como paso previo, para poder realizar esta tarea, es necesario restablecer todos los registros y tablas
del procesador al estado en el que se encontraban antes de que Minix se cargase (estado que fue salvado por el
monitor). Una vez finalizada la operacin de disco es necesario realizar el proceso inverso que deja el estado
del procesador tal como se encontraba antes del acceso a disco. Ambas tareas las lleva a cabo la funcin
bios_13.
5) Cul es la diferencia entre la funcin _phys_copy y la funcin _cp_mess ?
Ambas funciones sirven para copiar datos dentro de la memoria. La diferencia radica en que
_phys_copy puede copiar un bloque de datos de cualquier tamao y sin estar alineado, y la funcin _cp_mess
est optimizada para la copia de mensajes entre procesos, en la cual el tamao del mensaje es fijo y los datos
se encuentran alineados en palabra.
42
8.- Bibliografa
80386/80286 assembly language programming
William H. Murray III, Chris H. Pappas
Editorial Osborne McGraw-Hill, 1986
Sistemas Operativos: Diseo e implementacin Segunda Edicin
Andrew S. Tanenbaum, Albert S. Woodhull
Editorial Prentice Hall, 1997
PC Interno 5
Utilidades y Librera del Kernel: klib.s
Alexis Caballero Caballero, Pablo Prez Gonzlez
Ampliacin de Sistemas Operativos, curso 1999-2000
43
Bibliografa