Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - lweb20

#21
ASM / Modo protegido, dolor de cabeza
4 Marzo 2013, 01:43 AM
Hola que tal jeje. Soy yo de nuevo, me pareció muy creativo el título.

Llevo ya varios meses con el desarrollo de un sistema operativo en 32-bits en modo protegido (obviamente) y quisiera aquí tratar todos los problemas y pequeños detalles (trataré) sobre el modo protegido.

Este post va a ser un poco informativo pero va a haber más preguntas que respuestas. Quiero aclarar que no soy un experto pero no puedo negar que se aprende muchas cosas en el transcurso del camino. No quiero caer mal ni mucho menos quiero ofender a alguien.

¿Por qué elegí 32-bits?
- Porque 16-bits es muy limitado y vulnerable a ataques de aplicaciones al hardware (modo real)
- Porque la mayoría de lenguajes de alto nivel (que son los más fáciles de programar a mi parecer) usan 32-bits. Aclaro que gcc existe una forma de usar 16-bits

Características principales del modo protegido de 32-bits
- No interrupciones de la BIOS (que miedo :S)
- Puedes crear tus propias interrupciones
- Prácticamente 2 niveles de acceso (sistema* y usuario - ring0 y ring3)
- Entre otros que poco a poco voy a ir comentando

Lo interesante del modo protegido
- Crear drivers (controladores)
- Entrar y salir del modo usuario
- Multitarea
- Acceso directo a la memoria (modo sistema*)
- Posibilidad de usar out para enviar comandos a dispositivos (*)
- Manejo avanzado de energía (APM, ACPI)
- Ejecutar aplicaciones de distintas unidades de almacenamiento
- Crear uno mismo sistemas de archivos (hechos y propios)
- Modo virtual

Mis dudas ;D
Aquí si pido ayuda si alguien tiene alguna idea de lo que hablo. Disculpen si son muchas pero llevo tiempo con estas dudas y he tenido más que he ido solucionando poco a poco.

- Entrar al modo virtual y salir (ejecutar alguna interrupción de la BIOS)
- Salir del modo usuario (ya sé entrar :D)
- Ejecutar programas PE (los básicos, buscar el main y ejecutarlo)
- Necesito un manual de hardware del modo protegido. Sobre todo usando el in y el out.


Gracias por leer y disculpen la molestia. Sé que no es su obligación contestar y si podría poner puntos lo haría :)




Nunca edito mis mensajes


* creo
#22
ah ok perdon no sabía gracias. Hasta otro hilo :) DECLARO FIN DEL TEMA
#23
Sí xD pensé que me estaba equivocando y me pareció gracioso cuando comentaste eso.

Bueno, alguien sabe si no es mucha molestia un manual de modo protegido en español. Me serviría bastante. No importa si es asm (que sea sintaxis intel por favor) o si es C/C++. Gracias.

Sobre todo ejecutar de alguna forma interrupciones de la BIOS mediante out o algo así :P


Para Eternal Idol 7D:

Logré hacer algo interesante con el código que me pasaste:

Antes que nada el pusha y popa son necesarios ya que me mueve la pila creo el programa (esp creo).

_asm pusha
int r = ((int(*)(void))programa)();
_asm popa

pantalla.Escribir("\nEl resultado de la aplicación fue: %i", r);
#24
Cita de: avesudra en  4 Marzo 2013, 00:34 AM
Bueno, es la CPU quien las interpreta. Creo que me has entendido mal porque no he dicho que estén fuera  :laugh:

Por cierto bastante interesante el post, que chulo tener tu S.O.

CitarEnsamblador en teoría es fácil de aprender  porque tiene "pocas instrucciones"(muchas menos que otros lenguajes)

:laugh:


Está bueno el manual, muy bueno  ;-)
#25
Gracias por la información avesudra pero juraba que las instrucciones estaban dentro de la CPU
#26
Sí eso es lo que pensaba, pero el único debugger que "conozco" (entre comillas) es bochs y la verdad que con mis pocos conocimientos de asm (me confunde muchas instrucciones) no me ayuda mucho. Lo que me ayuda más es el print, es decir voy imprimiendo "estados" como pseudocódigo en la pantalla (obviamente puede fallar cuando se trata de problemas en el administrador de memoria, pero si no hay problemas sí sirve). En el caso del esp, ebp, esi y edi estoy super perdido. La mayoría de los manuales y guías están en inglés y la verdad que yo me confundo cuando es demasiado contenido. No es que no quiera estudiar o algo por el estilo sino que es mucho más sencillo leer información en español hasta incluso testear códigos e ir poco a poco solucionando los problemas a leer un manual inmenso en inglés (que me defiendo pero como digo me confundo si es demasiado). Puedo entender una cosa y es otra o cosas así. Gracias por todo, me diste ánimos ya que me había desanimado. Bueno mientras estaba solucionando ese problema del gcc también creaba un algoritmo para ejecutar programas PE y sí que es más difícil de lo que pensaba.
#27
:o increible gracias :)

Fíjate el la solución 2 ya no uso el pusha ni el popa (aunque no lo dije :P). Creo que el problema fue que nunca liberé la memoria del buffer ya que la moví directamente a 0x10000.
#28
Acabo de hacer una depuración simple y el error está en call. Depuración simple es para mi por ejemplo:


PSEUDOCÓDIGO:

IMPRIMIR "leer archivo - inicio"
LEER_ARCHIVO
IMPRIMIR "leer archivo - fin"
etc...

Cualquier novedad aviso. Ahora voy a depurar con bochs

EDIT

Luego de corregir un problema que tenía con el bochs y la disquetera he descubierto algo que no tiene mucho sentido.  :o

El error sigue ocurriendo pero cuando imprimo el contenido de la variable con un for y luego ejecuto el programa funciona todo correctamente.

Explicándome mejor:

Al solamente ejecutar el código con call sucede el page fault pero al imprimir la memoria de la variable en los dos casos (antes de copiarla a 0x10000 y después de copiarla) todo funciona normal.


EDIT 2

Una consulta. Por partes del manual que lei vi que se corregían algunos errores como ese page fault aumentando o disminuyendo el registro esp; ¿qué es lo que hace ese registro? no lo entiendo.


¡NOTICIA!

SOLUCIONÉ EL PROBLEMA

_asm pusha
_asm call programa
_asm popa

Pues lo que hice fue poner en el stack a los registros y luego liberarlos. Pero aún no entiendo el por qué :S ¿Alguien sabe la respuesta?

NOTICIA 2:

La solución era:

1. Abrir el archivo
2. Crear un buffer para los datos del archivo (malloc)
3. Leer el archivo y almacenarlo en el buffer
4. CREAR OTRA VARIABLE con la dirección de memoria 0x10000
5. Copiar el contenido del buffer a 0x10000
6. Liberar el buffer (free)
7. Ejecutar 0x10000
8. NO Liberar 0x10000 (no se debe liberar)

Gracias y ahí está la solución por si alguna otra persona como yo (:P) tiene un problema similar xD

Gracias por todo. Problema solucionado




YEAH  ::)
#29
Sí, tienes razón. Estuve revisando y el problema desaparece al quitar el "free" del administrador de memoria. Extraño.. super extraño. Ahí voy a sufrir ya que es muy complejo ese administrador de memoria :S


EDIT 1:

Pero aún así quiero saber qué son esas instrucciones (como dije no soy experto en asm). Por qué el gcc las crea y para qué. Sólo por curiosidad; y ¿está bien quitar la sección con strip?

EDIT 2:

Estoy probando el administrador de memoria con un ejemplo pequeño - usando 100000 bytes de memoria - y no me presenta problemas. Puede ser que la posición de memoria asignada por el programa ejecutable no sea la adecuada o algo así. Esa parte la tengo que estudiar bien. De todas maneras gracias por sacarme de varias dudas.

EDIT 3:

Alaa otro problema: El administrador de memoria parece estar bien. Resulta que todo está bien cuando descomento esta línea:

_asm call programa

Que es la que ejecuta los bytes en la variable "programa". No sé que está pasando, en serio; ya probé de todo :(
#30
Sí, el programa se carga en esa dirección de memoria. Uso memmove para mover los datos a esa dirección de memoria. Me muestra el mensaje, y también me parece extraño que se ejecute el otro código (ya que sale con un ret). ¿Alguna idea? Investigaré un poco más mi código en estas horas.



EI: juntando mensajes. No escribas mensajes consecutivos, edita.



Bueno, estuve revisando y encontré una supuesta solución (no funciona):

gcc -march=i686 -std=gnu99 -ffreestanding -c test.c -masm=intel
strip -R .eh_frame test.o
ld -o test -Tlink.ld test.o
objcopy -S -O binary test ..\programa.exe

¿está bien quitar esa sección? porque ahora no me muestra ningún mensaje. Cualquier noticia vuelvo a publicar.

EDIT:

Quedó así con el ndisasm:

00000000  55                push ebp
00000001  89E5              mov ebp,esp
00000003  83EC10            sub esp,byte +0x10
00000006  C745FC00000000    mov dword [ebp-0x4],0x0
0000000D  31C0              xor eax,eax
0000000F  8B5DFC            mov ebx,[ebp-0x4]
00000012  CD80              int 0x80
00000014  C9                leave
00000015  C3                ret
00000016  90                nop
00000017  90                nop
00000018  48                dec eax
00000019  6F                outsd
0000001A  6C                insb
0000001B  61                popad
0000001C  206D75            and [ebp+0x75],ch
0000001F  6E                outsb
00000020  646F              fs outsd
00000022  20646573          and [ebp+0x73],ah
00000026  6465204743        and [gs:edi+0x43],al
0000002B  43                inc ebx
0000002C  2028              and [eax],ch
0000002E  49                dec ecx
0000002F  6E                outsb
00000030  7465              jz 0x97
00000032  6C                insb
00000033  205379            and [ebx+0x79],dl
00000036  6E                outsb
00000037  7461              jz 0x9a
00000039  782C              js 0x67
0000003B  207072            and [eax+0x72],dh
0000003E  6F                outsd
0000003F  677261            jc 0xa3
00000042  6D                insd
00000043  61                popad
00000044  2E657865          gs js 0xad
00000048  2920              sub [eax],esp
0000004A  7632              jna 0x7e
0000004C  2100              and [eax],eax
0000004E  0000              add [eax],al


Y adjunto la imagen resultante (archivo final):



Sigo sin comprender por qué tanto código (disculpa la ignorancia) ya que mi código en nasm sólo hice esto:

[bits 32]
[org 0x10000]

jmp codigo
stringToPrint db "Hola mundo!", 0

codigo:
xor eax, eax
mov ebx, stringToPrint
int 0x80
ret 0



EDIT 2:

:o

Y ahora que lo reviso bien el código no me genera ninguna excepción hasta que intento ejecutar el mismo comando. Voy adelantando: mi sistema usa una línea de comandos con múltiples pantallas (eso es lo de menos). Me explico mejor: el comando "ejecutar" (es temporal) ejecuta el programa "programa.exe" con normalidad (sin el strip) hasta que escribo el mismo comando y PAGE FAULT!. Lo más extraño es que funciona normal con nasm, y como ya había mensionado con el gcc pero quitando los supuestos bytes "basura" (garbage)