Ten komentář o problematičnosti segmentace na 8086 z pohledu pointerové aritmetiky IMHO zapomíná na skutečnost, že podle standardu jazyka C je rozumné fungování pointerové aritmetiky garantováno pouze v rámci prvků jednoho pole (a navíc pointeru bezprostředně za jeho poslední prvek). Jinak řečeno, a priori např. nemůžeme vzít dva náhodné pointery na stejný typ, odečíst je a očekávat smysluplný výsledek.
V praxi to samozřejmě vždycky nějak funguje a vývojáři si na to zvykli natolik, že na toto omezení dávno zapomněli, pokud o něm tedy vůbec kdy věděli. IMHO to ale znamená, že ten problém zmiňovaný v článku nijak zásadní není. Stačí, aby pole "žilo" buď v rámci jednoho segmentu nebo nějaké posloupnosti navazujících segmentů, a pointer, který dostaneme aplikací operátoru & na prvek pole, byl vždy reprezentován hodnotou z tohoto segmentu, a při korektním používání žádný problém nevznikne.
Myslíš problém pointerové aritmetiky jako takové nebo porovnání ukazatelů? To první je spíš past na vývojáře, který si musí hlídat, co se mu vlastně vrátí (buď rozdíl offsetů, a když má štěstí, tak rozdíl celých adres). To druhé - tyjo ono to v BC vždycky fungovalo tak napůl a ještě to záleželo na volbě Fast huge pointers (to v podstatě vypnulo normalizaci ukazatelů, ale i když je zapnutá, tak nikde není jistota, že se někde neobjeví nenormalizovaný ukazatel).
V podstatě, pokud se dělalo se strukturami pod 64kB, tak to bylo v pohodě, jinak začaly problémy - typicky se nesahalo na volby překladače, aby to nějak drželo dohromady :-)
PS: byla jiná doba, žádné velké automatické testování se nekonalo; asi na to ani nebyla infrastruktura
Myslel jsem pointerovou aritmetiku obecně. K porovnávání se tam píše tohle:
6.5.9.6 Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
přičemž k té poslední části je poznámka pod čarou:
Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior.
Celkově mi z toho vychází, že pokud nebudu v programu spoléhat na nedefinované chování nebo si pointery "cucat z prstu", neměla by ta nejednoznačná reprezentace vést k neočekávaným nebo nelogickým výsledkům ani při porovnávání.
Dnes je samozřejmě všechno jednodušší, když máme 64-bitové procesory a na segmenty se můžeme vykašlat.
no a praxe je taková, že například pointer ukazuje na začátek VideoRAM. Co teď s tím? Objekt to žádný není, prostě mám pointer typu (řekněme) unsigned char*. Pointerovou aritmetiku v tomto případě naprosto chceme, možnost přičítat offsety taky a mělo by to fungovat. V rámci offsetů to funguje vždy, mimo ně IMHO jen v Huge režimu u huge ukazatelů - jinak ne jestli si pamatuju.
Nemyslím, že by někdo i dneska odčítal náhodné pointery - jaký by to mělo význam?
Ten problém se segmentací je, že můžu mít pole větší než 64 kB a pak posun v rámci pole, stejně jako spočítání offset prvku, vyžaduje 32-bitovou operaci a výsledek (a v případě pointeru změnu segment i offset). Nevím, jakého typu je off_t (pokud vůbec byl v tehdejším standardu).
Tedy jenom pro Huge memory model - musel jsem si ty názvy připomenout. Klobouk dolů - psát o tomhle musel být masochismus :-D .
Podle me provnavat 2 pointery a resit problem ze ukazatel na stejne adresove misto v pameti muze byt reprezentovan vice kombinacemi nedava moc smysl.
Pokud je to vyssi jazyk tak te to ma odstinit od toho ze ty hodnoty mohou byt ruzne, protoze se prekryvaji a videt to v C jenom jako vyslednou 20 bitovou adresu.
Pokud si to placas v assembleru tak zase existuje jen jedno "normalizovane" reseni kdy mas segment na te hodnote, aby ofset mohl byt nulovy na zacatku.
Pokud do jednoho 64k segmentu davas vice mensich poli a delas si z toho datovy segment, tak si taky najdes jednu hodnotu, kde prvni pole zacina a kterou chapes jako "normalizovanou". Urcite se ti nechce porad cachrovat se segmenty. A pokud jo, tak je nahodne neporovnavas.
Pokud ti pak vystane potreba resit zda to ukazuje na stejne misto v ramci pole, tak ti staci porovnat jen offset.
Kdyz je to vic nez 64k tak si to nejak resis sam. Mas vic moznosti. Muzes si vybrat co se ti hodi. Pokud mas velke pole 16 bajtovych polozek, tak muzes mit zase nulovy offset a porovnavat jen segmenty.
Nemyslim si ze by pri navrhu procesoru tohle videli jako velky nedostatek. Skoda jen ze nepreskocili prvni iteraci a rovnou nezvolili zarovnani 256 bajtove, ze by prvni limit nebyl mega ale rovnou tech 16 mega.
PS: Priznam se ze jsem v tom dost plaval (a ted si to zase nepamatuji), protoze jak nebyl dostatek informaci, tak bylo pro me tezke poznat ktery segmentovy registr instrukce vlastne pouziva... Mam pocit ze to slo zmenit prefixem, ale to byla instrukce o bajt delsi. Takze kdyz jsem psat 256 bajtove intro do souteze, misto abych se ucil na zkousku z fotogrammetrie, tak to byl dost horor i bez toho samomodifikujiciho se kodu pro Bresenhamuv algoritmus kresleni cary v SVGA...
3. 6. 2025, 22:28 editováno autorem komentáře
Kdyz se koukam na tu tabulku:
1 Tiny krátké 64kB pro program i data, všechny čtyři segmentové registry jsou totožné (a tedy limit 64kB se vztahuje na celek) 2 Small krátké 64kB programový kód, 64kB pro data 3 Medium dlouhé pro program, krátké pro data 1MB programový kód, 64kB pro data 4 Compact krátké pro program, dlouhé pro data 64kB programový kód, 1MB pro data 5 Large dlouhé 1MB programový kód, 1MB pro data 6 Huge dlouhé 1MB pro programový kód, 1MB pro data
Tak pokud budu ignorovat podvarianty s delkou kodu tak C resi jen 3 pripady.
1) Mas jen 64 kb na vsechny data, takze segment se nemeni a C te od nej odstini a mas 16 bitovy pointer (jen offset).
2) Mas 1 mb na data, ale alokovat muzes najednou max. 64kb na pole. To same co predchozi vidis zas jen 16 bitovy pointer (jen offset). Jen nesmis porovnavat ruzne pole mezi sebou, protoze maji ruzny segment.
3) C ti povoli vetsi jak 64 kb pole. Pak se to ma idealne chovat jako 20 bitovy pointer i kdyz v 32 bitovem cisle. Spravne by ten popisek u Large mel byt celkove 1MB pro data max 64kb velka.
Zajimalo by me zda jde v tom druhem rezimu udelat vetsi pole diky tomu ze C umi delat vicerozmerna pole vice zpusoby a pokud alokujes nejaky rozmer zvlast a vyssi je jen pole pointeru... No, v te dobe jsem stejne neumel a delal v BP, protoze mel lepsi vysledny kod. BC produkoval vetsi binarky. Pridaval na konec nazvy fci a jeste neumel automaticky vynechat z kodu fce co se nepouzili. Volajici navic uklizel zasobnik po kazdem volani. Hruza, clovek se snazil prejit na C a pak prislo jen zklamani. :)
Aha tak aby mohlo v LARGE modelu fungovat pole pointeru na az 64kb dalsi pole tak ten pointer musi byt fyzicky 32 bitovy, takze te C nemuze odstinit a tvrdit ti ze je to 16 bitove, protoze segment nesmis prekrocit/zmenit.
On je vlastne pointer jakoby nezavisly na jaky objekt ukazuje. Jakoby anonymni a pokud skryjes ze kazdy objekt ma vlastni segment, tak by C ani nevedelo k jakemu teda segmentu pointer odkazuje... Musel by si to odvodit z kodu k cemu to bylo inicializovany. Takze uz by ten pointer nebyl jakoby nezavisly. Komplikace.
Nenapada me u kodu jaky mit jiny pointer nez na fci.
Model Kód Funkční pointer Data Datový pointer Max data TINY near 16 bit (near) near 16 bit (near) 64 KB celkem (kód + data) SMALL near 16 bit (near) near 16 bit (near) 64 KB COMPACT far 32 bit (far) near 16 bit (near) 64 KB MEDIUM near 16 bit (near) far 32 bit (far) >64 KB LARGE far 32 bit (far) far 32 bit (far) >64 KB (objekty max 64 KB) HUGE far 32 bit (far) far 32 bit (huge) >64 KB, i pole přes 64 KB
Tohle je asi komplexnejsi tabulka jak to vypadalo.
"Pokud je to vyssi jazyk tak te to ma odstinit od toho ze ty hodnoty mohou byt ruzne, protoze se prekryvaji a videt to v C jenom jako vyslednou 20 bitovou adresu."
právěže to vidíš jako segment:offset i přímo v tom céčku. V podstatě nikdy z toho nikdo výslednou 20bitovou adresu nepočítá (pokud to nenapíšeš explicitně sám), pořád to vnitřně je jako pár dvou 16bitových hodnot. Jsou na to ta tři makra zmíněná v článku a nějaký funkce okolo.
cely ten problem se vlastne resi jen kvuli tomu, ze bazove adresy (a bazove registry) jsou 16bitove a ne 32bitove, coz by vsechny problemy vyresilo na dlouhou dobu dopredu. Nebo jeste jinak - kdyby si IBM zvolila Motorolu 68000, tak by se to neresilo, ale IBM melo svoje pravidla (dva dodavatele) a to Motorola nesplnovala.
Tých faktorov prečo nie 68k tam bolo viacero, okrem second sources aj nedostupnosť variantu s 8b dátovou zbernicou (ktorú kvôli nákladom preferovali) dostatočne včas - 68008 bol uvedený rok po IBM 5150; nižšia hustota kódu; horšia nadväznosť na CP/M ekosystém a 8080 tooling; vyššia cena. Plus je otázka, či by to bolo vo výsledku podobne úspešné, pokojne by sa mohlo stať, že by nakoniec prerazila nejaká konkurenčná platforma s 8086/88 práve kvôli tej jednoduchej migrácii existujúceho CP/M kódu.
A proto PC zvítězilo na celé čáře, přes všechny potíže. 386, chráněný režim a V86 režim nakonec splinily požadavky na pokročilejší operační systémy a zpětnou kompatibilitu.
Nebyl bych tak přísný, 80. léta byla bouřlivá dekáda a vidět do budoucnosti bylo tehdy nanejvýš obtížné.
5. 6. 2025, 09:33 editováno autorem komentáře
spis uspelo proto, ze ty PC skladala kazda garazovka, vetsinou s "vypujcenym" BIOSem (jedina vec, kterou mela IBM licensovanou) - to by dneska uz v zadnem pripade neproslo. Nevyhrala technologie, ale cena, zatimco konkurenti si to rozdavali mezi sebou. Apple taky chvili zkousel jit cestou licencovani vyroby, ale potom z toho seslo (a ty klony nebyly cenove marny).
Nevyhrala technologie, ale cena,
Takhle ale trh do značné míry funguje. Můžete vymyslet úžasnou super sofistikovanou technologii, ale pokud ji nebudete schopen vyrábět - a hlavně prodávat - za cenu, která osloví dostatečný počet zákazníků, ekonomický úspěch z toho nebude.
Koneckonců to bylo vidět už u těch domácích osmibitových počítačů. Bylo ZX Spectrum technologicky nejlepší? Ani omylem, byl to šílený bastl a některá designová rozhodnutí byla dost šílená. Ale právě díky tomu se jim podařilo dostat na cenu, která oslovila dostatečný počet zákazníků, aby síťový efekt dokonal zbytek. S PC to bylo do určité miry podobné.
A neplatí to jen pro počítače. Byl to Fiat, kdo koupil Alfu, Maserati nebo Ferrari, ne naopak. Nebo se podívejte na seznam značek patřících pod Volkswagen Group nebo Swatch Group, spousta z nich je daleko uznávanější odborníky i laiky, ale ekonomická realita je prostě jiná.