Segment (datorterm)

Ett segment är en beteckning på en särskild del av en dators arbetsminne. Oftast associeras segment med minnesmodellen som används av Intel 8086-processorn och dess efterföljare.

Segmenterade adresser hos Intelprocessorer

Intel hade som målsättning att det skulle vara lätt att överföra program skrivna för 8080 och 8085-processorerna till den nya generationen 8086-processorer; därför har många av de 16-bitars registerparen i 8086-processorn direkta motsvarigheter i 8080-familjens registerpar. Samtidigt började de 64 KiB, som dessa 16 bitar begränsade adressrymden till, kännas trånga; en större adressrymd behövdes för nästa generation. För att samtidigt kunna nå dessa båda specifikationer, utvecklade Intel segmenterad adressering.

Tidigare hade det för en specifik minnescell X behövts endast ett register som innehöll själva adressen. Nu behövdes det två 16-bitars register: ett segmentregister och ett offsetregister. Segmentregistret anger basadressen för ett 64 KiB stort "fönster" eller region i minnet (segmentet). Ett segment kan börja varje 16 byte i minnet (i hexadecimala talsystemet: 0x00000, 0x00010, osv). Offsetregistret anger då X adress mätt från början av segmentet (dess offset).  Den slutliga fysiska adressen erhålls genom att multiplicera segmentregistrets värde med 16 (hexadecimalt 0x10) och lägga till offseten.

Exempel
Låt oss anta att minnescellen X befinner sig på den 0x12345:e adressen i minnet (notera det hexadecimala talsystemet). En möjlig segmentadress är då segmentet som börjar på adress 0x1000 och en offset på 0x2345, eftersom 0x1000 * 0x10 + 0x2345 = 0x12345. Denna adress kan då skrivas 0x1000:0x2345. Dessvärre är denna segmenterade adress på inget sätt unik: X adress kan också uttryckas 0x1200:0x0345 eller 0x1234:0x0005.

Hos de första x86-modellerna fanns det fyra segmentregister att tillgå: CS, DS, ES och SS. CS (code segment) användes tillsammans med IP (instruction pointer) för att ange programpekaren; DS och ES (data resp extra segment) användes för allmänna minnesadresser; och SS (stack segment) användes tillsammans med SP-registret för att ange stackpekaren. Senare modeller introducerade ytterligare två segmentregister, FS och GS. Eftersom segmentregistren var begränsade till 16 bitar kunde de maximalt innehålla värdet 0xFFFF. Tillsammans med ett offsetvärde på 0xFFFF var den högsta adresses processorn kunde generera 0xFFFF * 0x10 + 0xFFFF = 0x10FFEF. Detta motsvarar en adressrymd på 1.114.096 byte, eller drygt 1 MiB.

"Protected mode"-segmentering

När datorminnen blev större än 1 MiB räckte inte denna typ av segmenterade adresser till. Intel lanserade då sin nya 80286-processor, som införde ett nytt arbetsläge, s.k. protected mode. Bland andra egenskaper hos protected mode var att segmentadresserna beräknades på ett annorlunda sätt. Istället för att direkt använda segmentregistret för att beräkna adressen som tidigare, användes det istället som index i en tabell i minnet, antingen LDT (local descriptor table) eller GDT (global descriptor table). I denna tabell fanns segmentets basadress lagrad. Som tidigare lades sedan offseten till basadressen för att få den slutliga fysiska adressen. På detta vis utökades processorns adressrymd till 16 MiB.

Kritik
Segmenteringsmodellen har kritiserats hårt sedan den introducerades. Den komplicerade programmeringen av x86-familjens processorer oerhört, jämfört med andra processorarkitekturer med "platta" adressrymder. Till exempel blev de speciella nyckelorden "__far" och "__near" framtagna för C-kompilatorer för x86-familjen för att kunna hantera segmenterade adresser. Detta gav upphov till kompatabilitetsproblem när program skulle överföras från andra operativsystem som Unix eller MacOS. Segmentadressering lämnade djupa spår i utformningen av MS-DOS och Windows, spår som går att skönja än idag. Allmänt betraktade programmerare segmentering som ett gissel. När sedan Intel 80386-processorn introducerades, fanns nu möjlighet för x86-programmerare att äntligen kunna använda "platta" 32-bitars adresser utan segmentering.

Datorer
Programmering