premiere mogrt importar essential español como archivos graphics io x86 assembly

graphics - importar - mogrt



¿Cómo puedo escribir directamente en la pantalla? (7)

Soy un adolescente que se ha interesado mucho en el lenguaje ensamblador. Estoy intentando escribir un pequeño sistema operativo en el ensamblador Intel x86, y me preguntaba cómo escribir directamente en la pantalla, sin depender del BIOS ni de ningún otro sistema operativo. Estaba buscando en las fuentes de coreboot, Linux y Kolibri, entre otras, con la esperanza de encontrar y entender algún fragmento de código que hace esto. Todavía no he tenido éxito en este sentido, aunque creo que echaré otro vistazo al código fuente de Linux, que es el más comprensible para mí de las fuentes que he buscado.

Si alguien sabe esto, o sabe en qué parte del código fuente puedo ver, agradecería que me lo dijeran.

O mejor aún, si alguien sabe cómo identificar qué puerto de E / S en una CPU Intel x86 se conecta a qué pieza de hardware, eso también sería apreciado. La razón por la que debo preguntar esto es que ni en el capítulo de entrada / salida en el Manual del desarrollador de software para arquitecturas Intel 64 e IA-32 Volumen 1: Arquitectura básica, ni en las secciones para las instrucciones de IN o OUT en el Volumen 3, ¿Podría encontrar alguna de esta información. Y porque ha sido demasiado arduo buscar las instrucciones relevantes en las fuentes que tengo.



Encontré un lugar que proporciona buena información al respecto: http://www.osdever.net/FreeVGA/home.htm Se trata de algunos detalles importantes para escribir código que se escribe directamente en la pantalla. Lo encontré en el enlace al sitio de Don Stoner (¡Gracias por el enlace, SilverbackNet!). Todavía estoy buscando más información, por lo que si alguien tiene más ideas, agradecería mucho la ayuda.



PARTE 1

Para los modos VGA antiguos, hay una dirección fija para escribir en el área de memoria de la pantalla (heredada). Para los modos de texto, esta área comienza en 0x000B8000. Para los modos gráficos comienza en 0x000A0000.

Para los modos de video de alta resolución (por ejemplo, los establecidos por la interfaz VESA / VBE) esto no funciona porque el tamaño del área de memoria de la pantalla heredada está limitada a 64 KiB y la mayoría de los modos de video de alta resolución necesitan mucho más espacio (por ejemplo, 1024 * 768 * 32-bpp = 2,25 MiB). Para evitar eso hay 2 métodos diferentes soportados por VBE.

El primer método se denomina "cambio de banco", en el que solo una parte de la memoria de visualización de la tarjeta de video se asigna al área heredada en cualquier momento (y puede cambiar la parte asignada). Esto puede ser bastante complicado. Por ejemplo, para dibujar un píxel, es posible que necesite calcular en qué banco se encuentra el píxel, luego cambiar a ese banco y luego calcular qué compensación en el banco. Para empeorar esto, para algunos modos de video (por ejemplo, modos de video de 24 bpp donde hay 3 bytes por píxel) solo la primera parte de los datos de un píxel puede estar en un banco y la segunda parte de los mismos datos de un píxel está en un banco diferente . El principal beneficio de esto es que funciona con el direccionamiento en modo real, ya que el área de memoria de la pantalla heredada está por debajo de 0x00100000.

El segundo método se llama "Linear Framebuffer" (o simplemente "LFB"), donde se puede acceder al área completa de la memoria de la tarjeta de video sin ningún cambio de banco desordenado. Debe preguntar a la interfaz VESA / VBE dónde se encuentra esta área (y generalmente se encuentra en el "agujero PCI" en algún lugar entre 0xC0000000 y 0xFFF00000). Esto significa que no puede acceder a él en modo real, y necesita usar el modo protegido o el modo largo o el "modo irreal".

Para encontrar la dirección de un píxel cuando está usando un modo LFB, haría algo como "pixel_address = display_memory_address + y * bytes_per_line + x * bytes_per_pixel". El "bytes_per_line" proviene de la interfaz VESA / VBE (y puede no ser lo mismo que "horizontal_resolution * bytes_per_line" porque puede haber relleno entre líneas horizontales).

Para los modos VBE / VESA "conmutados por banco", se convierte en algo más parecido a:

pixel_offset = y * bytes_per_line + x * bytes_per_pixel; bank_number = pixel_offset / bank_size; pixel_starting_address_within_bank = pixel_offset % bank_size;

Para algunos modos VGA antiguos (por ejemplo, el "modo 0x13" de 256 colores) es muy similar a LFB, excepto que no hay relleno entre líneas y puede hacer "pixel_address = display_memory_address + (y * horizontal_resolution + x) * bytes_per_pixel". Para los modos de texto es básicamente lo mismo, excepto que 2 bytes determinan cada carácter y su atributo, por ejemplo, "char_address = display_memory_address + (y * horizontal_resolution + x) * 2". Para otros modos VGA antiguos (modos monocromo / 2 colores, 4 colores y 16 colores), la memoria de la tarjeta de video está organizada de manera completamente diferente. Se divide en "planos" donde cada plano contiene un bit del píxel, y (por ejemplo) para actualizar un píxel en un modo de 16 colores, debe escribir en 4 planos separados. Por razones de rendimiento, el hardware VGA admite diferentes modos de escritura y diferentes modos de lectura, y puede complicarse (demasiado complicado de describir adecuadamente aquí).

PARTE 2

Para los puertos de E / S (en 80x86, "PC compatibles"), hay 3 categorías generales. El primero son los dispositivos heredados "de facto estándar" que utilizan puertos de E / S fijos. Esto incluye elementos como los chips PIC, el controlador DMA ISA, el controlador PS / 2, el chip PIT, los puertos serie / paralelo, etc. Casi cualquier cosa que describa cómo programar cada uno de estos dispositivos le dirá qué puertos de E / S usa el dispositivo.

La siguiente categoría es dispositivos heredados / ISA, donde los puertos de E / S que usan los dispositivos están determinados por los puentes en la propia tarjeta, y no hay una forma sensata de determinar qué puertos de E / S usan el software. Para solucionar esto, el usuario final debe indicar al sistema operativo qué puertos de E / S usa cada dispositivo. Afortunadamente, estas cosas crujientes se han vuelto obsoletas (aunque eso no significa necesariamente que nadie lo esté usando).

La tercera categoría es "plug & play", donde hay algún método para preguntar al dispositivo qué puertos de E / S usa (y en la mayoría de los casos, cambiar los puertos de E / S que usa el dispositivo). Un ejemplo de esto es PCI, donde hay un "espacio de configuración de PCI" que le brinda mucha información sobre cada dispositivo PCI. Para estas categorías, no hay manera de que alguien pueda determinar qué dispositivos usarán qué puertos de E / S sin hacerlo en tiempo de ejecución, y cambiar algunas configuraciones de BIOS puede hacer que cualquiera o todos estos dispositivos cambien los puertos de E / S.

También tenga en cuenta que una CPU Intel es solo una CPU. Nada impide que esas CPU se utilicen en algo que es radicalmente diferente a una computadora "compatible con PC". Los manuales de la CPU de Intel nunca le dirán nada sobre el hardware que existe fuera de la misma CPU (incluido el chipset o los dispositivos).

Parte 3

Probablemente el mejor lugar para obtener más información (que está dirigido a desarrolladores / aficionados de sistemas operativos) es http://osdev.org/ (su wiki y sus foros).


Para escribir directamente en la pantalla, probablemente debería escribir en el área del modo de texto VGA. Este es un bloque de memoria que es un búfer para el modo de texto.

La pantalla de modo de texto consta de 80x25 caracteres; cada carácter es de 16 bits de ancho. Si se establece el primer bit, el carácter parpadeará en la pantalla. Los siguientes 3 bits luego detallan el color de fondo; los últimos 4 bits del primer byte son el color del primer plano (o del carácter del texto). Los siguientes 8 bits son el valor del carácter. Esto suele ser la página de códigos 737 o 437, pero puede variar de un sistema a otro.

Here hay una página de Wikipedia que detalla este búfer, y here hay un enlace a la página de códigos 437

Casi todas las BIOS configurarán el modo en modo texto antes de que se inicie el sistema, pero algunas BIOS de computadoras portátiles no se iniciarán en modo texto. Si aún no está en modo de texto, puede configurarlo con int10h muy simple:

xor ah, ah mov al, 0x03 int 0x10

(El código anterior utiliza interrupciones de BIOS, por lo que debe ejecutarse en Modo Real. Le sugiero que ponga esto en su sector de arranque).

Finalmente, aquí hay un conjunto de rutinas que escribí para escribir cadenas en modo protegido.

unsigned int terminalX; unsigned int terminalY; uint8_t terminalColor; volatile uint16_t *terminalBuffer; unsigned int strlen(const char* str) { int len; int i = 0; while(str[i] != ''/0'') { len++; i++; } return len; } void initTerminal() { terminalColor = 0x07; terminalBuffer = (uint16_t *)0xB8000; terminalX = 0; terminalY = 0; for(int y = 0; y < 25; y++) { for(int x = 0; x < 80; x++) { terminalBuffer[y * 80 + x] = (uint16_t)terminalColor << 8 | '' ''; } } } void setTerminalColor(uint8_t color) { terminalColor = color; } void putCharAt(int x, int y, char c) { unsigned int index = y * 80 + x; if(c == ''/r'') { terminalX = 0; } else if(c == ''/n'') { terminalX = 0; terminalY++; } else if(c == ''/t'') { terminalX = (terminalX + 8) & ~(7); } else { terminalBuffer[index] = (uint16_t)terminalColor << 8 | c; terminalX++; if(terminalX == 80) { terminalX = 0; terminalY++; } } } void writeString(const char *data) { for(int i = 0; data[i] != ''/0''; i++) { putCharAt(terminalX, terminalY, data[i]); } }

Puedes leer sobre esto en esta página .


Para los puertos de E / S generales, debe pasar por el BIOS, lo que significa interrupciones. Hace muchas lunas azules, utilicé las referencias de Don Stoner para ayudar a escribir un ensamblaje en modo real, pero al cabo de unos meses lo quemé y olvidé la mayor parte de lo que sabía.


Un poco más allá de mi alcance, pero es posible que desee ver VESA .