💾 Archived View for texto-plano.xyz › peron › articulos › direccionamiento_dos.gmi captured on 2023-06-16 at 16:53:30. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-03-01)

-=-=-=-=-=-=-

Direccionamiento de Memoria RAM en DOS

A mediados de la década de 1990, con el precio de la memoria RAM en caída, era posible acceder a 4MB en equipos que corrían DOS. Esto hubiese bueno, ya que posibilitaba crear programas mucho más potentes. Sin embargo, la forma infausta en la que debías manejar la memoria bajo M$-DO$, terminó provocando una complejidad mucho mayor.

La falla tenía un poco que ver con Intel y bastante más con Micro$oft. En 1981, IBM lanzó la primera PC, su 5150. La había diseñado alrededor del microprocesador Intel 8088. Esta CPU de 16 bits estaba limitada por usar registros de 16 bits (1 MB de memoria), pero como Intel quería que fuese capaz de acceder a un espacio de direccionamiento de memoria de 20 bits (4MB), inventaron una abominación denominada "direccionamiento segmentado de memoria". En este esquema se destinaban DOS REGISTROS chicos de 16 bits (uno en forma de segmento y otro de offset) y se los cominaba para formar una dirección de memoria de 20 bits. Así se podrían direccionar 4 MB.

Esto resultó en la dificultad para la manipulación del puntero, bastante proclive a causar errores ya que diferentes puestas de segmentos/offset podían dirigir directamente a una dirección de memoria ya ocupada por encima del 1er MB de RAM (y causar problemas, obvio). También había dramas relacionados con la aritmética de puntero, ya que toda vez que el puntero se daba invertía, el segmento no se actualizaba automáticamente en concordancia.

La RAM del sistema se hizo un revuelto total con la aparición de los microprocesadores Intel 286 y el 386SX, que direccionaban ahora 24 bits, y se volvió delirante con el 386DX y el 486 - ya que ambas disponian ahora de un bus de direccionamiento de 32 bits. El espacio de direccionamiento era mucho para lo que podía lograrse con el truquito de la segmentación de 20 bits. La solución escogida por Micro$oft fue recurrir a gestores de memoria por software (como los programas EMM386.EXE y HIMEM.SYS). Ambos programas residentes en memoria podían ser capaces de proveer medios para solventar la memoria RAM no direccionable que se encontraba por encima de la barrera de "memoria inferior" al primer Megabyte instalado en el sistema.

Debería haber habido una solución más simple. Intel permitía que sus CPUs incluyeran dos modos de funcionamiento:

Lo que llamaron MODO REAL (que hacía que la CPU se comportara como si fuese un 8088 muy rápido), y luego estaba el MODO PROTEGIDO, en el cual se liberaba toda la potencia de las CPUs nuevas. Al usar MODO PROTEGIDO, se usaban registros de 32 bits lo suficientemente grandes como para direccionar toda la RAM en placa (algo conocido como "direccionamiento directo").

Hubiese funcionado si el sistema operativo hubiese contado con la posibilidad de correr en modo protegido. Sin embargo, en nombre de la retrocompatibilidad, Micro$oft hizo que el DO$ naciese viejo y sólo pudiese funcionar en MODO REAL, lo que terminó encerrando a los desarrolladores de DOS en una era de la programación de 16 bits, que prácticamente estaba al final de su ciclo productivo.

Por eso siempre digo que Micro$oft retrasó el advenimiento del cómputo de 32 bits no menos de 8 años, a cambio de contar con una masa crítica de desarrollo comercial gracias al concepto de "compatibilidad por estándar de facto".

Aún asi, donde hay una necesidad nace un derecho, y con la frustración que provocaba un DOS anquilosado, creció una oportunidad.

Si bien existieron muchos productos capaces de solucionar el tema, sobresalen dos compañías en particular, en una mancomunidad ganadora. La unión virtuosa del compilador de C de Warcom International Corporation y el "Extensor de DOS" DOS/4GW de Rational Systems permitía correr programas en Modo PROTEGIDO, a la vez que retenían en acceso a las funciones de 16 bits del DOS.

Extensor DOS/4GW

La manera normal para realizar una "llamada de sistema" en DOS era usar una instrucción de interrupción de software con el parámetro 21H. En programación C, esto constinuía una abstracción del encabezado DOS.H - encargado de llevar a cabo todo el trabajo de bajo nivel del sistema operativo.

Ambos mundos tenían que estar "puenteados" para permitir que un programa corriese en uno de los Modos de procesador y el sistema operativo lo hiciera en el otro. Para ello se instituía una capa intermedia denominada "Extensor DOS" - la cual era capaz de correr en ambos modos, biejecutble - y se la insertaba entre el programa y el sistema operativo.

Cuando inicializabas el Extensor DOS, este colocaba llamadas en la Tabla de Vector de Interrupción del Sistema Operativo, y allí metía sus propias rutinas. Desde el punto de vista de la aplicación todo resultaba transparente, y no tenías que alterar ningún código. Para disparar las llamadas de sistema que no estaban enlazadas al Extensor (por ejemplo, si querías usar la INT 33H para leer el registro del mouse), el Extensor te ofrecía la interfaz especial llamada DPMI, en la cual el interruptor 31H que se encargaba de traducir los pedidos de registros de 32 bits a 16 bits, tal que las rutinas de la Tabla de Vector de Interrución las entendiesen.

DPMI (Interfaz de Modo Protegido DOS) fue desarrollada originalmente para permitir que Windows 3.0 pudiese correr aplicaciones de 32 bits y que fuese compatible con un sistema operativo de 32 bits proyectado entre IBM y Microsoft llamado OS/2)

Cuando el extensor interceptaba una llamada de sistema operativo, tenía mucho trabajo que hacer:

1. Realizaba la llamada requerida (ej. Una dirección de 32 bits debía ser expresada como un offset de 32 bits con un segmento de 16 bits.

2. Conmuta la CPU a MODO REAL.

3. Reenvía la llamada al DOS.

4. Recoge los resultados y los convierte desde registro de 16 bits a 32 bits.

5. Conmuta la CPU a MODO PROTEGIDO nuevamente.

Las aplicaciones más dependientes de la alta performance se la pasaban conmutando entre modo real y protegido. Como vimos, esto constituia un problema en las CPUs 286 porque Intel nunca imaginó que un programa podría querer conmutar ida y vuelta entre MODO REAL y MODO PROTEGIDO. Se terminaban usando varios trucos de sistema, entre ellos falsear un reseteo de teclado con Ctrl+Alt+Del para resetear la CPU sin reiniciar realmente.

Si bien el problema era volver, en los Intel pasar de MODO REAL a MODO PROTEGIDO era simple. Solo tenías que usar 6 instrucciones mnemónicas oara colocar el Registro de Control del bit 0 al 1 y activarlo.

cli                     ; desactiva las interrupciones.
lgdt [gdtr]             ; establece la dirección de memoria de la Tabla de Descriptor Global.
mov eax, cr0 or al, 1   ; Prepara el MODO PROTEGIDO.
mov cr0, eax

; Vacía el pipeline con una instrucción de salto lejano.
JMP 08h:PModeMain

PModeMain:
; carga DS , ES , FS , GS , SS , ESP.

Watcom

El Extensor DOS era mágico, pero bastante difícil de presentar como producto integrado real. La inicialización para localizar el DOS4GW.EXE y el programa a ejecutar, configurara ambos y les diera arranque solía requerír múltiples pasos difíciles de hacer y casi 100 líneas de código en lenguaje C. Llevaba mucho tiempo - pero sobre todas las cosas significaba que la ejecución se tornaba sumamente técnica: simplemente por eso casi nadie usaría estos programas "de 32 bits para DOS".

Lo que realmente se necesitaba era disponer de un ambiente integrado en el cual el compilador y en enlazador se encargasen de embutir tanto al extensor y como a la aplicación en sí dentro de un fichero ejecutable.

La solución vendría del extremo norte.

En 1979 en la Universidad de Waterloo en Ontario, Canadá comenzaron a desarrollar un compilador multiuso llamado Watcom. Inicialmente sólo soportaba BASIC, pero con el correr de los años los estudiantes lo mejoraron con soporte para nuevos lenguajes y sistemas operativos. Para 1987 tres doctorados en ciencias del cómputo (Fred Crigger, Ian McPhee y Jack Schueler) pudieron lograr el primer compilador de C que corríese en la IBM PC con procesador Intel 386. Se asociaron formando la Watcom Internacional Corporation, y bajo el loguito de un rayo eléctrico se lanzaron a publicitar su compilador haciendo foco en su desempeño. Para 1993 habían alcanzado mejoras considerables con el Watcom C/386. La versión 9.0, de sólo 639 dólares, se la consideraba la mejor disponible para MS-DOS.

WATCOM C/C++ producía código que era al menos del doble de rápido que los compiladores Borland o Microsoft, y al menos era cinco veces más rápido.

No sólo eran programadores talentosos, también destacaron en el marketing de su producto. A principios de los 90s no podías abrir una revista de computación profesional sin encontrar todas las variedades de la líena de compiladores Watcom. Todas subrayaban la presencia del Extensor DOS que liberaba a los programadores del odiado modo de 16 bits y les permitía "liberar el poder de 32 bits".

Uno de los trucos de márketing de Watcom fue arrancar directamente con una "versión 6", Esto los dejaba al menos una versión por delante de sus competidores directos, Borland y Microsoft. Tener un número de versión más alto llevaba a la noción de ser "mas avanzados que sus competidores". A su vez, una versión 1.0 hubiese sugerido que contenía muchos bugs, mientras que la versión seis probablemente ya estaba sumamente pulida.

ANSI C

El combo Watcom/Extensor hacía mucho más simple la programación y también hacía que los programas corrieran más rápido, pero el tercer aspecto de la programación de modo protegido - menos obvio pero muy importante, era que se podía traer al lenguaje C al mundo del Modo Real bajo MS-DOS en una IBM PC, y que fuese capaz de manipular segmentos. Para esto había que usar le lenguaje ANSI C estándar pero también usar extensiones para el mismo.

Orignalmente ni "C para DOS" ni las funciones de E/S eran portables, y era imposible usar un programa para UNIX y compilarlo para que funcionase en DOS.

Pero el combo Watcom/Extensor permitía ahora hacer esto, con lo cual se podían utilizar muchísimas aplicaciones Unix - incluidas las del ecosistema GNU - para programar para DOS.