#Klooienmetcomputers

De uitdagingen van de 8086

Arnout van Kempen over rommelen in een digitale wereld.

Zoals we enkele weken geleden al bespraken, was de 8086 van Intel bedoeld als een soort tijdelijk tussenstapje tussen de redelijk succesvolle 8080, die door de concurrerende Z80 wel werd overvleugeld, en de nog in ontwerp zijnde 8800. Met de 8800 zou een totaal nieuwe weg worden ingeslagen, toekomstbestendig, robuust en nou ja, uiteindelijk mislukt omdat de 8086 die positie in nam.

De 8086 was nadrukkelijk bedoeld om een soort opgeflufde 8080 te zijn. Dat begint al met de behuizing en de pinnen. Ik heb in mijn verzameling een Z80 en een 8086 en beiden zijn, als je de opdruk wegdenkt, simpelweg niet te onderscheiden van een 8080. Voor computerbouwers is dat prettig, want je hoeft een hoop niet opnieuw te ontwerpen als je de overstap maakt.

Toch begint hier ook meteen al het verschil zichtbaar te worden. Hoewel de 8086 evenveel pinnen heeft als de 8080, zijn er dit keer geen 16 maar 20 adrespinnen, wat een adresbus van 20 bits geeft, en een adres ruimte van 2^20=1.048.576, ofwel 1M. Veel van de voeding, klok en controle-pinnen zijn min of meer vergelijkbaar met de 8080. De databus is bij de 8086 ook nog eens 16 bits breed, waarmee het wel een echte 16-bits processor is. Maar hoe kan dat? 4 extra adreslijnen, 8 extra datalijnen, en toch nog steeds maar 40 pinnen? De oplossing is multiplexing. Heel kort samengevat: een flink aantal pinnen kan zowel adres- als data-bits doorgeven. Hoe dat technisch werkt laat ik even voor dit moment.

De 8086 maakt net als de 8080 en de Z80 gebruik van interrupts. Dit keer zelfs drie soorten. De normale interrupt die bij de 8086 werkt via een interrupt table met sprong-adressen voor de uitvoering van een interrupthandler, of een Interrupt Service Routine, ISR. Geen 8 zoals bij de 8080, maar 256. Daarnaast een non maskable interrupt, die dus nooit genegeerd kan worden, die altijd naar dezelfde locatie springt waar een noodprocedure behoort te staan. En tenslotte weer de Reset, die het systeem laat herstarten.

Naast de hardwarematige uitdaging om een bredere adresbus en een bredere databus in dezelfde 40 pinnen te bouwen, heeft de 8086 nog een lastige kwestie. Alle registers zijn 16 bits (in latere versies van de 80x86 zelfs meer). Maar als je maar 16 bits in een register hebt en die registers adresseren je programma, je stack, je data, hoe kan je dan 20 bits bereiken? Dat kan dus niet. Tenzij je een truc toepast die best handig is als je compatibel wil blijven met het 64K model van de 8080, maar een redelijke nachtmerrie wordt voor wie met data of programmablokken van meer dan 64K wil werken. Die truc heet segmentatie. Om dat te begrijpen, bekijken we alle registers van de 8086:

De algemene registers zijn AX (Accumulator), BX (ook wel het base register), CX (ook wel het count register) en DX (ook wel het data register). Deze registers zijn 16 bits breed, maar kunnen ieder ook benaderd worden in stukken van 8-bits, in de vorm AH en AL, BH en BL, etcetera.

Naast de algemene registers kent de 8086 nog:
SI en DI, ofwel de Source Index en Destination Index, voor array en springbewerkingen.
BP, de Base Pointer die naar de stack verwijst.
SP, de Stack Pointer die naar de top van de stack verwijst.

De combinatie van BP en SP maakt het bijvoorbeeld mogelijk meerdere stacks in te richten.

Dan zijn er natuurlijk nog de IP ofwel Instruction Pointer, waar het volgende commando staat, en FLAGS, de vlaggen zoals Zero, Carry en nog een hele reeks andere. Ze worden aangeduid met een letter voor hun functie, gevolgd door een F, dus ZF, CF etc.

Maar de vreemdste registers zijn:
CS, het Code Segment, het 64K geheugensegment met de code.
DS, het Data Segment, het 64K geheugensegment met data.
SS, het Stack Segment, waar de stack staat.
ES, het Extra Segment, bijvoorbeeld voor het verplaatsen van data tussen segmenten.

De volgende programma-instructie staat dus strikt genomen niet op lokatie IP, maar op lokatie IP binnen segment CS. In de 8086 wereld schrijf je dat als CS:IP. Maar denk nu niet dat hiermee twee 16-bits getallen achter elkaar staan. Dat zou immers 32 bits adresruimte geven en de 8086 heeft maar 20 bits. Nee, CS:IP betekent dat je CS 4 bits naar links schuift, dus vermenigvuldigt met 16, en daar IP bij optelt. Het gevolg is dat je een aantal benaderingen kan kiezen. Als je net als de 8080 in een zuiver 64K model wil werken, dan laat je alle segmentregisters gelijk aan elkaar en negeer je ze verder. Voor de liefhebbers: alle programma's die in MS-DOS eindigen op .COM werken zo. Maar als je graag programma en data gescheiden houdt, of zelfs de stack weer daarvan wil scheiden, dan geef je al die delen hun eigen segment, waarbij ieder segment maximaal 64K groot is. En wil je het helemaal wild maken, dan kan je ook de segmenten gaan veranderen tijdens gebruik, zodat je adresbereik 1M groot wordt.

Maar let op, gevolg van deze manier van adresseren is wel dat het adres (alles hexadecimaal natuurlijk) 1234:0005 en 1224:0105 er wel verschillend uitzien, maar ze zijn identiek. Reken maar uit naar welk fysieke adres beiden verwijzen.

Wie mee wil doen met #klooienmetcomputers kan dat doen via GitHub. Maak een account op github.com en zoek naar Abmvk/kmc. Het account Abmvk volgen kan ook. Lezers zijn vrij te gebruiken wat ze willen en om zelf zaken toe te voegen of aan te passen, vragen te stellen of commentaar te leveren.

Arnout van Kempen di CCO CISA is directeur compliance & risk bij aaff, de fusieorganisatie van Alfa en ABAB. Hij schrijft op persoonlijke titel.

Gerelateerd

reacties

Reageer op dit artikel

Spelregels debat

    Aanmelden nieuwsbrief

    Ontvang elke werkdag (maandag t/m vrijdag) de laatste nieuwsberichten, opinies en artikelen in uw mailbox.

    Bent u NBA-lid? Dan kunt u zich ook aanmelden via uw ledenprofiel op MijnNBA.nl.