U.K. flag click here for English version

- = Programování = -

      No tak to vezmeme od začátku: od QBASICu (se krerým jsem se setkal někdy koncem 1995) jsem se přes Pascal dostal až k C. K tomu jsem ještě pokusoval s různými assemblery (x86, Z80, uPC 51, HC11, TMS320Cxx...). Pascal byl po dlouhou dobu mým nejoblíbenějším jazykem. Ovšem jeho překladač Borland Pascal 7.0 je dnes již pěkný stařeček, který na nové CPU už nestačí. Existuje sice 32-bitový překladač GNU FreePascal, který zvládá pmode, ale... Říkal jsem si, že když už začít s něčím novým, tak s C. Zájemce o FreePascal odkážu na web INT21h, kde se mu pár autorů věnuje.
      C je v současnosti asi nejrozšířenější jazyk vůbec a tak na různých platformách (od superpočítačů po mikrokontroléry) máte hned několik překladačů. Tím nejvhodnějším pro DOS je DJGPP/GCC. O tom, že to není žádný salát by vás měl přesvědčit např. Quake od ID Software nebo nový engine pro Hexen II.
      Přechod z Pascalu na C není nijak jednoduchý a já moc děkuji Redoxovi/MovSD, že mi poskytl mnohé cenné rady ohledně DJGPP a podpořil mě tak na té strastiplné cestě ;-). Taky můžu vřele doporučit knížku Pavel Herout: Učebnice jazyka C z nakladatelství Kopp, kde jsou často uváděny analogie v Pascalu. Ovšem na Pascal jsem samozřejmě nezapomněl. Pokud je potřeba udělat rychle nějakou malou low-level utilitu, je Pascal asi tím nejlepším. EDIT: Pascal už jsem zapomněl, jak jsem zjistil a nijak mi to nechybí ;) BTW zde je zajímavý článek o pohledu na genetiku a DNA očima kodéra.

- = DJGPP = -

+ DJGPP je GNU software, to znamená že si ho stáhnete zadarmo i se zdrojáky.
+ GCC je stále vyvíjený překladač a jeho aktuální verze je 4.7.1 (vyšla před nedávnem).
+ Rozsáhlé možnosti optimalizace kódu a podpora instrukčních sad moderních CPU.
+ Obsahuje vlastní kvalitní DPMI server, velký jen 20 kB proti 260 kB extenderu DOS4/GW, který používá Watcom C.
+ Protože pracujete v chráněném režimu (pmode) je všechna paměť PC vaše a ještě k tomu až 2048 MB swapfile. To jde, proti 640 kB Pascalu ne?
+ Obsahuje řadu UNIX/Linuxových funkcí, což pomůže při portaci software.
+ Mnoho dalších plus, o kterých ještě třeba nevím ;-)
- Trochu krkolomný přístup k hardwaru a BIOSu a prostě všemu realmodovému, ale to se dá zvládnout. V DJGPP jde udělat i rezident!

Pokud na vašem PC neběží nějaký DPMI server, jako třeba QDPMI, HDPMI nebo snad W9X, tak tady je nezbytné CWSDPMI7.ZIP [71 kB] nyní ve verzi 7, společné pro všechny programy z DJGPP.
Novinkou od verze 5 je CWSDSTUB.EXE, který umožní běh programu bez externího DPMI serveru. Stačí program zkonvertovat do formátu COFF (exe2coff mypgm.exe), tím se odřízne standardní stub, a připojit k němu na začátek cwsdstub.exe (COPY+APPEND v DOS Navigatoru nebo COPY /B cwsdstub.exe + mypgm mypgm.exe).
      U GCC od verze 3 se objevil problém s casesensitivitou příkazového řádku. Pokud GCC předáváte názvy souborů velkými písmeny, může se stát, že začne vypisovat nesmyslné chyby ve zdrojovém kódu (jak jsem zjistil později, soubory s velkými písmeny se zpracovávají jako C++ nehledě na to, že mají příponu pouze .C). Napsal jsem proto malý prográmek GCC Launcher, kterým se nahradí původní GCC.EXE, jenž se přejmenuje na GC_.EXE. Launcher lowercasuje názvy souborů a takto upravené argumenty předává původnímu GCC, tedy GC_.EXE.
      Pozor na UPX 3.x a GCC 4.x.x! Některé novější verze DJGPP GCC 4.x.x balíčků byly komprimovány UPX 3.01 s parametrem --brute, který používá nově LZMA kompresi, jenž sice produkuje o něco menší soubory ale dekomprese trvá oproti NRV mnohanásobně déle. Proto dpoporučuji .EXE soubory překladače rozbalit pomocí UPX -d *.EXE a znovu zabalit metodou NRV UPX --best *.EXE. V mojem případě se tak doba překladu zkrátila asi na polovinu (u libjpeg v0.6 z 41s na 21s).
      Pokud máte problém s tím, že překladač při kompilaci vychrlí spoustu chybových hlášek, které nelze zastavit na konci obrazovky ani přesměrovat do souboru, zkuste tento malý rezidentní prográmek v assembleru: STDERROR.ASM. Ten jednoduše přesměruje stream STDERR, který jde v DOSu výlučně na obrazovku na stream STDOUT, který již lze klasicky filtrovat (např. |more, |grep...) nebo přesměrovat do souboru ( >error.log). Další možnost je použít inteligentnější DOSový shell, např. 4DOS nebo BASH, které umí se STDERR lépe pracovat.
      DJGPP si můžete stáhnout z oficiálního FTP: ftp.delorie.com/pub/djgpp a zde najdete aktualizované buildy GCC od Andrise Pavenise. Také doporučuji aktualizovat systémový balíček DJDEV 2.04 (LibC, start-up kódy a tak) od Ozkana Sezera, který ho používá při kompilaci herního engine Hexen II: Hammer of Thyrion. Oficiální balíček je už totiž asi 8 let starý a má určité problémy s novějšími verzemi GCC. Dále se vám může hodit komplexní grafická a zvuková knihovna Allegro http://www.talula.demon.co.uk/allegro (je potřeba stáhnout starší verzi, v současné už podpora DJGPP bohužel chybí). Pro portování grafických linuxových programů přijdou vhod knihovny Nano-X, Microwindows, NXlib a FLTK pomocí nichž byl nedávno portován pro DOS webový prohlížeč Dillo, více zde. Diskusní fórum o DJGPP na Google Groups: http://groups.google.com/group/comp.os.msdos.djgpp.
      Zde je pár prográmků, které jsem v DJGPP napsal a můžete je používat jako freeware. Pokud něco z toho shledáte užitečné nebo objevíte nějaké chyby, dejte vědět prosím mejlem: rayer^seznam*cz

ABITVC.EXE ver. 1.0 [48 kB] - Abit BX133-Raid Vcore controll utility je program pro nastavení Vcore bez limitů, tedy v plném rozsahu 1,30 - 3,50 V (zkoušel jsem pouze do 2,00 V). Program mění hodnotu uloženou v CMOS, po nastavení je třeba provést tvrdý reset, aby změna nabyla účinnosti. Více zde.

AWDLS.EXE ver. 1.7 [50 kB] - vypíše informace o komprimovaných modulech v daném Award BIOS image souboru. V podstatě totéž co CBROM /d ale navíc ukáže dekompresní adresy/module IDs a offsety, kde se moduly v image nachazi.
      29.3.2008 Do verze 1.2 jsem přidal možnost vykopírovat moduly z image do samostatných souborů, které pak lze snadno rozbalit např. programem LHA 2.55. Také jsem přidal podporu rozeznávání modulů s hlavičkou -lh0- a modulu NCPUCODE, které se objevily v nových Award BIOSech.
      11.8.2008 Ve verzi 1.4 jsem opravil počítání kontrolního součtu hlavičky LHA modulů (špatný součet se indikuje znakem '!' za jménem modulu) a chybu při kopírování modulů, které mají nenulovou velikost rozšířené hlavičky (např. MEMINIT.BIN).
      9.9.2009 Ve verzi 1.6 jsem opravil nekorektní zpracování modulu NCPUCODE.BIN, nyní ho lze v plné velikosti vyextrahovat.

AWPKICK.EXE ver. 2.0 [53 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - vygeneruje heslo pro Award BIOS 4.51PG do SETUPu. Z původního hesla se v CMOS uchovávají pouze dva bajty, proto ho nelze zjistit, ale jen nahradit sekvencí znaků se stejným kontrolním součtem. Testováno na mojí desce a na školních počítačích P166/233iTX.

BIOS Extract 7.12.2010 [247 kB] (DOS/Win9x/NT/2k/XP/Vista/7/Linux + C zdrojáky) - toto je DOSový a WIN32 port linuxové utility BIOS Extract, která slouží pro dekompresi AMI/Award/Phoenix BIOS image souboru na jednotlivé moduly (vše v jednom kroku). Při portování jsem se musel vypořádat s chybějící funkcí mmap(), která je použita pro práci se soubory. Napsal jsem jednoúčelovou náhradu, jenž si alokuje buffer v paměti, kam nakopíruje požadovanou část souboru. Při volání munmap() se pak buffer zapíše do souboru a uzavře.

BMP2EPA.EXE ver. 1.0a [50 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - můj vlastní konvertor formátu *.BMP do *.EPA 2.0. Už mě štvaly různé pitomé sharewary, omezené rozlišením, které mi navíc vždy zdestrojili moji pečlivě připravenou paletu a taxem sám hacknul formát *.EPA. Tento program paletu nemění, takže je třeba se postarat předem o to, aby určité indexy měly správnou barvu (0 - pozadí, 7 - šedý text, 9 - modrý panáček, 15 - bílý text - nelze změnit) zde je paleta pro Paint Shop Pro.

BMP2GRFX.EXE ver. 1.0 [68 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - můj vlastní konvertor formátu *.BMP do *.EPA intel GRFX pro základní desky Asus s AMI BIOSem, které používají tento nový formát loga. Na Asus P5LD2 je velikost obrázku omezena na 640x98/4bit. Tento program nemění paletu a je třeba mít na paměti, že BIOS nahradí určité indexy pro vlastní použití (0 - pozadí, 7 - šedý text, 15 - bílý text).

CODEUP.EXE ver. 1.10 [5 kB] (real mode Borland Pascal executable) Malá utilitka pro nahrání microcode update ze souboru do intel CPU za běhu. Nahraný mikrokód zůstává v procesoru jen do vypnutí nebo restartu PC. Soubor s microcode update pro dané CPUID lze vyextrahovat z image BIOSu (stáhnout od výrobce desky) nebo ze souboru UPDATE.SYS z Windows XP.

COVOXMP3 ver. 1.1 [103 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - přehrávač MP3 s výstupem na D/A převodník Covox na paralelní port. Knihovnu na dekódování MP3 jsem převzal ze Scitech SNAP SDK 3.1. Byla napsaná 100% ANSI C, takže se mi ji povedlo v DJGPP bez problémů přeložit. K tomu jsem dopsal hlavní program MP3 přehrávače, který si na přerušení časovače nainstaluje vlastní p-mode obsluhu přerušení a ta pak posílá přepočtené vzorky na paralelní port. Když je přehrán celý MP3 rámec (1/2 bufferu), nastaví obsluha flag pro hlavní smyčku, která načte a dekóduje další rámec. Mezitím se přehrává druhá polovina bufferu s už dekódovanými daty, takže by se to nemělo nikde zasekávat. Na některých PC jsem pozoroval, že systém nějak nestíhá tak rychlý sled přerušení časovače (např. 44100 Hz) a zvuk se přehrával pomaleji než by měl. Proto jsem přidal možnost vynechání daného počtu vzorků spolu se snížením frekvence časovače a při 22050 Hz se to už přehrávalo OK. Dalším parametrem lze nastavit adresu portu, kam se mají vzorky posílat. Ovládání je jednoduché, šipkami doleva/doprava se přetáčí, nahoru a dolů se mění hlasitost v 8-mi krocích a mezerník je pauza. Program umí načítat i playlist soubory .M3U a zobrazuje ID3 tagy.

CPUID.ZIP ver. 2.16 [105 kB] (DOS/Win9x/NT/2k/XP/Vista/7/Linux) - tento prográmek vypíše info o vašem procesoru (od 386 výše). Nyní umí detekovat i skutečnou a nominální frekvenci jádra, FSB a násobič (pro plnou funkčnost je třeba ho spustit pod DOSem - čtení MSR registrů).
      20.3.2005 byla rozšířena CPU databáze o nová jména procesorů intel a AMD a přidán další řádek CPU flagů nových procesorů řady Pentium 4 (SSE3, HT...).
      12.3.2007 Nová verze 2.x byla přepsána tak, aby byla na úrovni zdrojového kódu kompatabilní s překladači GCC pro OS DOS, Windows a Linux. Nejprve jsem tedy musel vytvořit knihovnu pro low-level přístup k hardware, která implementuje dané funkce individuálně pro každý OS. V DOSu nebyl žádný problém, přistupuje se přímo. Pod Linuxem se využívá funkce iopl(3), která vyžaduje rootovská práva a zařízení /dev/cpu/?/msr. Pro Windows NT a vyšší jsem musel napsat Kernel Mode Driver a DLL knihovnu, která obsahuje driver a podle potřeby ho nainstaluje/odinstaluje. Inspiroval jsem se projektem ioperm.sys 0.4 Marcela Telky pro CygWin (po menších úpravách lze přeložit i MinGW32), moje verze driveru 0.5 je zpětně kompatabilní. Pro Windows XP by driver nebyl nezbytně nutný, neboť lze využít hack na funkci ZwSystemDebugControl z NTDLL.DLL, ale to zas nefunguje ve starších Windows a nemusí to být zaručeno ani po aplikaci nejnovějších záplat. Psaní KMD mi docela stačilo, takže už jsem neměl náladu psát ještě další VXD driver pro Windows 9x. Ty jsou naštěstí dostatečně děravé, takže mi dovolí nainstalovat si vlastní CallGate, přes kterou volám potřebné instrukce RDMSR/WRMSR s oprávněním ring 0. No alespoň jsem se naučil trošku jak funguje chráněný mód 386.
      V samotném CPUID programu pak přibyla podpora nových featur procesorů intel, vylepšil jsem detekci velikosti cache, násobiče a FSB a přibyla podpora čtení teploty jader ze senzorů DTS (zde jsou zatím určité nejasnosti, neboť intel mlží s dokumentací a tak na nových procesorech může být údaj chybný, např. CoreTemp 0.94 ukazuje o 15°C nižší teplotu na Core 2 Duo E4300, CPUID by měl ukazovat správně). Dále pomocí parametrů z příkazové řádky můžete přečíst nebo zapsat libovolný MSR registr (použij parametr /h pro help).
      26.3.2007 Verze 2.03 opravuje kritickou chybu verze 2.02, kde na starších CPU, které nepodporovaly CPUID extended level info, mohlo dojít k zacyklení programu vlivem špatné detekce CPUID extended levels.
      12.5.2007 Do verze 2.06 jsem přidal detekci násobiče pro další CPU od AMD, Cyrix, VIA, IDT a opravil detekci násobiče na P4 a Core. Za potřebné informace a feedback děkuji Janovi Steunebrinkovi.
      28.8.2007 Od verze 2.10 (DJGPP) opravena chybná detekce Windows (VDM), která se projevovala např. pod HDPMI32.
      16.9.2007 Od verze 2.11 (DJGPP) kompletně přepracován přístup k MSR do ring0, nyní DOSová verze funguje i ve virtuálním módu (např. EMM386) a Win9x.
      16.4.2011 Verze 2.14 opravuje nefunkční zápis do MSR přes parametr wrmsr (chyba se pravděpodobně táhne od verze 2.11). Dále byly aktualizovány funkce pro detekci násobiče, FSB, cache, počtu jader, čtení DTS, výpis flagů vybavení, APIC ID mask a databáze jmen procesorů. Program jsem ladil na intel Core i5-750, Core 2 Duo E8400 a Pentium 4 HT.
      26.12.2012 Verze 2.15 obsahuje celou řadu vylepšení: podpora neceločíselného násobiče u 45nm procesorů intel Core 2 Duo a detekce turbo násobiče u procesorů intel core i3/5/7, nový výpočet velikosti cache u procesorů intel core i3/5/7, přidán výpis aktuální, min. a max. napětí Vcore (jen pro Core 2 Duo, testováno pouze na 45nm E8500) a byla rozšířena databáze jmen procesorů. Dále jsem rozšířil příkaz wrmsr předávaný z příkazové řádky o další 2 nepovinné parametry bits a shift, pomocí kterých lze pohodlně změnit jen část MSR bez ovlivnění ostatních bitů. Např. pro zapnutí EIST na Core 2 Duo zadej cpuid wrmsr:1A0:1:1:16 - do MSR 1A0h zapíše hodnotu 1, která čítá 1 bit, na pozici bitu 16.
      19.1.2013 Do verze 2.16 jsem přidal nový přepínač /s - safe mode, kterým lze explicitně potlačit přístup k MSR a TSC.

DEMO2.ZIP [55 kB] Pro zajímavost jsem zde uploadnul i jedno 64kB demíčko stvořené kdysi v Borland Pascalu. Bylo dokonce promítnuto na malé lokální demopárty Subway p2k, results roku 1999 v Praze. Jeho náplní je hlavně práce s jednoduchými 3D objekty v prostoru ve VGA módu 13h. Tehdá jsem ho ladil na pentiu 166@200 MHz a vykašlal se na nějakou synchronizaci, takže vám pofrčí asi drobet rychleji :) No dobrá, přeložil jsem ještě jednu verzi s narychlo přidaným Vsyncem.

EDDINFO.EXE ver. 1.1 [10 kB] (real mode Borland C++ executable) Pro otestování schopností rozšířených služeb BIOSu INT 13h pevného disku (BIOS Enhanced Disk Drive services) jsem napsal tento malý prográmek, který zjistí přítomnost a verzi EDD, základní parametry disku a řadiče. EDD definuje nové funkce pro čtení a zápis sektorů, kde umožňuje používat až 64-bitové adresování a tím pádem přístup k obrovské kapacitě. Služby jsou nezávislé na typu a rozhraní paměťového zařízení, ať už je to ATA, SATA, SCSI nebo USB...

EXEINFO.EXE ver. 1.2 [12 kB] - vypíše pár užitečných informací z hlavičky EXE souboru, rozpozná jedná-li se o stub a případně vypíše typ binárního image (LE/NE/PE/COFF/Pharlap...).
      1.11.2007 od verze 1.1 detekuje u některých typů image (např. DJGPP COFF, LE) kompresi UPX a vypíše jeho verzi.
      12.11.2007 od verze 1.2 rozezná typ image Rational DOS/16M.

FFC.EXE ver. 2.1 [53 kB] - Fast File Comparator, program na binární porovnání dvou (velkých) souborů. Využívá hodně RAM pro cachování. Schválně si jeho rychlost porovnejte se standardním FC v DOSu. Nyní od verze 2.1 podporuje i wildcards a rekurzivní procházení podadresářů.

FOTODATE.EXE ver. 2.1 [52 kB] - jednoduchá utilitka pro nastavení správného datumu a času u JPEG fotografií podle odpovídajících hodnot v EXIFu.

GDTDUMP.EXE ver. 1.1 [35 kB] - okolnosti mě donutily trochu proniknout do principů fungování chráněného režimu 386 a tak jsem si cvičně napsal utilitku na zobrazení obsahu důležitých struktur GDT, IDT a LDT. Vzhledem k různému stupni ochrany v různých OS program funguje pouze v DOSu a Windows 9x. Pod WinNT/2k/XP se mi sice podaří alokovat LDT deskriptor a nastavit ho aby ukazoval na GDT s PL3, ale při jakémkoli přístupu mě OS sestřelí.

GPSMON.ZIP ver. 1.1 & 1.2 [56 kB] je malý prográmek, který jsem si napsal za účelem monitorování příchozích NMEA dat z GPS přijímače připojeného přes sériový adaptér k atárku. Oproti obyčejnému terminálu jsou GPS data zobrazena v přehledné podobě a neutíkají před očima. Podporovány jsou tyto NMEA-183 řetězce: GGA, GGL, GSA, RMC, GSV, VTG a ZDA. Program funguje na Atari Portfoliu a na PC v DOSu. Parametry na příkazové řádce lze nastavit číslo sériového portu a bitovou rychlost. Funkci jsem úspěšně otestoval s GPS modulem Fastrax uPatch100C.
      1.9.2007 Přidal jsem verzi 1.1 kompilovanou v DJGPP, která by měla fungovat pod DOSem i Windows. Klávesou D lze přepínat zobrazení zeměpisné šířky a délky DD.dddddd / DD.MM.SS.dd a klávesami + / - lze posouvat lokální časovou zónu. Ukončení klasicky přes ESC.
      13.9.2011 verze 1.1 & 1.2 opravuje chybu parseru, která se projevuje, když zeměpisná šířka nebo délka má místo úvodní nuly mezeru, tak program načte vždy 3 číslice pro stupně a tudíž může přečíst i jednu nebo dvě číslice z následujících minut (pokud byly na začátku 1 nebo 2 mezery). Takže např. místo 14°22' se načetlo 142°02. Tato chyba se týkala i programu NMEA2PLT.

LAPLACE.EXE ver. 1.01 [50 kB] (nepotřebuje CWSDPMI, má CWSDSTUB).
Inspirován předmětem Teorie elektromagnetického pole jsem napsal tento malý prográmek na grafické řešení Laplaceovy rovnice iterační metodou. V první fázi pomocí myši a palety definujete elektrody a jejich potenciál. Defaultní potenciál v okně lze změnit z příkazové řádky /h. Po spuštění se rozjede výpočet, který by měl po nějaké době zkonvergovat ke stabilnímu řešení rozložení potenciálu. Klepnutím na "E" lze zapnout/vypnout zobrazení vektorů intenzity, které však nemusí být úplně korektní.

LIDECR.EXE ver. 1.1 [51 kB] - utilita na dekódování zakryptovaných souborů s příponou .liCrypt, které kóduje neznámý červ/trojan. Moje PC bylo tímto šmejdem napadeno 29.9.2009 ráno (ze staženého freewarového programu Free RapidShare Downloader 1.3), pozná se podle běžícího procesu regdtopt.exe a výrazné diskové aktivity a CPU zátěže. Proces může běžet ve více instancích. Prochází disk a otvírá všechny možné soubory, kterým zakóduje prvních 10 Bytů pomocí statického XOR klíče (naštěstí nejde o destruktivní změnu). Antivir nic nepoznal. Červa jsem dále testoval ve Virtual PC 2007 a zdá se, že klíč nemění. Není ale vyloučeno, že po internetu koluje více variant s jiným klíčem. V mojem případě to byl řetězec 5C, 34, 1B, 69, DC, AD, 52, 15, 5D, 40. Proto je důležité napřed program otestovat např. na nějakém textovém souboru, kde víme, co mělo na začátku být a pak to teprv pustit na další soubory. Program jsem psal narychlo, takže neumí rekurzivní procházení adresářů, ale jen * wildcardy. Toto omezení lze obejít vytvořením dávkového souboru, který vytvoříme z výpisu souborů na disku např. příkazem dir C:\* /b /on /s >list.bat a následnou úpravou hledat/nahradit v editoru, kde přidáme volání LIDECR.
      30.9.2009 Jak jsem záhy zjistil, tak červ používá pro různé typy souborů různou délku klíče. Obvykle to je 10 Bytů, ale u souborů .TXT, .DOC, .XLS to může být 35 Bytů. Celý klíč je řetězec: 5C 34 1B 69 DC AD 52 15 5D 40 C5 90 C2 B8 06 33 AD E0 23 0D FC A3 20 C1 82 BA E7 A3 0B D0 C9 E0 C9 F7 3F. Do verze 1.1 jsem přidal povinný parametr, kterým se volí použitá délka klíče [1 - 35 Bytů].

MCOPY.EXE ver. 1.24 [54 kB] - tato drobná utilita vám umožní ze vstupního souboru vykopírovat jakoukoliv část do jiného souboru. Stačí zadat offset a velikost bloku. Od vereze 1.23 akceptuje též hexadecimální argumenty označené prefixem 0x.

MP3CUT.EXE ver. 1.0 [52 kB] - jednoduchý nástroj na bezeztrátové stříhání MP3 souborů. Umožňuje ze začátku a z konce souboru odstranit daný počet vteřin (když je tam příliš dlouhá pauza nebo nějaký rušivý lupanec), aniž by bylo potřeba soubor rekompresovat. Pozor, při oříznutí začátku souboru je odstraněn i ID3 v2 tag a při oříznutí konce souboru je odstraněn ID3 v1 tag. Program by měl pracovat s jakýmkoliv MPEG audio souborem různých vzorkovacích frekvencí a bitrate. Zatím jsem ho testoval jen na MPEG1 layer 3 souborech.

MINJECT.EXE ver. 1.1 [52 kB] - provádí v posdtatě opačnou operaci než MCOPY - na určenou pozici v cílovém souboru zapíše data ze zdrojového souboru dané délky. Akceptuje též hexadecimální argumenty označené prefixem 0x.

MTRRLFBE.EXE ver. 1.3 [55 kB] - MTRR-WC enabler for VESA LFB. Na žádost jsem napsal tento malý prográmek, který umožňuje samostatně nastavit režim MTRR registrů pro oblast VGA (A0000h) a LFB (adresu si detekuje sám). Lze tak při nastavení W-C režimu urychlit stávající programy, které vykreslují přes VESA VBE. Na svém stroji Celeron Tualatin 1466, intel BX chipset, SVGA GeForce MX440 jsem např. v režimu 800 x 600 / 32 LFB dosáhl zvětšení propustnosti (RAM->VRAM) z 62 MB/s na 315 MB/s.
      BTW celá věc ohledně MTRRLFBE začala takto: když jsem programoval nějaké grafické funkce v DOSu pro svojí knihovnu, prováděl jsem taky benchmarky různých algoritmů abych vybral ten nejrychlejší. Občas se ale stalo, že program proběhl třeba 5x rychleji než normálně. Ale nesouviselo to nijak s mým kódem, prostě všechny grafické programy v DOSu byly najednou rychlejší. Vysledoval jsem, že tato situace nastane, když restartuju z Win98 přímo do DOSu, aniž by probíhal POST BIOSu. To mě vedlo k myšlence, že nejspíš samy Windows nebo nVidia ovladače něco nastavují tak, že kopírování do framebufferu je mnohem rychlejší. Nakonec jsem vygooglil tento dokument intelu, který popisuje nastavení MTRR a jejich vliv na výkon grafiky. Pak už bylo docela snadné napsat kód, který MTRR nastaví.
      8.1.2007 Verze 1.1 dovoluje nastavit vlastní rozsah adres pro daný režim pomocí parametru USER:bazova_aresa:velikost_kB.
      10.3.2011 Ve verzi 1.3 jsem kompletně přepsal funkce pro nastavení MSR registů tak, aby fungovaly i při běhu pod starým správcem paměti emm386.exe a ve Windows 9x.

NMEA2PLT.EXE ver. 1.3 [53 kB] - konvertor surových GPS dat NMEA-183 do formátu stopy pro OziExplorer. Z terminálového logu vybere řetězce GGA s validním fixem a uloží je jako body stopy ve formátu .PLT. Tento soubor pak lze načíst a zobrazit v OziExploreru, nejlépe na podkladu kalibrované mapy. Časové údaje se uvažují v UTC, OziExplorer je sám zobrazí v LTC, ale pomocí proměnné prostředí TZ je možno provést korekci už při převodu.
      23.1.2007 verze 1.1 opravuje chybu, kdy v případě pěti desetinných míst u zeměpisné šířky a délky docházelo k přetečení a chybným výsledkům v desetinné části stupňů. Dále byla opravena položka udávající počet waypointů v souboru, aby odpovídala skutečnosti (program vynechává NMEA řetězce s neplatným fixem).
      5.9.2007 verze 1.2 upravena z BC pro DJGPP, bylo vylepšeno filtrování vět, takže si poradí i s různým binárním bordelem jako třeba UBX pakety mezi textovými větami. Také jsem přidal počítání kontrolního součtu vět, takže porušené věty jsou ze zpracování vypuštěny.
      13.9.2011 verze 1.3 opravuje chybu parseru, která se projevuje, když zeměpisná šířka nebo délka má místo úvodní nuly mezeru, tak program načte vždy 3 číslice pro stupně a tudíž může přečíst i jednu nebo dvě číslice z následujících minut (pokud byly na začátku 1 nebo 2 mezery). Takže např. místo 14°22' se načetlo 142°02. Tato chyba se týkala i programu GPSMON. Stejným neduhem trpí i program OziExplorer File Format Converter 1.13.

NVSC.COM ver. 1.0 [1 kB] (realmode COM + NASM zdroják) - malá utilitka na přepínání režimu on-chip scaleru grafických karet nVidia pro případ připojení LCD monitoru přes DVI-D. To se může hodit pokud požadujete neinterpolovaný výstup nižších rozlišení 1:1.

NVCLOCK.ZIP ver. 0.8 beta 4 [406 kB] (DOS/Win9x/NT/2k/XP + C zdrojáky) - toto je DOSový a WIN32 port známého linuxového nástroje NVClock. pro grafické karty nVidia. Umožňuje nastavit taktovací kmitočet GPU a videopaměti, zapínat pixel pipeliny, řídit otáčky ventilátoru na GPU, číst teplotu GPU a výpis technických informací včetně MMIO registrů. Win32 port už sice ve zdrojových kódech existoval, ale binár jsem nikde nepotkal. Navíc byla tato sekce kódu zastaralá a zanedbaná a configure dokonce odmítal vytvořit mejkfajly. Nakonec se mi podařilo vše opravit a zkompilovat. K běhu budete ještě potřebovat nainstalovat knihovnu MemAccess Library 1.4 pro přímý přístup k fyzické paměti (MMIO registrům GPU). Jako správný fanda DOSu jsem taky nemohl odolat pokušení portnout NVClock i pro DOS. Pro přímý přístup k fyzické paměti používám DPMI funkci __djgpp_map_physical_memory(), která ale vyžaduje DPMI 1.0 server nebo podporu funkce 0508h. V případě CWSDPMI není žádný problém.
      2.3.2009 jsem rozšířil NVClock o bohatší debug výpis (přidány další registry, zejména RAMDAC CRTC) a přidal jsem novou funkci -e, --expansion <mode>, která umožňuje nastavit scaling obrazu pro připojený LCD panel přes DVI-D. Lze vybrat režim roztažení na celou plochu, obraz 1:1 uprostřed a nativní režim (bez přepočítávání) - ten mi ale funguje pouze v rozlišení 1280x1024 (při menších rozlišeních jde do monitoru nesmyslná frekvence a ten skončí s hláškou out of sync). Možná je to problém jen mojí grafické karty Asus EN7900GT/2DHT.

PWRDOWN.EXE ver. 1.0 [40 kB] - jednoduchá utilita na vypnutí PC s ATX zdrojem. Funguje pouze na základních deskách s jižním můstkem intel ICH.

RAW2C.EXE ver. 1.3 [48 kB] - malý pomocník C programátora, převede jakýkoliv soubor do textového souboru s definicí a inicializací proměnné bajtového pole, který lze pak inkludovat do jiného zdrojového .C souboru.

RAWSPEED.EXE ver. 2.3 [75 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - jednoduchý diskový benchmark. Zjistí průměrnou zápisovou a čtecí rychlost.

ROTOZOOM.EXE ver. 2.2 [59 kB] (nepotřebuje CWSDPMI, má CWSDSTUB).
Rotozoomer - prográmek na real-time rotaci a zoomování obrázku. Impuls k napsání tohoto prográmku mi dal kolega, který totéž psal v assembleru jako semestrálku, ale jeho kód, využívající matematický koprocesor, zrovna rychlostí neoslnil. A tak jsem napsal svoji verzi v C, zvědav jak si s tím poradí optimalizace GCC. Na mojem PC byl program asi 5x rychlejší, na Pentiu 4 dokonce asi 20x. Umožňuje načítat GIFy a 8-bit TGA (i RLE), teoreticky omezené jen velikostí DPMI paměti. Zde je jeden - face.gif.

SERREN.EXE ver. 1.0 [56 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - malá utilitka, která zprovozní propojení SERR# signálu z PCI sběrnice na NMI procesoru nastavením routingu v chipsetu intel ICHx. U některých základních desek / BIOSů toto propojení nefunguje, což brání funkčnosti DOSových driverů SoundBlaster Live! To je sice podmínka nutná, ale nikoliv postačující (na mojí desce GA-P31-DS3L po zapnutí routingu začal fungovat MIDI a Adlib zvuk, ale SFX stále mlčí - patrně problém s DMA).

SMB.ZIP ver. 2.09 [221 kB] (DOS/Win9x/NT/2k/XP/Vista/Linux).
Nyní se zabývám komunikací po sběrnici SMBus, která je v každém novějším počítači a umožňuje pomocí SMB řadiče komunikovat s různými zařízeními základní desky jako např. hodinovým obvodem PLL (mj. řídí FSB), SPD EEPROM na modulu DIMM či různými monitorovacími obvody. Problém je, že každá řada chipsetů má jinak implementován řadič SMBus a proto můj program podporuje pouze základní desky s obvodem southbridge intel 82371 (PIIX4) vyskytujícím se na deskách s chipsety intel TX,LX,BX,ZX,GX pro který jsem měl možnost jej odladit. Stejně tak každé SMB zařízení má svoje specifické ovládání a registry.
      Od 10.1.2003 je v programu zahrnuta experimentální podpora southbridge intel 82801 (ICHx), takže by to mělo chodit i na novějších chipsetech intel 8xx.
      Program zatím umí číst informace o modulech DIMM (včetně výrobce, velikosti, přístupové doby...), číst a nastavovat frekvenci FSB a spread spectrum u PLL obvodů Winbond 83194R-02/04/39/39A, 83195R-08, ICS 9148-26 a CY 28349 a číst teplotu z obvodů MAX1617 a LM75. Testoval jsem jej pouze na obvodu Winbond 83194R-39A. Program používám na "adaptivní overclocking", kdy přetaktuji pouze v případě, že spouštím nějaký náročný program, jinak není důvod 850MHz procesor zbytečně vařit ;-).
      4.7.2003 verze SMB 1.13 obsahuje několik podstatných novinek:
-otestovaná podpora southbridge ICH až ICH5 (ICH6) -informace o modulech DIMM jsou nyní korektní i pro paměti DDR, aktualizovaná databáze výrobců (JEDEC ID)
-podpora PLL Cypress CY28349 s krokem FSB po ~1 MHz od 50 do 248 MHz
-program SCANSMB je nyní integrován do SMB a je dostupný pod parametrem /s
      12.2.2005 do verze SMB 1.15 byla přidána podpora pro obvod-HW monitor ADT7463 a experimentální podpora pro PLL Realtek RTM520-39D (desky Abit BX133 a BF6). FSB lze zatím nastavovat jen v 8-krocích, protože nevím jak odemknout další registry PLL obsahující M,N faktory pro jemné nastavování po 1 MHz, takže zatím aspoň něco. Také byla aktualizována databáze ID výrobců (JEDEC ID).
      18.2.2005 od verze SMB 1.17 budou k dispozici dvě verze programu. Jedna klasicky pro DOS a Win9x kompilovaná v DJGPP a druhá pro Win9x/NT/2K/XP kompilovaná v MinGW32. Windowsácká verze by nemohla vzniknout bez projektu IO.DLL, což je systémová knihovna umožňující přímý přístup k I/O portům pomocí klasických funkcí typu inport/outport. Knihovna se nemusí nijak instalovat, stačí aby byla někde v systémové cestě a program by si ji měl natáhnout sám. Vcelku nenáročnou úpravou svého zdrojáku jsem dosáhl toho, že program můžu kompilovat beze změny oběma překladači (využití #ifdef __MINGW32__ ..., a náhrada pár funkcí z conio.h pomocí funkcí WinAPI).
Nová verze dále obsahuje plnou podporu HW monitoru Winbond W83782D, který je na základních deskách celkem rozšířený. Novinkou je také experimentální debug konzole, kterou lze spustit SMB /dbg. Pomocí zadávaných příkazů lze volat interní C-funkce na obsluhu PCI a SMB a tímto způsobem komunikovat s dosud nepodporovanými zařízeními. Díky skvělé možnosti směrování I/O v C lze příkazy zapsat do textového souboru a pak je spustit jako skript SMB /dbg skript.txt. Jen upozorňuji, že funkce je třeba používat velmi opatrně, jedním chybným zápisem lze zatuhnout počítač tak, že nepomůže ani tvrdý reset nebo i poškodit hardware.
      5.3.2005 Do nové verze SMB 1.18 byla implementována podpora IDE/ATA. Pomocí parametru SMB /ide [hexdump] lze získat spoustu zajímavých informací o IDE discích, včetně S.M.A.R.T. statistiky a třeba i teploty disku, pokud to podporuje (prakticky všechny nové disky). Program funguje i s ternárním a kvaternárním IDE kanálem řadiče HighPoint HPT37x, což ne každý podobný program rozdejchá (bohužel jen v DOS/W9X, NT-suxx). Patřičně byla také rozšířena paleta funkcí konzole, lze například nastavovat AAM (Automatic Acoustic Management), APM, vypnout motor jednotky, číst/zapisovat sektory, měnit konfiguraci... V podstatě lze provést jakýkoliv příkaz ATA, parametry je potřeba nastudovat v příslušné dokumentaci (ATA-7a, ATA-7b, ATA-7c). Pokud příkaz čte/zapisuje nějaká data, jsou uchována v 512B bufferu, který lze modifikovat, mazat a vypisovat. Jako ukázku, jak využít možnosti konzole, jsem napsal tento demo skriptík: smbdemo.txt, který se spustí SMB /dbg smbdemo.txt.
      5.6.2007 Nová řada SMB 2.xx byla z velké části přepsána s využitím knihovny/driveru ioperm.dll 0.5 (stejně jako u programu CPUID) pro Windows řady NT a nově vznikla i verze pro Linux. Přepsány byly moduly obsluhy PCI, SMBus - kde bylo vylepšeno časování a zrychlena komunikace a také přibyla podpora posledních chipsetů ICH7, ICH8 a 631x/632x od intelu, IDE - kde přibyla podpora IDE/ATAPI řadiče ITE8211/8212 a taktéž ICH7, ICH8 a ve výpisu zařízení nyní zobrazuje informace i o ATAPI mechanikách. Podpora IDE je pro Windows řady NT zatím experimentální, vzhledem k nemožnosti zakázat přerušení doporučuju spouštět jen pokud systém zrovna neprovádí diskové operace (kontrolka HDD nesvítí), otestováno na ITE2811 a HPT370 pod Windows XP. Modul SPD byl rozšířen o podporu DDR II pamětí a doplněna databáze výrobců (JEDEC ID). Nově také přibyla funkce PCI scanneru, která se spustí parametrem SMB /pci a vypíše informace o všech nalezených PCI zařízeních. Program má už v sobě vestavěnou malou databázi PCI vendor ID, ale pokud chcete podrobnější informace (i s názvem konkrétního zařízení), tak doporučuji stáhnout velkou databázi z http://members.datafast.net.au/dft0802, kterou řada lidí průběžně doplňuje. Soubor PCIDEVS.TXT stačí nakopírovat do stejného adresáře odkud je SMB.EXE spouštěn a program už sám zdetekuje jeho přítomnost a bude v něm vyhledávat. Také se změnily některé příkazy v debug konzoli.
      16.9.2007 Verze 2.05 přináší experimentální podporu intel ICH9 a opravuje chybu linuxové verze, kdy program spadnul při pokusu uložit DIMM SPD data do souboru.
      16.3.2008 Do verze 2.06 jsem přidal nově podporu pro HW monitor, který je součástí LPC SuperIO Winbond W83627. Pomocí parametru SMB /t fan_type pwm_duty_cycle, kde fan_type je 'a'-auxfan|'c'-cpufan|'s'-systemfan a pwm_duty_cycle je číslo [0-255] určující střídu výstupního signálu PWM regulátoru, lze plynule nastavit otáčky větráku. Také jsem aktualizoval databázi výrobců (JEDEC ID).
      23.3.2008 Verze 2.07 přináší experimentální podporu PLL ICS 954128. Lze nastavit 23 fixních kroků FSB v rozsahu 100 - 400 MHz. Bohužel ale na mojí desce P4LA i při malé změně FSB došlo k výpadku funkce SATA nebo zakousnutí celého systému, takže nemám dále možnost tuto funkci ladit. Také jsem provedl optimalizaci PLL kódu, díky čemuž je nová binárka o chlup menší.
      8.4.2008 jsem přidal do verze 2.08 novou funkci, která umožňuje spolu s parametrem /pci [file] použití externího textového PDT (PCI Device Template) souboru šablony. V tomto souboru lze nadefinovat PCI registry v rámci jednoho PCI zařízení spolu s popisky a formátovacím řetězcem jak se má hodnota vypisovat a přizpůsobit si tak výpis na míru podle daného zařízení. Na ukázku jsem do balíčku přidal šablonu pro intelí (G)MCH 82P31.
      7.9.2009 jsem přidal do verze 2.09 podporu pro SMBus řadič ICH10(R). Úspěšně otestováno na desce Gigabyte GA-P43-ES3G.
      Pokud program vyzkoušíte, dejte mi laskavě vědět, jak vám chodí a s jakým PLL. Budu vděčen i za poslání vašeho logu o modulech DIMM (SMB /d >dimm.log). Zde je ukázka logu mojeho DIMMu 128MB PC133, SMB scanu a HW monitoru. Pokud máte na desce jiný PLL obvod který není podporován a máte zájem o použití programu, stačí napsat a pokud budu mít čas pokusím se jej implementovat.

SPIPGM.ZIP ver. 2.12 [101 kB] (DOS/Win9x/NT/2k/XP/Vista/7/Linux) je software určený k programování sériových SPI FlashROM pamětí připojených k PC přes paralelní port. Umožňuje identifikovat, číst, programovat, verifikovat, mazat a odemykat paměť. Více informací o potřebném hardware zde.
      9.6.2008 Přidána detekce FlashROM pamětí SST25VFxxx a SST26VFxxx. Nemám žádnou paměť na které bych to vyzkoušel, ale podle datasheetu by to mělo fungovat.
      1.8.2008 Přidána detekce FlashROM pamětí Macronix MX25L1005 - MX25L6405 - otestováno s MX25L1605 a MX25L8005.
      25.8.2008 Přidána detekce FlashROM pamětí Atmel AT26DF041 - AT26DF321 - netestováno.
      28.10.2008 Přidána detekce FlashROM pamětí Winbond W25X16 - W25X64 - otestováno s W25X32 a W25X80.
      10.1.2009 Přidána detekce FlashROM pamětí Spansion S25FL004A - S25FL128P - otestováno s S25FL032A.
      21.1.2009 Přidána detekce FlashROM pamětí intel QB25F016S33B8, QB25F032S33B8, QB25F064S33B8 - netestováno.
      11.10.2010 Přidána detekce FlashROM pamětí EON EN25F16, EN25F32, EN25F64, EN25F128 - netestováno. Také jsem vylepšil funkce ovládání LPT portu, takže čtení pamětí by mělo být nyní asi 1,6x rychlejší.
      22.12.2010 Opravena detekce FlashROM pamětí intel a přidána detekce pamětí AMIC A25L05PU/PT, A25L10PU/PT, A25L20PU/PT, A25L40PU/PT, A25L80PU/PT, A25L16PU/PT, A25L32PU/PT, A25L64PU/PT, A25L512, A25L010, A25L020, A25L040, A25L080 - otestováno s A25L080. Také jsem přidal kontrolu parity JEDEC ID Byte, což by mělo pomoci hned na začátku odhalit problém s komunikací (špatný kabel, nevhodné napájení, atp.).
      31.1.2011 Přidána detekce FlashROM pamětí EON EN25F20, EN25F40, EN25F80 - otestováno s EN25F80.
      5.2.2011 Přidána detekce FlashROM pamětí Winbond W25Q10, W25Q20BV, W25Q40BV, W25Q80BV - otestováno s W25Q80BV.
      22.2.2011 Přidána detekce FlashROM pamětí Atmel AT26F004 - otestováno a ESMT F25L004A - otestováno, F25S04PA, F25L08PA, F25L16PA, F25L32PA, F25L32QA.
      20.3.2011 Přidána detekce FlashROM pamětí Winbond W25Q16BV - otestováno, W25Q32BV - otestováno, W25Q64BV, W25Q128BV; PMC Pm25LV512A - otestováno, Pm25LV010A, Pm25LV020, Pm25LV040 - otestováno, Pm25LV080B, Pm25LV016B, Pm25LV032B, Pm25LV064B.
      30.1.2012 V nové verzi 2.0 jsem přepsal velkou část kódu. Zásadně byla přepracována funkce na detekci FlashROM pamětí zvětšující flexibilitu. Nyní jsou podporovány i některé starší paměti, které nemají identifikaci přes JEDEC ID, ale mají kompatabilní ostatní příkazy. Programovací funkci jsem rozšířil o algoritmus Auto Address Increment (AAI) Byte/Word programming mode, který používají starší FlashROM od SST a ESMT. Děkuji Frantovi Ryšánkovi za poskytnutí paměti SST25VF080B na které jsem to mohl odladit. Pro paměti ST řady M45PExx jsem musel přidat funkci mazání po 64kB blocích, protože tyto paměti nemají příkaz Chip Erase. Dále jsem přidal příkaz verify, který porovná obsah paměti se souborem. Nyní je také možno flashovat i image soubory, jejichž velikost je menší než velikost paměti. Program vypíše varování, ale dovolí normálně pokračovat. Nakonec jsem upravil i low-level funkce pro ovládání pinů SPI na základě doporučení Helge Wagnera, díky čemuž se čtení paměti zrychlilo o 25% a zápis o 41%. Přidána detekce FlashROM pamětí Atmel AT25F512B, AT25DF021, AT26DF161, AT25DQ161, AT25DQ321A; EON EN25B10, EN25B20, EN25B40(T), EN25B80, EN25B16; ESMT F25L008A/08PA, F25L016A/16PA, F25L32PA, F25L64PA, F25L016QA; Macronix MX25L512E, MX25L12835E/12836E, MX25L25635E/25735E/25835E; Spansion S25FL256S, S25FL512S, S25FL01GS; ST/Numonyx M25P05, M45PE10, M45PE20, M45PE40, M45PE80, M45PE16, M25PX80, M25PX16, M25PX32, M25PX64, N25Q032A13E, N25Q032A11E, N25Q064A13E, N25Q064A11E, N25Q128A13E, N25Q128A11E, N25Q256A13E, N25Q256A11E, N25Q512A13G, N25Q512A11G, N25Q00AA13GB; SST25VF512(B) - otestováno, SST25VF010(B), SST25VF020(B), SST25VF040(B), SST25VF080(B) - otestováno, SST25VF016(B) - otestováno, SST25VF032(B), SST25VF064C, SST25VF128(B); Winbond W25Q256F.
      7.2.2012 Přidána detekce FlashROM paměti ST M25P10AV - otestováno.
      19.4.2012 Přidána detekce FlashROM pamětí GigaDevice GD25Q512, GD25Q10, GD25Q20, GD25Q40, GD25Q80, GD25Q16 - otestováno, GD25Q32 a GD25Q64.
      8.4.2013 Opravena chyba detekce FlashROM pamětí Spansion S25FL128P, S25FL128S, S25FL129P, S25FL129S pro které jsem měl v tabulce špatné JEDEC ID (překlep).
      14.4.2012 Přidána detekce FlashROM pamětí EON EN25Q40, EN25Q80, EN25Q16, EN25Q32, EN25Q64, EN25Q128 - netestováno.

FAQ:
Ohledně programu SPIPGM dostávám maily ze všech koutů světa a zdá se, že je to od doby uvedení asi nejstahovanější můj program. Děkuji za reporty testů pamětí, které jsem dosud neměl možnost sám otestovat. Některé dotazy a problémy se často opakují, proto bych je zde vypíchnul.       19.3.2011 jsem se pustil do výroby nového hardware pro SPIPGM, který mi umožní snadno programovat i SMD paměti v pouzdru SOIC-8. Mailem mi také došlo pár fotek vašich programátorů:

Franta Ryšánek SPI header cable Richard Burke SPI programmer Carel Minnaar SPI programmer MSI mobo SPI header
Franta Ryšánek Richard Burke Carel Minnaar MSI MB SPI hdr
Colin Mawbey ZIF socket Carl Evans SPI programmer Carl Evans SPI programmer Carl Evans ZIF socket
Colin Mawbey Carl Evans Carl Evans Carl Evans

SUDOKU.EXE ver. 1.2 [55 kB] (nepotřebuje CWSDPMI, má CWSDSTUB) - Když jsem poprvé luštil Sudoku, hned jsem si říkal, že je to úplně ideální úloha pro počítač. Algoritmus je jednoduchý, jen vyžaduje trochu více paměti než je schopen běžný člověk při hře použít (bez psaní čísílek na stranu papíru bych se nechytal). Tak jsem se do toho pustil a po pár hodinách byl Sudoku Solver 1.0 na světě. Podporuje hru v matici 9x9 o 9-ti blocích 3x3. Zadání lze naťukat z klávesnice nebo předat textový soubor jako parametr.

VESATEST.ZIP ver. 1.46 [152 kB] - pro obsluhu grafiky jsem si napsal vlastní VESA VBE driver, VESATEST otestuje kompatabilitu vašeho VESA BIOSu a mojeho driveru. Po proběhnutí testu se vytvoří log soubor, pošlete mi laskavě tyto výsledky.
      24.3.2005 jsem zčásti předělal a vylepšil svůj VESA driver, nyní např. podporuje možnost nastavení režimu Write-Combining pro Linear FrameBuffer a BS okno pomocí MTRR registrů (procesory Pentium Pro a výš), čímž se až několikanásobně urychlí přenos dat z RAM off-screen bufferu do LFB. Toto nastavení příznivě ovlivní i jiné DOSovské programy (ovladače pro Windows obvykle nastaví W-C režim automaticky). Nastavení zůstává platné až do tvrdého resetu.
      10.3.2011 Nová verze 1.45 má vylepšené funkce nastavení MTRR registrů tak, aby fungovaly i pod starým správcem paměti emm386.exe a Windows 9x. V režimu přepínání banků se nyní volá přímo přepínací funkce video BIOSu přes far pointer místo služby INT 10h, což by mělo být o něco rychlejší. Opravil jsem také pár menších chyb. Do balíčku jsem navíc přidal utilitku gtfcalc.exe včetně zdrojového kódu, která vygeneruje podle zadaného rozlišení a obnovovací frekvence monitoru soubor crtc.cfg s nastavením CRTC registrů dle specifikace VESA GTF. Pokud se tento soubor nachází v aktuálním adresáři spolu s VESATESTem, tak ten si z něj načte rozlišení, hodnoty CRTC registrů a další nastavení jimiž překryje výchozí nastavení nebo parametry z příkazové řádky. Dále pracuju na portaci své knihovny pod Windows s využitím knihovny SDL, tak abych mohl své grafické prográmky kompilovat beze změny zdrojového kódu jak v DJGPP pro DOS, tak v MinGW32 pro Windows.

W83977D.EXE ver. 1.0 [49 kB] - Winbond superIO controller W83977EF registers controll utility slouží k výpisu a modifikaci registrů tohoto obvodu, který se hojně používal na základních deskách jako integrované periferie (obsahuje FDC, KBC, LPT, 2xUART, ACPI, 2xGPIO).

WINFALL.EXE [64 kB] - moje 1. 64kB intro v DJGPP, které se umístilo 8. z 10-ti na Fiasku 2000.

TIPY A TRIKY

      Zde bych uvedl pár tipů na co si při psaní programů (nejen) v DJGPP/C dát pozor. Pokud se vám zdá, že se váš program chová poněkud nestandardně, či se právě chystáte v amoku prohodit monitor oknem, zkuste si přečíst pár následujících řádků. Na těchto případech jsem si sám osobně nabil hubu a jak se říká, chybama se člověk učí...

* Inicializace proměnných - v C vám nikdo nezaručí, že proměnné budou mít při startu programu nějakou definovanou hodnotu. I když je tam většinou nula, nelze se na to v žádném případě spoléhat. Zvlášť nebezpečné jsou neinicializované pointery - takto jsem se jednou spálil, když jsem na konci programu uvolňoval paměť funkcí free(...) odkazující se na neinicializovaný pointer (byl využíván jen v některých případech) a divil se, že to občas spadne. Inicializaci je možné provést spolu s deklarací proměnné, např. int i=0; nebo pro struktury a pole funkcí memset(...);.

* Přetečení proměnných/chybná indexace - C nijak nekontroluje přetečení proměnných nebo indexování mimo hranici pole (kvůli rychlosti). Proto je dobré se vždy zamyslet, jaké hodnoty může index pole nabývat a případně to nějak ošetřit. Při zápisu mimo pole můžou nastat zhruba tyto 3 případy:
1) přepíšete si pouze nějaké jiné proměnné - program funguje chybně
2) přepíšete nějakou oblast paměti, která nepatří vašemu programu - zde nejspíš zareaguje správce paměti tím, že program shodí a vypíše chybu o porušení ochrany paměti
3) přepíšete nějakou důležitou systémovou oblast - pokud to memmgr nevychytá tak reset/zatuhnutí PC.
Obzvláště zapeklité jsou případy, kdy dojde k přetečení nikoliv proměnné, ale vnitřní hodnoty ve výrazu (registru). Nedávno jsem to zrovna řešil při portování dekodéru JPEGu, který v 32-bit DJGPP/GCC fungoval bezchybně, ale v 16bit Borland C už ne (kompilátor s -Wall nehlásil žádné chyby a pak že C je vysoce portabilní jazyk). Podívejte se dobře na tento řádek:
QuantTable[temp0][xp][yp]=(JPGGetByte()*aanscales[(xp<<3)+yp])>>12;
QuantTable a aanscales jsou pole typu Word, funkce JPGGetByte() vrací typ Byte. V případě Borland C je vnitřní výraz JPGGetByte()*aanscales[(xp<<3)+yp] vyhodnocován v 16-bitovém registru a když tedy násobíme 16*8 bitů tak nám to samozřejmě přeteče, vyšší bity se ztratí a pak už nepomůže žádná rotace zpět. 32-bitový překladač DJGPP/GCC výraz vyhodnocuje ve 32-bitovém registru a tak k žádnému přetečení nedojde, výraz se rotuje 12 bitů doprava, takže se do Wordu vejde. Najít tuto chybu mi trvalo několik hodin, přitom náprava byla velice jednoduchá, stačilo uvést explicitní přetypování vnitřního výrazu na 32-bit DWord.
QuantTable[temp0][xp][yp]=((DWord)JPGGetByte()*aanscales[(xp<<3)+yp])>>12;

* Nekonstantní velikost standardních datových typů - z Pascalu jsem byl zvyklý, že když napíšu int tak mám prostě 16bit proměnnou, nic víc nic míň. Ne tak v C. Zdá se, že velikost je zcela na libovůli tvůrce překladače a obvykle se uzpůsobuje pro danou architekturu. Proto má DJGPP int 4-bajtový. GCC pro 64-bit procesory bude mít int zřejmě 8-bajtový. Ve většině případů nám to nemusí nijak vadit (kromě případné vyšší konzumace paměti u velkých polí), problém nastane, když máme pracovat s nějakou pevně definovanou datovou strukturou - např. při čtení hlavičky nějakého souboru do struktury si nemůžeme dovolit ponechat její velikost náhodě, protože formát souboru byl jednou stanoven tak a tak. Proto je dobré v takových strukturách nepoužívat standardní datové typy ale nadefinovat si vlastní, které můžeme kdykoli snadno předefinovat. Já jsem si takto definoval typy Byte, Word, DWord a QWord pro 8,16,32,64 bitů do vlastního h-souboru, který includuju v každém programu.

* Memory alignment - to že jsme správně definovali velikosti datových typů nám ještě nezaručí, že struktura z nich složená bude mít správnou velikost. Kdysi jsem se dost divil, že mi sizeof(...) vrací velikost 4 B u struktury složené ze dvou bajtových položek, což by mělo být 2 B. Je to způsobeno úžasnou fíčurou zarovnání paměti (na sudé adresy, pro rychlejší přístup), která je u některých překladačů defaultně zapnutá. V GCC je třeba použít u položek struktury kouzelné slůvko __attribute__((packed)), které zarovnání paměti lokálně potlačí.
Někdy je také potřeba alokovat blok paměťi zarovnaný na násobky velikosti stránek (typicky 4096 B). K tomu slouží funkce valloc(...) (ze stdlib.h), která je proti malloc(...) specifická pro DJGPP.

* sizeof(...) a dynamické proměnné - pokud deklarujeme statické pole např. Byte a[10];, vrátí sizeof(a); hodnotu 10. Avšak pro dynamicky alokované pole Byte a=(Byte *)malloc(10); vrátí sizeof(a); hodnotu např. 4, odpovídající velikosti pointeru. Jak zjistit skutečnou velikost dynamicky alokovaného pole nevím. Zřejmě je potřeba si informaci o alokované velikosti uchovat v další proměnné.

* Správná volba režimu otevření souboru - soubory můžeme rozdělit na textové a binární. Jak je známo, tak textové soubory na systémech DOS a Windows používají jako oddělovače řádků dva bajty - znaky CR a LF, zatímco na Unixech pouze jediný bajt LF. Otevíráme-li tedy v DJGPP textový soubor s oddělovači řádků CRLF použijeme fopen(...,"r"); zatímco u binárních souborů použijeme fopen(...,"rb"); (rb jako read binary). To, že je slušností všechny otevřené soubory (i když otevřené jen pro čtení) taky pouzavírat funkcí fclose(...) (nejlépe hned poté, jakmile už z nich nebudeme dál číst) snad nemusím zdůrazňovat.

* Velikost písmen názvů souborů předávaných programu přes argv[] - case sensitivita je zlo. Zvlášť v operačních systémech, které negarantují konzistenci velikosti písmen v názvech souborů, jako jsou M$ Windows. V případě souborů, jejichž název splňuje DOSovské pravidlo 8.3, se totiž různé verze Windows chovají různě, alespoň na FAT. Pokud je pod Windows 9x vytvořen takový soubor velkými písmeny, uloží se v adresářovém záznamu velkými písmeny. Jestliže obsahuje alespoň jedno malé písmeno, je vytvořen LFN záznam v UNICODE, který Windows 9x i NT-based zpracovávají přednostně. Naproti tomu pokud je pod Windows NT vytvořen soubor s všemi malými písmeny, tak se místo vytvoření LFN záznamu zapíše flag do rezervovaného bajtu v adresářovém záznamu. S tím ale Windows 9x nepočítají a zobrazí soubor velkými písmeny. Navíc při kopírování takových souborů pod Windows NT systém tyto "nadbytečné" LFN záznamy maže. Při přenosu souborů z Windows NT do Windows 9x tedy může dojít ke změně velikosti písmen v názvech souborů, opačně nikoliv.
Start-up kód DJGPP programu provádí také filtrování velikosti písmen a expanzi (globbing) wildcards (*, ? znaků). Implicitně jsou všechny názvy souborů 8.3 konvertovány na malá písmena. V některých případech to může vadit, což lze změnit nastavením proměnné prostředí FNCASE=Y nebo přímo v programu nastavením flagu _CRT0_FLAG_PRESERVE_FILENAME_CASE v proměnné _crt0_startup_flags, viz následující kousek kódu:

#ifdef __DJGPP__
#include <crt0.h>
int _crt0_startup_flags = _CRT0_FLAG_PRESERVE_FILENAME_CASE;
#endif

* Válka indiánů - pro uložení vícebajtových čísel existují dva (doufám že ne více ;-) používané principy: Motorolácký Big endian, kdy se číslo v paměti ukládá od nulté adresy postupně od nejvíce významného bajtu po nejméně významný bajt a Intelácký little endian, kdy se nejprve ukládají nejméně významné bajty. Např. číslo FA821A57 se podle Big endianu uloží jako FA, 82, 1A, 57 zatímco podle little endianu jako 57, 1A, 82, FA (adresy rostou zleva doprava). Mě osobně je sympatičtější Motorolí Big endian. Uvádím to zde proto, že i na PC je potřeba zpracovávat soubory z jiných platforem a např. i ve výše zmiňovaném formátu JPEG se používá zrovna Big endian.

* Granularita funkce delay() - jak jsme byli zvyklí, tak slušně vychovaná funkce delay(...) akceptuje jako argument čas v milisekundách s rozlišením na 1 ms. Při běhu v NTVDM pod Windows NT/2k/XP ale systém delay ignoruje kvůli snížení zátěže CPU. V DJGPP 2.04 byla funkce delay(...) přepsána tak, aby chodila i v NTVDM, avšak granularita se zvýšila na 18,2 ms (standardní rozlišení časovače), což může v některých případech způsobit problémy. Zjistil jsem, že v NTVDM funguje korektně funkce uclock(...), která vrací počet tiků vysokorychlostního časovače (< 1us) a pomocí ní si napsal vlastní funkci delay, která zdá se funguje bez problémů. Jen pro informaci, v MinGW32 je přímý ekvivalent windowsí funkce Sleep(...), též s rozlišením 1 ms.

* Runtime kontrola porušení zásobníku - občas se při ladění záhadně padajícího programu může hodit detekce, že někde došlo k porušení obsahu zásobníku, např. přepsání lokálních proměnných ve funkci mimo rámec. V takové situaci nemusí dojít k běžné chybě ochrany paměti a program zhavaruje později nebo "jen" funguje chybně. Od verze GCC 4.1 přibyla funkce GCC Stack-Smashing Protector (ProPolice). Ta funguje na principu pokusného kanárka. Překladač změní prolog a epilog kód funkcí tak, že na začátku volané funkce se do zásobníku vloží speciální blok dat - tzv. kanárek, který se na konci před návratem z funkce zkontroluje. Pokud se změnil, je kanárek mrtev :). K tomu typicky dojde při překročení indexu pole nějakého bufferu během sekvenčního zápisu. Jestliže však index pole ustřelí o kus dál, nemusí to tento způsob detekce odhalit. Ale pořád lepší než drátem do oka... Zde je jednoduchý příklad pokus.c na otestování SSP:

 int pokus(int x)
 {
   char buffer[10];
   int moo=0x55AA;
   buffer[10]='J';
   return(x+moo);
 }

 int main()
 {
   pokus(1);
   return(0);
 }

Překlad se zapnutým SSP se provede pomocí těchto parametrů: gcc -Wall -fstack-protector-all -lssp -o pokus.exe pokus.c. Po spuštění by se měla objevit hláška: *** stack smashing detected ***: terminated. Bez SSP program normálně skončí bez chyby.

* Agresivní optimalizace GCC - s tím, jak se GCC neustále vyvíjí a zlepšují se jeho optimalizační schopnosti, tak občas dochází i k optimalizacím kódu, které mají nežádoucí vedlejší efekty, jenž mohou způsobit chybné výsledky výpočtů nebo havárii programu. Někdy ani chyba nemusí být na první pohled zřejmá a projeví se až v nejméně vhodnou chvíli. Pokud program crashne, máte aspoň možnost najít a opravit problémovou funkci. Optimalizace GCC se zapíná přepínačem -Ox, kde x je typ / úroveň optimalizace [0..4]. Obvykle se zapisuje v Makefile projektu do proměnné CFLAGS. Nejčastěji se používá -O2 pro optimalizaci na rychlost nebo -Os pro optimalizaci na velikost kódu. Při -Os se používají některé optimalizace -O2, jenž nezvětšují velikost kódu. Optimalizace -O3 se používá už méně často, protože je u ní větší pravděpodobnost výskytu nežádoucích vedlejších efektů. Zapeklitost problému tkví v tom, že každá verze GCC může dělat při dané optimalizaci něco jiného. Občas se tak stává, že program kompilovaný starší verzí GCC, který fungoval korektně, začne při kompilaci novější verzí GCC záhadně padat (při stejné úrovni optimalizace). Nikdy si nemůžete být jisti, že až znovu přeložíte váš program novější verzí GCC, tak bude fungovat správně. Pokud na takové chování narazíte a víte že program dřív fungoval, zachovejte paniku a zkuste to znovu přeložit s -O0 nebo -Os. Pokud program bude fungovat, pokuste se najít problémovou funkci. Možná v ní někde chybí třeba kouzelné slovíčko volatile nebo je nekompletní clobberlist u inline assembleru. Pokud na žádnou chybu ve zdrojáku nepřijdete, je nejjednodušší cesta zbavit se problému selektivním vypnutím optimalizace pro celou funkci pomocí atributu. Tuto možnost nabízí GCC 4.4.0 a vyšší. Zde je ukázka definice takové funkce s potlačenou optimalizací na -O0:
static int __attribute__((optimize(0))) exec_ring0_code(DWord code_address, DWord ecx, DWord *eax, DWord *edx)
Je také možné optimalizaci vypnout pro jeden zdroják nebo jeho část pomocí pragmy:

 #pragma GCC push_options
 #pragma GCC optimize ("O0")

   blok kódu

 #pragma GCC pop_options

Pokud vynecháme push_options a pop_options, bude vynucená optimalizace platit až do konce zdrojového souboru.

* Přetečení max. počtu relokací v jednom object souboru - při překladu nějakého složitějšího projektu jako např. FFMPEG se vám může stát, že překlad nějakého modulu skončí s podobnou chybou:

 CC      dsputil.o
 e:/djgpp/bin/as.exe: dsputil.o: /68: reloc overflow: 0x15b32 > 0xffff
 L:\WINXP\TEMP/ccOqvtFj.s: Assembler messages:
 L:\WINXP\TEMP/ccOqvtFj.s: Fatal error: can't close dsputil.o: File truncated
 make.exe: *** [dsputil.o] Error 1

Jak jsem zjistil, tak formát COFF (Common Object File Format) má limit 65536 relokací v jednom souboru. Pokud je tedy zdrojový soubor příliš velký, vytvoří se při kompilaci tolik relokací, že je nelze všechny uložit. Řešení je několik: je možno zdrojový soubor rozdělit na 2 menší nebo použít selektivně menší úroveň optimalizace (viz tip výše), která obvykle vygeneruje méně relokací. To jsou ale dost nesystémová řešení. Po té, co jsem na tento problém upozornil 25.12.2011 na DJGPP Google group se rozjela celkem zajímavá diskuze, kde bylo zmíněno (již existující) řešení, jak rozšířit COFF formát a nakonec 7.1.2012 vypustil Juan Manuel Guerrero novou verzi BinUtils 2.22, která rozšiřuje počet relokací na teoretických 4294967296 v jednom souboru. Bohužel však této hodnoty nepůjde tak snadno dosáhnout, protože cc1.exe může dojít paměť na zásobníku. Každopádně to dovolí překročit původní limit alespoň několikanásobně. Jak jsem se v praxi přesvědčil, FFMPEG se nyní zkompiloval bez problémů, download zde.

* Volací konvence C-funkcí a DLL - volací konvence C funkcí z dynamických knihoven - ABI V praxi se používá několik typů volacích konvencí (dáno specifikací ABI konkrétního kompilátoru), které určují, jak volající program předá funkci parametry - jejich pořadí v zásobníku, využití registrů a způsob vyklizení zásobníku při návratu z volané funkce. Ve Windows se lze běžně setkat s těmito:

- = MINGW32 = -

      Tak, a teď něco pro 'vývojáře'. Ne, nebojte se, zas tak hrozný to nebude. Jen tak mimochodem, je zajímavé, jaxe lidi, co vytvářejí programy rozdělili na 'vývojáře', 'programátory' a 'codery'. Já se tedy považuji nejspíše za klasického programátora. Akorát mě ještě zcela nepohltila iluze, že kilo salámu váží 1024g. :-) Takové problémy nemusí vývojáře vůbec zajímat, neboť ti jen natahají do projektu ikonky a přiřadí jim procedůrky. Ti by si měli napřed přečíst, jak to fungovalo dříve. Proč tedy o tom melu: i programátor někdy potřebuje něco naprogramovat pro Windows. A proto je tu MINGW pro normální programátory, které jim umožní vytvářet W32 appz klasickým způsobem. MINGW je svým principemvelmi podobné DJGPP - tedy překladač a pár utilit, tzv. GNU toolchain. Pro srovnání jsem si nainstaloval M$ Visual C++ 6.0 a když jsem sehnal MINGW32, taxem VC s radostí smazal.
      Abych nešířil paniku, že snad chci přeběhnout k Windozákům, tak jen uvedu, že jelikož se zajímám o grafiku, taxi taky nemohu nechat ujít programování v OpenGL, které je nyní velmi populární, ať už proto, že jsou konečně na trhu grafické karty za relativně lidovou cenu, které OpenGL kvalitně akcelerují, nebo proto, že OpenGL je velice univerzální - běží totiž na SGI, W32, Linuxu, FreeBSD, snad i BeOSu a dokonce i v DOSu! Bohužel jen softwarově (HW driver je zatím jen pro 3Dfx voodoo).

+ MINGW32 je GNU software, to znamená že si ho stáhnete zadarmo i se zdrojáky.
+ GCC je stále vyvíjený překladač a jeho aktuální verze je 4.7.0
+ Generuje snad nejmenší *.EXE, co jsem kdy ve Windows viděl. No uznejte, helloworld ~3 kB vs 150 kB z M$ Visual C...
+ Na disku zabere jen asi 30 MB.
- Vhodné spíše pro konzolové appz, což v případě SDL/OpenGL nevadí.

Poslední verze MINGW32 s GCC 4.7.0 je zde: http://www.mingw.org.

Zde je vůbec můj první windozácký program, který něco zobrazí v OpenGL okně: POKUS.EXE [3 kB]. Pro jeho spuštění je třeba standardní knihovna opengl32.dll, kterou jistě všichni máte ve svých Windows a dále GLUT32.DLL [68 kB] kterou už asi všichni nemáte...
      5.9.2012 DŮLEŽITÉ UPOZORNĚNÍ: MinGW32/64 od verze GCC 4.7.0 a vyšší používá defaultně zapnutý parametr -mms-bitfields (dříve byl implicitní -mno-ms-bitfields). To se prý týká i GCC na 64-bitovém Linuxu. Tato vlastnost má velmi nepříjemný důsledek v tom, že datové struktury, které byly označeny __attribute__ ((packed)) nejsou nyní pakované na minimální velikost, protože Micro$oft asi chápe pakování jinak. To může velmi zásadně porušit kompatabilitu existujících knihoven a nového kódu. Jedna možnost je přidat do Makefile GCC parametr -mno-ms-bitfields, čímž se zajistí chování jako dříve (vhodné pro překlad starších knihoven). Ve vlastním kódu je také možno použít atribut gcc_struct (jeho protějšek je ms_struct, byly zavedeny už od GCC 3.4) ve spojení s atributem packed, tedy __attribute__ ((gcc_struct, packed)) a pak je zaručeno, že struktura bude vždy pakovaná. Teda možná jen do příští verze GCC :). Více informací zde, zde a zde.

- = LLVM = -

      Programovací jazyky a překladače se neustále vyvíjí. Na poli C/C++ překladačů se čím dál častěji mluví o LLVM (Low-Level Virtual Machine), jenž se dostal do popředí hlavně díky podpoře firmy Apple, která jej využívá pro svůj Mac OS. Jedná se však o OpenSource projekt, který je využíván i dalšími OpenSource projekty, např. poměrně intenzivně ve FreeBSD, kde pravděpodobně nahradí systémový překladač GCC, viz např. tento článek na rootu. GCC totiž začíná být kritizováno, že kompiluje příliš pomalu, žere při tom moc paměti, jeho zdrojové kódy jsou příliš rozsáhlé a zastaralé a ani kompilovaný kód není vždy nejlepší. LLVM je novější a rychle se rozvíjející projekt, který řeší kompilaci inovativním způsobem, kompiluje rychleji s menšími nároky na paměť a dokonce i výsledný kód může být o poznání rychlejší, viz benchmark poslední verze LLVM/Clang 2.9 vs GCC 4.6.
      O LLVM jsem zaslechl už někdy před rokem, ale až teď jsem ho konečně vyzkoušel. Zde se budu dál zabývat jen verzí pro Win32 na PC, jinak je LLVM k dispozici i pro Linux, FreeBSD, Mac OS, Solaris a další. LLVM sám o sobě není kompletním překladačem C/C++, ale umí překládat specifický bytecode virtuálního stroje do nativního strojového kódu procesorů x86-32/64, Alpha, PowerPC, SPARC, ARM, MIPS a dalších. U x86 mě trochu zarazilo omezení, že výsledný kód potřebuje procesor Pentium a vyšší. Např. některá průmyslová PC jsou založena na SoC procesorech Vortex86, což je v jádru přetaktovaná 486, navíc bez matematického koprocesoru. Očekával bych tedy spíše podporu 386 a vyšších. LLVM také umí tento bytecode spouštět runtime na různých platformách jako např. Java JVM. V současnosti existuje celá řada překladačů vyšších programovacích jazyků do bytecode LLVM. Pro C, C++ a Objective-C jsou k dispozici hned dva frontendy: LLVM-GCC a Clang. Zdá se však, že LLVM-GCC zamrzlo na verzi 4.2.x kvůli licenčním problémům (GPL2 vs GLP3). Takže lépe má našlápnuto progresivní Clag, který má lepší a rychlejší parsování kódu při menším využití paměti. Podporuje C99 standard a většinu GNU rozšíření. Produkované chybové hlášky jsou srozumitelnější (zobrazují i řádky zdrojového kódu), viz např.:

L:\LLVM>clang hello.c
hello.c:6:3: warning: array index of '10' indexes past the end of an array (that

      contains 10 elements) [-Warray-bounds]
  b[10]=0;
  ^ ~~
hello.c:3:1: note: array 'b' declared here
char b[10];
^
1 warning generated.

Getting Started dole LLVM 2.9 download clang=C, C++, Objective-C frontend Clang Binaries for Mingw32/x86 LLVM Binaries for Mingw32/x86 LLVM-GCC 4.2 Front End Binaries for Mingw32/x86 Intro to LLVM - book chapter providing a compiler hacker's introduction to LLVM GNU-Binutils GNU Make libiconv-2.dll - http://sourceforge.net/projects/mingw/files/MinGW/libiconv/libiconv-1.13.1-1/libiconv-1.13.1-1-mingw32-dll-2.tar.lzma/download libintl-8.dll GCC 4.6, LLVM/Clang 2.9, DragonEgg Five-System Benchmarks llvm-gcc bylo ukonceno ve verzi 3.0, nahrazuje ho DragonEgg The DragonEgg plug-in is just ideal for those still dependent upon GCC at this time but would like to take advantage of LLVM's code generators and optimizers, but is not considered production ready. The DragonEgg work supersedes LLVM-GCC, which is a LLVM C front-end to GCC. Work on LLVM-GCC is being discontinued after the LLVM 2.9 release with its developers recommending users switch to DragonEgg or Clang, so we are not benchmarking LLVM-GCC anymore. What's New in LLVM 3.0? Windows (32-bit)- On Win32(MinGW32 and MSVC), Windows 2000 will not be supported. Windows XP or higher is required. http://adrianboeing.blogspot.com/2009/05/llvm-for-beginners-windows.html http://code.google.com/p/pcxllvm/downloads/list - win32 llvm 3.0 port http://www.blogcompiler.com/2010/06/13/gcc-for-windows/ - mingw64

- = WinAVR = -

      Poprvé jsem se dostal k mikropočítačům někdy v roce 1997 na SPŠE. Tam jsme se učili o legendárním 8-bitovém procesoru Zilog Z80. Na hardware jsme si ale bohužel ani nesáhli a veškerá praxe se odbývala jen v simulátoru EASYASZ80 1.30. A tak jsem si na univerzálním plošňáku postavil vlastní vývojový kit s eNDeRáckým klonem UA880D, paticí na RAM/EPROM a LEDkama na sběrnicích. Cyklus programování/mazání EPROM, při kterém jsem jednou málem vyhořel, když jsem zapomněl dlouho zapnuté horské slunce, byl příliš zdlouhavý a ubíjející a tak jsem na tom nikdy nic kloudnýho nenaprogramoval. I když to je hadr proti tomu, když jsem četl, jak v dřevních dobách Miroslav Němeček naprogramoval na první pokus funkční monitorovací program (BIOS) pro svůj počítač do 1kB PROM.
      Později jsem se setkal s mikropočítači řady 51 od Atmelu - malý ale šikovný (a levný) AT89C2051, který už měl na čipu 2 kB FlashROM. Programoval jsem ho pomocí paralelního programátoru PATMEL. Stále však bylo nutné vyjímat čip z obvodu a přendavat do programátoru, nicméně díky FlashROM se programovací cyklus mnohanásobně zrychlil. Na FELu jsem pak také dělal na jednom předmětu u Rozehnala (dokud tam ještě učil) s Motorolou MC68HC11, která už podporovala nahrávání programu přímo v cílovém obvodu - ISP (In System Programming) po sériové lince pomocí bootloaderu. Tento MCU byl ale hůře dostupný a na hraní poměrně drahý.
      Vzhledem k malé velikosti paměti se tyto jednočipy programovaly výhradně v assembleru. 51-čkový assembler se dal celkem rychle naučit. Ten motorolí měl jistá specifika, která mi zrovna moc nesedla. Assembler umožňuje programátorovi absolutní kontrolu nad celým hardwarem a maximálně efektivně využít jeho vlastností. Kód je plně deterministický a lze přesně určit počet strojových cyklů na jeho provedení. Horší je to však s orientací ve složitějším projektu, nutnost vlastní zprávy paměti a přenositelností na jiné platformy (ASM instrukce odpovídá strojovému kódu instrukce konkrétního typu/rodiny procesorů).
      Další významnou změnou pro mě bylo, když jsem se ve čtvrťáku setkal poprvé s MCU ATmega32 s 32 kB FlashROM, 2 kB SRAM a 1 kB EEPROM na čipu z rodiny Atmel AVR a programovacím jazykem C pro AVR. Céčko jsem se v té době učil na x86-PC jako samouk a objevoval jeho výhody. Možnost používat takto výkonný jazyk na MCU mi přišla naprosto úžasná. C umožňuje jednoduše vytvářet složitější konstrukce a řeší za programátora správu paměti, přitom lze snadno a efektivně provádět low-level operace na úrovni HW a vždy je tu možnost část kódu nainlajnovat v assembleru. AVR assembler se ale od x51 assembleru dost liší a já jsem pak nějak neměl potřebu se ho učit, když už jsem psal v C. Nicméně je dobré ho umět alespoň číst pro prohlížení toho, co vypadne z C kompilátoru a pro ladění. A uznávám, že dobrý programátor napíše program v assembleru pro MCU vždy lépe, než to udělá překladač jakéhokoliv vyššího jazyka, jenže takových lidí je dnes už dost málo. Z té mladší generace znám jen jednoho, Standu Mašlána, který to s AVRASM opravdu umí, respect.
      Céčko otevírá na MCU dosud netušené možnosti díky přenositelnosti zdrojového kódu. Konkrétně pro AVR existují nejméně 3 různé překladače C: komerční CodeVisionAVR, IAR Embedded Workbench for AVR a OpenSource AVR-GCC, které je k dispozici pro Win32 a Linux (např. pro Debian Linux jsou k dispozici i binárky v .deb balíčku). Právě GCC, které najdete snad všude, umožňuje téměř dokonalou kompatabilitu s velkými stroji. Pro AVR je vyvíjena také malá verze LibC knihovny - AVRLibC. Díky tomu jsem např. mohl velkou část svojí diplomky (souborový systém FAT a částečně ATA driver) napsat a odladit na PC a následně s minimálními úpravami přenést na MCU. Co se týče rychlosti kódu, je na tom GCC znatelně lépe jak CodeVision a o trochu hůře jak IAR. Pro představu, kolik jaká operace či funkce v C zabere taktů, jsem udělal tento test (měřeno pomocí vnitřního 16-bitového časovače).
      AVRko se dá jednoduše programovat přímo v daném obvodu buď přes JTAG nebo sériovou SPI sběrnici. SPI programátor typu BSD je velmi jednoduchý na výrobu, jde v podstatě jen o pár drátů vytažených z paralelního portu (jeden z důvodů, proč se mi nelíbí, že LPT mizí z notebooků a PC). Existuje zde však nebezpečí, že při nějaké nehodě kromě MCU vyhoří i paralelní port PC, což se mi jednou díky mé neopatrnosti opravdu stalo a tak je asi bezpečnější použít nějaký oddělovací obvod pro datové linky osazený v patici. Při použití plochého kabelu je vhodné dát mezi signály SPI země proti přeslechům. O naprogramování vnitřní FlashROM, EEPROM a fuse-bitů se postará program AVRDude, který lze volat přímo z make scriptu (přidal jsem si to jako příkaz make flash). Je pro něj i grafická nadstavba AVRDude-GUI. Pokud toužíte po IDE, tak firma Atmel nabízí zdarma ke stažení AVR Studio, které spolupracuje s WinAVR (není jeho součástí). Obsahuje editor, správce projektu a ladicí nástroje. Ty lze využít jen při propojení pomocí JTAG rozhraní (např. v práci používám JTAG ICE MKII na USB). To přináší možnosti ladění jako na velkém PC - krokování v C i ASM, breakpointy, prohlížení stavu paměti a všech registrů. Ve stop stavu lze například na všech portech jednoduše naklikat stav jednotlivých I/O linek (DDRx, PORTx) a sledovat aktuální stav v případě vstupů. To se hodí při oživování nových desek, když si chci změřit, jestli se signál z portů dostává tam, kam má.
      AVRka jsem si velice oblíbil. Jsou poměrně rychlá (standardně 8 nebo 16 MHz, většina instrukcí trvá 1 takt), dobře vybavené (různé on-chip periferie, výkonové výstupy [half-bridge] schopné přímo budit LED), blbovzdorné (už se mi povedlo párkrát přepólovat napájení nebo hustit proud do výstupního portu bez následků), dostupné (GME, GES) a levné (leckdy se vyplatí dát 30 peněz za 1 MCU, než se matlat s kupou standardních TTL/CMOS obvodů). Existuje celá škála od mrňousů ATTiny s 8 vývody a 1 kB FlashROM po velké ATMegy256x s 256 kB FlashROM, 8 kB SRAM a 4 kB EEPROM na čipu. Další verze mají nějakou speciální periferii nebo jsou určeny pro automobilový průmysl či pro bateriové aplikace se sníženou spotřebou a napájecím napětím - řada picoPower AVR. Doma i v práci jsem navrhoval zapojení či programoval celou řadu AVR (ATTiny2313, ATMega8, 1650, 32, 325p, 3250, 64, 6450, 128 a 2560, přes SPI i JTAG) a jsem s nimi velice spokojen. Takto vypadá moje bastldeska s ATMega32:

ATMega32 bastldesk foto

      Pokud chcete začít programovat AVRka, odkážu vás na tutoriály pro začátečníky zde a zde. Nemusím snad zdůrazňovat, že základním zdrojem informací jsou datasheety a aplikační nóty firmy Atmel, kde je vše podrobně a vcelku srozumitelně popsané. Předpokladem je však znalost angličtiny a odborných termínů. Ti pokročilejší pak mohou hledat pomoc se zapeklitými problémy na fóru AVRFreaks. Bohužel v poslední době díky krizi je dostupnost AVRek bídná a ceny vysoké (i několikanásobně než dříve). Podle mých posledních informací už jede výroba zase naplno, ale téměř všechny součástky jdou velkým zákazníkům do výroby a nepatrný zbytek do distribuce. Snad se příští rok 2011 situace zlepší, nerad bych z nouze sahal po něčom jako PIC. Pokud vám výkon 8-bitového AVR už nestačí, můžete zkusit zaexperimentovat s 32-bitovým ARM7 LPC2103FBD48 od NXP, který nabídne za stejné peníze mnohem větší výkon.
      29.8.2012 Každý programátor dělá chyby, ale nejhorší je, když musí lovit chyby v cizím kódu nebo se nemůže spolehnout ani na vývojové nástroje. Následující příběh se týká avr-gcc 4.7.0 vydaného 24.4.2012. V práci jsem dostal za úkol ke své senzorové aplikaci na AVR ATMega88pa napsat ještě bootloader, aby šlo firmware aktualizovat přímo po vyvedeném RS232. Jako protokol pro přenos dat jsem se rozhodl implementovat XModem-CRC download, protože je to protokol jednoduchý a podporuje ho každý lepší terminálový program (už od dob DOSu). Dílo se celkem dařilo, ale protože jsem musel dost šetřit pamětí (ATMega88pa má boot sekci velkou max. 2 kB), hledal jsem další optimalizace. Jednou z nich, kterou už používám celkem automaticky je vytvoření samostatných sekcí pro funkce tak, aby linker mohl ty nepoužívané vypustit (jedná se o parametry GCC -fdata-sections, -ffunction-sections a -Wl,--gc-sections).
      Dále jsem přešel na GCC 4.7.0, které lépe optimalizuje na velikost a ušetřilo mi asi 150 B kódu, ale tím jsem si také zadělal na problémy. XModem přenos náhle začal tuhnout. Né hned, ale až po té, co jsem zrušil dočasné globální proměnné. Funkce pro příjem XModem paketu strká data do pole, které je zde definováno jako static pole Bytů (ušetří taky trochu místa): static Byte packet_buffer[XMODEM_DATA_SIZE];. Jak jsem zjistil, tak po zápisu asi 30 Byte do bufferu se program zbláznil a nakonec zasekl. Bylo evidentní, že se zapisuje někam, kam se nemá, ale přitom nešlo o překročení hranice pole. Pokud jsem dal třídu static pryč, tj. buffer se alokoval se zavoláním funkce na zásobníku, tak problém zmizel. Pokud jsem vyhodil z Makefile parametry na vytváření samostatných sekcí, tak taky OK. Když jsem zakomentoval dočasně část kódu a přeložil starým GCC 4.3.3, tak vše fungovalo bezchybně i se static.
      Po bádání s kolegou nad LST a MAP soubory, jsme objevili nemilé překvapení, kdy GCC 4.7.0 ze záhadného důvodu umístilo buffer v sekci .bss od adresy 0x60, kde se nachází různé systémové registry procesoru, místo od adresy 0x100, kde začíná SRAM. Takže docházelo při příjmu dat k přepisu těchto registrů, což celkem logicky vyústilo v havárii, dokonce mi i blikla LEDka (jelikož při ladění této funkce nemůžu používat UART pro ladicí výstupy a MCU má jen jeden, tak jsem si prostě blikal a chytal to na digitálním osciloskopu) Tato vlastnost se přitom projevovala pouze tehdy, pokud zde nebyly žádné globální proměnné a sekce .data tak byla prázdná. Linker jakoby sekci .data vypustil a posunul kvůli tomu začátek .bss. Náprava byla tedy už celkem jednoduchá, jednu proměnnou z funkce main() jsem vyšoupnul ven jako globální a vše zas fungovalo. Když jsem chtěl chybu reportovat na AVRFreaks, koukal jsem, že už vydali ke stažení RC verzi GCC 4.7.1, tak jsem ji samozřejmě vyzkoušel a hle, chyba byla opravena. Resp. linker script WINAVR\AVR\LIB\LDSCRIPTS\avr4.x, který stačí překopírovat do stávající verze avr-gcc. Zde je ukázka z MAP souborů:

.data           0x00800100        0x0 load address 0x00001fb4
                0x00800100                PROVIDE (__data_start, .)
 *(.data)
 *(.data*)
 *(.rodata)
 *(.rodata*)
 *(.gnu.linkonce.d*)
                0x00800100                . = ALIGN (0x2)
                0x00800100                _edata = .
                0x00800100                PROVIDE (__data_end, .)
.bss            0x00800060       0x82
                0x00800060                PROVIDE (__bss_start, .)
 *(.bss)
 *(.bss*)
 .bss.start_main
                0x00800060        0x2 bootldr.o
                0x00800060                start_main
 .bss.packet_buffer.1868
                0x00800062       0x80 bootldr.o
 *(COMMON)
                0x008000e2                PROVIDE (__bss_end, .)
špatně

.data           0x00800100        0x2 load address 0x00001fdc
                0x00800100                PROVIDE (__data_start, .)
 *(.data)
 *(.data*)
 .data.timeout  0x00800100        0x2 bootldr.o
                0x00800100                timeout
 *(.rodata)
 *(.rodata*)
 *(.gnu.linkonce.d*)
                0x00800102                . = ALIGN (0x2)
                0x00800102                _edata = .
                0x00800102                PROVIDE (__data_end, .)
.bss            0x00800102       0x82
                0x00800102                PROVIDE (__bss_start, .)
 *(.bss)
 *(.bss*)
 .bss.start_main
                0x00800102        0x2 bootldr.o
                0x00800102                start_main
 .bss.packet_buffer.1876
                0x00800104       0x80 bootldr.o
 *(COMMON)
                0x00800184                PROVIDE (__bss_end, .)
správně

- = SPHINX C-- = -

      Jak již název napovídá, jedná se o mrňavou distribuci C překladače, který je speciálně určen na tvorbu malých programů *.COM a rezidentů. Takový helloworld.com pak zabírá ~70 B ! Optimalizuje pro CPU 8086-80586. Bohužel syntaxe není zrovna moc ANSI, takže se napřed budete muset seznámit s dodávanými příklady.

Zde je verze 1.04a C--.ZIP [979 kB]
domovská stránka je tady: http://c--sphinx.narod.ru

- = NASM = -

      Tak a teď něco pro opravdu lowlevel programátory. Jelikož jsem se teď začal zajímat o modifikaci BIOSu, potřeboval jsem vytvořit kousek čistého binárního kódu. A v tom mě TASM zklamal. Naštěstí ale právě pro tyto účely existuje tento GNU překladač assembleru. Má však jiné direktivy a pseudoinstrukce, nicméně pro začátek nemusíte použít žádnou. Stačí jen posloupnost instrukcí. Dokonce ani na konci souboru nemusí být END. Taky se trochu liší syntaxe přístupu k paměti:  MOV AL,[CS:SI+10] proti MOV AL,CS:[SI+10] a jiné drobnosti.
      Nakonec z toho všeho vznikl projekt ROMOS, který umožňuje bootovat FreeDOS z ROMky. Na něm jsem se v assembleru docela vyřádil, takže rači zpět k pohodlí Céčka :). Pokud se chcete inspirovat, jak píší opravdoví mistři assembleru, tak doporučuju prostudovat zdrojáky z programátorské soutěže Hugi Size Coding Competition.

Zde je ke stažení NASM ver. 0.98.38 [116 kB]
Po dlouhé době se objevila nová verze 2.08.02, ke stažení na domovské stránce: http://nasm.sourceforge.net



Zpět

Aktualizováno 15.4.2013 v 3:36

Sportovní výživa a posilovací stroje Ronnie.cz. Luxusní kabelky od Hraběnky