De broncode voor MS-DOS 1.25 is officieel door Microsoft vrijgegeven. De geschiedenis van computers en standaardsoftware fascineert mij, dus voor het robijnen jubileum van de x86 wil ik deze assembleren. Dat is gemakkelijker gezegd dan gedaan...
Henk van de Kamer
Elders in PC-Active 319 lees je een artikel over het begin van wat we tegenwoordig het x86-tijdperk noemen. IBM-model 5150 was een vreemde mengelmoes van gedachten. Zo had het geheel een 32 kB ROM met Microsoft BASIC om in ieder geval te kunnen concurreren in de bloeiende homecomputermarkt. De traditionele IBM-klanten namen dat niet serieus, want het model met alleen een cassette werd een flop. Dat is niet bedoeld als grap richting de variant met een floppydrive. Die moest het in de standaardconfiguratie doen met een enkele 160 kB +single sided double density+ versie.
HARDDISK?
Er waren nog meer beperkingen. Zo was de processor een 8088, ofwel het gecastreerde broertje van de 8086. De eerste is intern eveneens 16-bits, maar heeft naar buiten slechts een 8-bits data- bus. De belangrijkste reden van al deze beperkingen was de angst dat met betere specificaties de veel duurdere mainframes niet meer verkocht zouden worden. Nogmaals tegenstrijdig, want IBM wilde met de introductie concurreren op de homecomputermarkt. Je zou dan een machine verwachten die de concurrentie ver achter zich zou laten. Echter veel van die concurrenten hadden meer geheugen en waren veel goedkoper. Tegen (fikse!) meerprijs was het geheugen uitbreidbaar tot 64 kB en kon een tweede diskettestation worden geplaatst. Negen maanden na de introductie kon met PC-DOS 1.10 ook de andere kant van de diskette gebruikt worden, zodat het totaal per diskette op 320 kB uitkwam. De voeding was te zwak om een harddisk aan te sluiten. Geen probleem, want die kon pas met de komst van PC-DOS 2.00 in maart 1983 gebruikt worden. Ondertussen waren 9 in plaats van 8 tracks per sector mogelijk en groeide de capaciteit van een diskette naar 180 kB per zijde.
BRONCODE MS-DOS
Op 25 maart 2014 gaf Microsoft toestemming om de broncode voor MS-DOS 1.25 en 2.0 vrij te geven. Op 22 september 2018 werd dat dunnetjes overgedaan door het in Github te plaatsen (https://github.com/microsoft/MS-DOS). Deze dienst was drie maanden daarvoor door Microsoft gekocht, dus dit was een logische keuze. De broncode zijn slechts zeven assembly-bestanden. Inderdaad, geen C of andere bloated programmeertalen!
Voor ons is vooral de uitleg in het mailtje van Tim Paterson – inderdaad de persoon die de basis voor dit alles heeft gelegd – van belang. Versie 1.25 was de eerste die naar OEM-klanten werd gestuurd. Versie 1.24 is identiek aan PC-DOS 1.10 van IBM. Het verschil is een kleine aanpassing. Van de zeven bestanden zijn er vier specifiek voor SCP, de voormalig werkgever van Tim Paterson. De trans.asm bijvoorbeeld is de broncode voor een Z80 naar 8086 assembly-vertaalprogramma. Tim heeft zijn QDOS/86-DOS onder CP/M-Z80 geschreven (http://bytepointer.com/masm/index.htm). In die tijd was het al gebruikelijk om programmatuur voor een nieuwe processor te bootstrappen via een reeds bestaand systeem.
De taak van een OEM was het aanpassen van een drietal bestanden naar de hardware in hun eigen systeem. De rest van MS-DOS 1.25 werd geassembleerd – dus zonder broncode – aangeleverd. Uiteraard moet Tim de broncode hebben gehad, maar deze is blijkbaar verloren gegaan? De broncode van versie 2.0 is veel completer, maar vanuit historisch perspectief ook minder interessant.
ASSEMBLEREN
Op dit punt gaan we een probleem ontdekken dat bijna nooit wordt verteld. Ongetwijfeld kent een aantal lezers de zogenaamde selfhosting compiler. Met deze kreet wordt aangegeven dat de broncode van de compiler door zichzelf gecompileerd kan worden. Klinkt goed, toch? Zo ja, download dan eens de broncode van GCC – de C-compiler die tegenwoordig door bijna iedereen wordt gebruikt. Gedaan? Mooi! Probeer deze dan eens te compileren op een kaal systeem. Tenzij je systeem minder kaal is dan een verse, commandline-gebaseerde Debian-installatie, gaat je dat niet lukken!
Zoals gezegd wordt bij de meestal met trots verkondigde selfhosting nooit verteld dat de broncode eerst verwerkt moet worden door een vorige versie of een andere reeds gecompileerde C-compiler. Het resultaat is dan de nieuwste versie van de compiler en die kan dan zichzelf compileren. In mijn ogen is dat valsspelen. En gelukkig ben ik niet de enige die daar zo over denkt. Maar dat is een Het Lab-aflevering op zich. Voor nu moet je onthouden dat de broncode van een compiler of assembler eerst door een oudere of andere versie respectievelijk gecompileerd of geassembleerd moet worden. Dus om bijvoorbeeld de asm.asm – gezien de naam is dit de broncode van een assembler – tot iets bruikbaars om te vormen, moeten we een reeds geassembleerde versie hebben. Met dat exemplaar kunnen we dan net zo goed ook de rest doen... Voor de grap – ik zou verbaasd zijn geweest als het had gewerkt – heb ik eens nasm (https://www. nasm.us/) geprobeerd: hvdkamer@obelix:~/msdos$ nasm -f bin COMMAND. ASM -o command.com
Dat geeft maar liefst 419 foutmeldingen. De reden is simpel: nasm gebruikt andere instructies in de broncode.
ZOEKTOCHT
We moeten dus op zoek naar een assembler die veertig jaar geleden al bestond. In de vrijgegeven broncode van MS-DOS 2.0 is masm.exe aanwezig en die geeft onder FreeDOS – zie Het Lab in PC-Active 315 – slechts 18 foutmeldingen. Een volgende zoektocht gaf een Microsoft Macro Assembler 1.0 diskette-image (https://winworldpc.com/
product/macro-assembler/1x). Gelukkig ook een directory met de bestanden, want het is mij (nog) niet gelukt om de 160 kB-versie onder Linux te mounten. Ook de verschillende emulatoren snappen niets van deze grootte.
Deze versie werkt probleemloos: C:\MSDOS10>m command;
The Microsoft MACRO Assembleren
Version 1.00 (C)Copyright Microsoft 1981
Warning Severe
Errors
0 0
Na afloop hebben we een command.obj ter grootte van 8.409 bytes. Het objectbestand is een tussenvorm en kan bijvoorbeeld slechts een deel van het uiteindelijke programma bevatten. Om die delen samen te voegen, ook als er maar één is, gebruiken we een linker. Deze is in de v11object directory van de vrijgegeven broncode of op de gevonden diskette aanwezig. Ik heb die laatste versie gebruikt: C:\MSDOS10>link command
Dit commando geeft een waarschuwing dat er geen stack is gedefinieerd, maar ik vermoed dat we die kunnen negeren. Na afloop hebben we een command.exe van 5.760 bytes groot. Wie in een ver verleden met DOS heeft gewerkt, zal zich nu afvragen waar de .com-versie is gebleven. Zo lang een .exe kleiner is dan 64 kilobyte, kan deze geconverteerd worden naar een .com-versie. Het benodigde programma is in de v11object directory aanwezig: C:\MSDOS10>exe2bin command command.com
Daarmee hebben we ons eerste doel bereikt: een 4.879 bytes groot bestand dat ingetikte opdrachten kan verwerken. Tenminste, als we een floppydrive zouden hebben: C:\MSDOS10>command
Command v. 1.17H
Not ready error reading drive A
Abort, Retry, Ignore?
UITDAGING?
Op dit punt moet ik helaas stoppen. Voor een bootable DOS-diskette zijn een viertal zaken nodig: bootsector, io.sys, msdos.sys en de zojuist gemaakte command.com. De stdos.asm en msdos.asm horen bij elkaar – de tweede is een include in de eerste die een aantal opties regelt – en vormen waarschijnlijk msdos.sys. Het grootste probleem is dat io.asm weliswaar een io.sys geeft, maar dan voor het product van SCP en dat is absoluut geen IBM pc-kloon. Een ander probleem is dat deze plus de overige drie .asm-bestanden niet met de gevonden m.exe geassembleerd kunnen worden. Voor deze moeten we op zoek naar een versie die ooit door Tim Paterson is geassembleerd.
De bootsector is waarschijnlijk te maken via de sys.com in de v11object-directory. Daarvoor moeten we echter een emulator hebben die overweg kan met de 160/320 kB-diskettes. Na lang zoeken heb ik een aanwijzing gevonden dat zo’n emulator zou bestaan, maar tot op heden heb ik deze niet kunnen vinden. Moderne emulatoren kunnen alleen overweg met de 180/360 kB-diskettes en die zullen niet herkend worden. Kortom: het idee dat Microsoft de broncode heeft vrijgegeven is leuk, maar is dus verre van compleet. Hetzelfde schijnt te gelden voor versie 2.0.