Zaváděcí kód a velikost .EXE souboru
                    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

        There was once a programmer who was attached to the court of the
      warlord of Wu. The warlord asked the programmer: "Which is easier to
             design: an accounting package or an operating system?"

                 "An operating system," replied the programmer.

          The warlord uttered an exclamation of disbelief. "Surely an
      accounting package is trivial next to the complexity of an operating
                               system," he said.

          "Not so," said the programmer, "when designing an accounting
      package, the programmer operates as a mediator between people having
       different ideas: how it must operate, how its reports must appear,
       and how it must conform to the tax laws. By contrast, an operating
        system is not limited my outside appearances. When designing an
      operating system, the programmer seeks the simplest harmony between
        machine and ideas. This is why an operating system is easier to
                                    design."

      The warlord of Wu nodded and smiled. "That is all good and well, but
                           which is easier to debug?"

                         The programmer made no reply.
                  -- Geoffrey James, "The Tao of Programming"

          Po  provedení  stubu se dostane ke slovu  zaváděci  kód.  Ten má
      za úkol všechno  připravit a zavolat  vlastní main. Dělá doho o něco
      víc, než je zvykem. DJGPP se tím snaží docílit větší kompatibility s
      UNIXEM. (V UNIXu například expanze příkazové řádky (* a další znaky)
      nejsou věcí programu, ale věcí shellu,  který  program  volá.  DJGPP
      tedy  expanduje  tyto znaky  automaticky při startu, aby programy už
      dostaly  parametry  stejně jako v UNIXU)  Například tato automatická
      konverze je občas nežádoucí,  protože pak nemůžete  předat  programu
      parametry obsahující znaky jako *.

          Díky  tomu  jsou  také  výsledné  .EXE  soubory  o  něco  větší.
      Hodně  funkcí  jde  ale  vypnout v případě, že nejsou  třeba.  Proto
      lze velikost  výsledného  .exe souboru  změnšit na 6KB, což není tak
      strašné  vzhledem k popsanému  cirkusu  při  inicializaci a DJGPP je
      tedy i docela vhodné pro psaní krátkých utilit.

          Všechny  prototoypy  pro  tento  kód  sídlí  v  headeru  crt0.h.
      Rúzné  parametry  pro start  programu lze  nastavit  pomocí  proměné
      _crt0_startup_flags. Nastavíte jí tak, že do svého programu napíšete
      int 15_crt0_startup_flags=něco.  Funkce musí být globální (tedy mimo
      funkci a bez static) Jde nastavit následující flagy:

      _CRT0_FLAG_PRESERVE_UPPER_CASE   Pokud   tento   flag  je  nastaven,
         nepřevede se argv[0] (jméno programu) na malá písmena.
      _CRT0_FLAG_USE_DOS_SLASHES  Nepřevádí  se  potom  v  argv[0]  opačná
         lomítka na normální
      _CRT0_FLAG_DROP_EXE_SUFFIX Pokud je nastaven, užízne se přípona .exe
         v argv[0]
      _CRT0_FLAG_DROP_DRIVE_SPECIFIER  pokud  je  nastaven,  užízne  se  z
         argv[0] jméno disku (pokud je uvedeno)
      _CRT0_FLAG_DISALLOW_RESPONSE_FILES  Standardně  zavaděcí  kód projde
         parametry a pokud  najde  parametr ve formátu  @jmeno,  přečte si
         parametry  se souboru  jmeno a nahradí  je.  Pokud je tento  flag
         nastaven, nic takového se nestane.
      _CRT0_FLAG_FILL_SBRK_MEMORY Pokud je nastaven, každá pamět přidávaná
         do  programu  se  napřed  snuluje.  To  potřebují  některé  vadné
         programy z UNIXU,  protože  tam se  to  děje  automaticky  (kvůli
         bezpečnosti)
      _CRT0_FLAG_FILL_DEADBEEF  Paměť  nenuluje,  ale nastavuje na hodnotu
         0xdeadbeef, což umožňuje vychytat chyby.
      _CRT0_FLAG_NEARPTR Pokud je nastaven, od adresy __djgpp_nearptr_base
         se spřístupní  fyzická paměť. Vypne to protekci paměti a proto se
         to nedoporučuje.
      _CRT0_FLAG_NULLOK Vypne odchytávání přístupu na ukazatel NULL.
      _CRT0_FLAG_NMI_SIGNAL   Pokud  se  nastaví,   nejsou   MNI   signály
         propouštěny do 16ti bitového  kódu. To občas dělá  potíže s green
         BIOSy
      _CRT0_FLAG_NO_LFN Vypne podporu pro dlouhé názvy pod W95
      _CRT0_FLAG_UNIX_SBRK  Zařídí,  aby  se  sbrk  chovalo  jako v UNIXu.
         Tedy  aby  všechna  paměť  byla  zasebou. To ale  občas  vyžaduje
         přesouvání bloků paměti a také některé DPMI servery neumožňují tak
         naalokovat celou paměť.
      _CRT0_FLAG_LOCK_MEMORY  Uzamkne  celý  program  v  paměti  a  zakáže
         swapování.  To  je  občas   třeba,  když  chcete   psát  ovladače
         interruptů a nechcete je zamykat  ručně.  Vypne to ale  virtuální
         paměť a tak to není dobrý nápad.
         Co jsme s ReDoxem testovali, tento flag nějak nefunguje.
      _CRT0_FLAG_PRESERVE_FILENAME_CASE  Vypne  převod   názvů  z  velkých
         písmen na malá.

          Nastavením  této  proměné  sice  můžete  vypnout  různé  funkce,
      ale pořád se zalinkují do programu.  Pokud  chcete  určité kusy kódu
      vyhodit, je nutné  místo nich napsat  prázdné  funkce,  které  potom
      linker použije místo těch originálních.

      Startovací kód mimo zavádění programu ještě dělá:
      - detekci koprocesoru a zavedení emulátoru
      - načítání kondifuračního souboru djgpp.env do environmentu
      - expanzi příkazové řádky (*, @ apod)

      Vypnutí zavedení souboru s environmentem (to jde udělat skoro ve všech
      programech) se provede pomocí:

      void __crt0_load_environment_file(char *_app_name) { return; }

      Expanze zolinkových znaků se provádí pomocí:

      char **__crt0_glob_function(char *_arg) { return 0; }

      Pomocí této funkce můžete nastavit i svůj vlastní expander...

      Přípravu argv a argc provádí funkce:

      void __crt0_setup_arguments(void);.

          Pokud  váš  program  nepoužívá  parametry, je možné ji  nahradit
      za prázdnou funkci.

          Dále lze z programu  vyhodit exception  handling  (program potom
      v případě že například vydělí nulou nevypíše registry, ale zatuhne)

      void _npxsetup(void) { return; }
      int __emu387_load_hook;
      short __djgpp_ds_alias;
      void __djgpp_exception_setup(void) { return; }
      int __djgpp_set_ctrl_c(int enable) { return 0; }

          Poslední  šikovná  proměná  je  _stklen,  potomcí  které  můžete
      nastavit velikost zásobníku bez použítí programu stubedit.

          Mimochodem jedna z metod jak zmenšit velikost výsledného souboru
      je nezalinkovat  debugovací  informace  pomocí přepínače -s, nebo je
      sundat  pomocí  programu  strip.  Přestane  pak ale chodit  užitečná
      utilitka symify.


            výheň