# Assembly HOWTO

## Autor: François-René Rideau fare@tunes.org
v0.4n, 22 Sierpnia 1998
Wersja polska: Zbigniew Michał Kempczyński wegorz@bydgoszcz.pkobp.pl
v1.0, 30 Stycznia 1999 r.

Dokument ten został napisany w standardzie ISO-8859-2. Oryginał tego dokumentu znajduje sie pod adresem http://www.tunes.org/~fare/Assembly-HOWTO. To jest Linux Assembly HOWTO. Ten dokument opisuje metody programowania w assemblerze z użyciem WOLNYCH narzędzi programistycznych, koncentrując się na Systemie Operacyjnym Linux na platformach i386. Załączony materiał może, ale nie musi być zgodny, z innym sprzętem i/lub oprogramowaniem. Przewodnictwo na tym będzie mile widziane. Słowa kluczowe: assemblacja, assembler, wolny, makroprocesor, preprocesor, asm, inline asm, 32-bitowy, x86, i386, gas, as86, nasm

## 1. WPROWADZENIE

## 1.1 Legal Blurp

Copyright © 1996,1997,1998 by François-René Rideau.

Ten dokument jest wolnym oprogramowaniem, możesz go redystrybuować i/lub modyfikować zgodnie z założeniami GNU General Public License opublikowanym przez Free Software Foundation; wersja 2 Licencji, lub (w twoim przypadku) inna późniejsza wersja.

## 1.2 Ważna Informacja

To jest interaktywnie rozwijany dokument: jesteś specjalnie proszony do zadawania pytań, udzielania odpowiedzi na pytania, poprawiania odpowiedzi, dodawania nowych odpowiedzi na FAQ, wskazywania na inne oprogramowanie, wskazywania osobie prowadzącej błędy lub braki na stronach. Jeśli jesteś zmotywowany, mógłbyś przejąć prowadzenie tego HOWTO. Słowem, działaj !

By przejąć prowadzenie skontaktuj się z kimkolwiek, kto wydaje się prowadzić Assembly-HOWTO. W trakcie tego pisania to jestem ja, np. François-René Rideau. Jakkolwiek, minęło trochę czasu od kiedy poszukiwałem mocnego gościa by podmienił mnie jako prowadzącego ten dokument. Niekorzyścią jest to, iż musisz spędzić trochę czasu trzymając dokument na czasie, poprawiając go, i ucząc się narzędzi publikacyjnych LDP. Korzyścią jest to, iż zdobędziesz trochę sławy i możesz otrzymać wolne kopie kompendiów HOWTO.

## 1.3 Przed słowem

Ten dokument ma na celu udzielenie odpowiedzi na najczęściej zadawane pytania przez ludzi, którzy programują lub chcą programować w 32-bitowym assemblerze x86 używając wolnych assemblerów, zwłaszcza w systemie operacyjnym Linux. Może on także wskazywać inne dokumenty o nie-wolnych, nie-x86, lub nie-32-bitowych assemblerach, chociaż nie jest to jego pierwszorzędnym celem.

Ponieważ głównym celem programowania w assemblerze jest budowa wnętrzności systemów operacyjnych, interpretatorów, kompilatorów, i gier, gdzie kompilator C zawodzi nie dostarczając potrzebnych środków wyrazu, (wykonanie jest coraz rzadszym tematem), skoncentrujemy się na rozwoju takiego oprogramowania.

### Jak używać tego dokumentu

Ten dokument zawiera odpowiedzi na pewne najczęściej zadawane pytania. W wielu miejscach, zostały umiejscowione adresy URL by wskazać na pewne oprogramowanie lub magazyny dokumentacji.

Sprawdź gdzie są skopiowane najbardziej użyteczne magazyny, i spróbuj dobrać się do najbliższej z nich; uchronisz w ten sposób Internet przed niepotrzebym ruchem w sieci, i zaoszczędzisz swój cenny czas.

W szczególności pewne wielkie magazyny na całym świecie, sa kopiami innych popularnych magazynów. Powinieneś się nauczyć i zapamiętać miejsca umiejscowione blisko ciebie (roztropność-sieciowa). Czasami, lista takich kopii jest wypisana w pliku, lub we wiadomości wejściowej. Miej na uwadze te porady. W przeciwnym wypadku zapytaj archie o oprogramowaniu którego szukasz...

Najświeższe wersje tego dokumentu znajdują się w http://www.tunes.org/~fare/Assembly-HOWTO lub http://www.tunes.org/~fare/Assembly-HOWTO.sgml

ale to co jest w magazynach Linux HOWTO powinno być także na czasie (ale tego nie wiem):

ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/ (?)

Francuska wersja tego HOWTO może być znaleziona w

ftp://ftp.lip6.fr/pub/linux/french/HOWTO/

### Inne zależne dokumenty

- Jeśli nie wiesz czym jest wolne oprogramowanie, proszę przeczytaj ostrożnie GNU General Public License, która jest używana w wielu wolnych programach, i jest pierwowzorem dla większości takich licencji. Ogólnie pojawia się w pliku o nazwie `COPYING`, z wersją biblioteczną w pliku o nazwie `COPYING.LIB`. Literatura z FSF (fundacja wolnego oprogramowania) może także ci pomóc.
- W szczególności, interesującym rzeczą w takim typie wolnego oprogramowania przychodzącego ze źródłami jest to, iż możesz je sprawdzić, poprawić a także czasami z nich zapożyczyć. Przeczytaj ostrożnie szczegóły licencji i skorzystaj.
- Jest lista FAQ na comp.lang.asm.x86, która odpowie na wiele ogólnych pytań o programowaniu w assemblerze x86, i pytaniach o pewnych komercyjnych assemblerach w 16-bitowym środowisku DOS-a. Pewne z nich zahaczają o wolnym 32-bitowym programowaniu, więc możesz chcieć przeczytać to FAQ... http://www2.dgsys.com/~raymoon/faq/asmfaq.zip
- FAQ-i i dokumenty istnieją o programowaniu na twojej ulubionej platformie, jakakolwiek ona jest, więc powinieneś skonsultować tematy specyficzne dla niej nie bezpośrednio związane z programowaniem w assemblerze.

## 1.4 Historia

Każda wersja zawiera kilka napraw i mniejszych korekt, których nie będzie trzeba ciągle poprawiać.

Version 0.1 23 Kwiecień 1996

  Francois-Rene "Faré" Rideau <fare@tunes.org> tworzy i publikuje pierwsze mini-HOWTO, ponieważ ``Jestem chory od ciągłego odpowiadania na te same pytania na comp.lang.asm.x86''

Version 0.2 4 Maj 1996

  *

Version 0.3c 15 Czerwiec 1996

  *

Version 0.3f 17 Październik 1996

  *

Version 0.3g 2 Listopad 1996

  Utworzenie Historii. Dodanie wskaźników w sekcji o cross-kompilacji. Dodanie sekcji o programowaniu I/O pod Linux-em (w szczególności video).

Version 0.3h 6 Listopad 1996

  więcej o cross-kompilacji - Zobacz na sunsite: devel/msdos/

Version 0.3i 16 Listopad 1996

  NASM łatwo przechodzi

Version 0.3j 24 Listopad 1996

  wskazanie na tłumaczenie francuskie

Version 0.3k 19 Grudzień 1996

  Co ? Zapomniałem wskazac na terse???

Version 0.3l 11 Styczeń 1997

  *

Version 0.4pre1 13 Styczeń 1997

  tekst mini-HOWTO przekształca się w pełne linuxdoc-sgml-owe HOWTO, by zobaczyć jak wyglądają narzędzia SGML.

Version 0.4 20 Styczeń 1997

  pierwsze jako takie wypuszczenie tego HOWTO.

Version 0.4a 20 Styczeń 1997

  dołożono sekcję Wyrazy Uznania

Version 0.4b 3 Luty 1997

  przesunięcie NASM: teraz jest przed AS86

Version 0.4c 9 Luty 1997

  Dodano sekcję "CZY POTRZEBUJESZ ASSEMBLACJI ?"

Version 0.4d 28 Luty 1997

  Vapor oznajmia o nowym przewodnictwie Assembly-HOWTO.

Version 0.4e 13 Luty 1997

  Wypuszczenie o DrLinux

Version 0.4f 20 Marzec 1997

  *

Version 0.4g 30 Marzec 1997

  *

Version 0.4h 19 Czerwiec 1997

  wciąż więcej na temat "jak nie używać assemblacji"; unowocześnienie o NASM, GAS.

Version 0.4i 17 Lipiec 1997

  info o 16-bitowym trybie dostępu z Linux-a.

Version 0.4j 7 Sierpień 1997

  *

Version 0.4k 19 Październik 1997

  *

Version 0.4l 16 Listopad 1997

  wypuszczenie o szóstej edycji LSL.

Version 0.4m 23 Marzec 1998

  poprawki o wywołaniu gcc

  To jest jeszcze inne ostatnie-wydanie-przez-Faré-przed-przejęciem-przez-nowego prowadzącego (?)

## 1.5 Wyrazy Uznania

Chaciałbym podziękować następującym osobom, w kolejności występowania:

- Linus Torvalds za Linux-a
- Bruce Evans za bcc z którego jest wyciągnięty as86
- Simon Tatham i Julian Hall za NASM
- Jim Neil za Zwięzłość
- Greg Hankins za prowadzenie HOWTO
- Raymond Moon za jego FAQ
- Eric Dumas za tłumaczenie mini-HOWTO na francuski (smutna rzecz, że autor jest francuzem i pisze po angielsku)
- Paul Anderson i and Rahim Azizarab za pomoc, jeśli nie przejęcie HOWTO.
- Marc Lehman za wgląd w wywołania GCC.
- Wszystkim ludziom którzy włożone pomysły, uwagi i wsparcie moralne.

## 2. CZY POTRZEBUJESZ ASEMBLACJI?

No, nie chciałbym przeszkadzać w tym co robisz, ale tu jest kilka porad ciężko zarobionego doświadczenia.

## 2.1 Za i Przeciw

### Korzyści Assemblacji

Assemblacja może wyrazić mocno niskopoziomowe rzeczy:

- masz dostęp do zależnych-od-maszyny rejestrów i I/O.
- możesz kontrolować dokładnie zachowanie kodu w krytycznych sekcjach które mogą wywołać martwe punkty pomiędzy wieloma wątkami programowymi lub urządzeniami.
- możesz złamać ustalenia zwykłego kompilatora, który może pozwalać na pewne optymalizacje (jak chwilowe łamanie zasad o przydzielaniu pamięci, wątkach, konwencji wywołań, itd).
- możesz budować interfejsy pomiędzy fragmentami kodu używającego pewnych niekompatybilnych konwencji (np. produkowanego przez różne kompilatory, lub oddzielonego nisko-poziomowym interfejsem).
- masz dostęp do nieużywanych trybów twojego procesora (np. 16 bitowy tryb interfejsu startowego, instrukcji chip-owych (przyp.tłum.) lub dziedziczonego kodu na Intel PC)
- możesz produkować rozsądnie szybki kod dla zwartych pętli by poradzić sobie ze złym nie-zoptymalizowanym kompilatorem (po co, są przecież dostępne wolne zoptymalizowane kompilatory!)
- możesz produkować kod gdzie ale tylko na procesorach ze znanym czasem instrukcji, który ogólnie wyłącza cały przepływ ....
- możesz produkować ręcznie-zoptymalizowany kod który jest perfekcyjnie dostosowany do twojej szczególnej konfiguracji sprzętowej, a zatem do nikogo więcej.
- możesz pisać pewien kod dla twojego kompilatora nowego języka (to jest coś którzy mogą zrobić nieliczni, i także oni, nie często).

### Niekorzyści Assemblacji

Assemblacja jest bardzo nisko-poziomowym językiem (najniższym jest ręczne-kodowanie w kodach binarnych instrukcji).

To znaczy

- jest długo i monotonnie pisać wszystko od początku,
- jest mocno podatna na błędy,
- błędy będą bardzo trudne do wyśledzenia,
- jest to bardzo trudno zrozumieć i modyfikować, np. utrzymywać
- rezultat jest bardzo nie-przenośny na inne architektury, aktualne i przyszłe,
- twój kod będzie zoptymalizowany tylko w pewnych implementacjach na tej samej architekturze: dla przykładu, pośród platform Intelowskich, każdy wariant CPU i jego odmian (względy ukryte, przepustowość, pojemność jednostek obliczeniowych, cache'y, RAM-u, szyny, dysków, obecności FPU, rozszerzeń MMX, itd) daje potencjalnie całkowicie różne techniki optymalizacji. Warianty CPU już włączone Intel 386, 486, Pentium, PPro, Pentium II; Cyrix 5x86, 6x86; AMD K5, K6. Nowe warianty pojawiają się więc nie spodziewaj się, że każdy listing twojego kodu będzie na czasie.
- twój kod może być także nieprzenośny przez różne platformy systemowe na tej samej architekturze, przez brak właściwych narzędzi (no, GAS wydaje się pracować na wszystkich platformach; NASM wydaje się pracować lub być w stanie pracować na platformach intelowskich).
- spędzisz więcej czasu na kilku detalach, i nie będziesz mógł skoncentrować się na małych i dużych algorytmach, które są w stanie przynieść największą część przyspieszenia. [np. możesz spędzić trochę czasu budując bardzo szybkie prymitywy manipulacji na listach/tablicach w assemblerze; tylko hash-tablice (przyp.tłum.) mogą mocno przyspieszyć twój program; lub i innym przypadku, drzewka binarne; lub pewne wysokopoziomowe struktury rozprowadzane przez klaster CPU]
- mała zmiana w konstrukcji algorytmu mogłaby całkowicie unieważnić twój cały istniejący assemblowany kod. Tak więc także ty masz być gotowy (i w stanie) by przepisać to wszystko, lub będziesz przywiązany do poszczególnych rozwiązań algorytmicznych;
- W kodzie który nie wypada daleko od standardowych testów, komercyjne zoptymalizowane kompilatory wykonują prawe ręcznie-kodowany assembler (no, to jest mniejszą prawdą na architekturze x86 niż na architekturach RISC-owych; i być może mniejszą prawdą niż dla szeroko dostępnych/wolnych kompilatorach; jakkolwiek, dla typowego kodu w C, GCC jest całkiem dobry);
- I w dowolnym przypadku, jak powiedział wstrzemięźliwy John Levine na comp.compilers, ``kompilatory mocno ułatwiają używanie złożonych struktur danych, i kompilatory nie dają znudzenia w połowie drogi i generują całkiem dobry kod.'' One także będą prawidłowo przechodzić transformacje kodu poprzez cały (olbrzymi) program podczas optymalizacji kodu pomiędzy procedurami i granicami modułów.

### Ocenianie

Podsumowując, chociaż możesz uznać że użycie assemblacji jest czasami konieczne, a nawet pożyteczne w kilku przypadkach gdzie nie jest konieczne, będziesz chciał:

- minimalizować użycie kodu assemblera,
- hermetyzować ten kod w dobrze zdefiniowanych interfejsach
- mieć kod assemblera generowany automatycznie ze wzorców wyrażonych w wysokopoziomowym języku niż w assemblerze (np. assemblerowe makra GCC inline)
- mieć narzędzia automatyzujące tłumaczenie tych programów w kod assemblera
- mieć ten kod zoptymalizowany jeśli jest to możliwe
- Nade wszystko, np. pisać (rozszerzać do) zoptymalizowanych wnętrzności kompilatora.

Nawet w przypadkach kiedy Assemblacja jest konieczna (np. rozwój OS) możesz uznać, że nie aż do tego stopnia i trzymać się w/w zasad.

Obejrzyj źrodła jądra Linux-a zwracając uwagę: jak mało assemblacji jest konieczne, by uzyskać szybki, niezawodny, przenośny, utrzymywalny OS. Także udana gra taka jak DOOM została prawie całkowicie napisana w C, z mała częścią napisaną w assemblerze tylko do przyśpieszenia jej działania.

## 2.2 Jak NIE używać Assemblera

### Ogólne zasady uzyskania efektywnego kodu

Jak rzekł Charles Fiterman na comp.compilers o 'człowieku kontra kod assemblera wygenerowany przez komputer',

``Człowiek powinien zawsze wygrać i oto przyczyna.

- Po pierwsze człowiek pisze całość w języku wysokiego poziomu.
- Po drugie zarysowuje gdzie mogą wystąpić gorące punkty gdzie program spędza swój czas.
- Po trzecie ma kompilator produkujący kod assemblera dla tych małych sekcji kodu.
- Po czwarte ręcznie dostosowuje je by znaleźć małe korzyści nad wygenerowanym przez maszynę kodem.

Człowiek wygrywa poniewaz umie używać maszyny.''

### Języki ze zoptymalizowanymi kompilatorami

Języki takie jak ObjectiveCAML, SML, CommonLISP, Scheme, ADA, Pascal, C, C++, wsród innych, wszystkie mają wolne zoptymalizowane kompilatory, które zoptymalizują masę twoich programów, i często będą lepsze niż ręczny kod assemblera nawet dla szczelnych pętli, umożliwiając ci skoncentrowanie się na wysokopoziomowych szczegółach, i bez zakazywania ci złapania kilku procent wykonania w wyżej wymieniony sposób w momencie gdy osiągniesz stabilny rozwój. Oczywiście, są także komercyjne zoptymalizowane kompilatory dla większości z tych języków.

Pewne języki mają kompilatory produkujące kod w C, który może być dalej zoptymalizowany przez dany kompilator C. Takimi są LIST, Scheme, Perl i wiele innych. Prędkość jest całkiem dobra.

### Ogólne zasady przyśpieszania twojego kodu

W celu przyspieszenia kodu powinieneś robić zrobić to tylko dla fragmentów programu które narzędzie profilujące konsekwentnie określa jako wąskie gardło wykonania.

Stąd, jeśli określisz fragmenty kodu jako zbyt wolne, powinieneś

- najpierw spróbować lepszego algorytmu;
- następnie spróbować skompilować go zamiast interpretować;
- następnie spróbować włączyć optymalizacje twojego kompilatora;
- następnie dać kompilatorowi wskazówki jak optymalizować (wypisywanie informacji w LISP-ie; używanie rejestrów w GCC; i pełno innych opcji w większości kompilatorów, itd).
- następnie można cofnąć się do programowania w assemblerze

Na końcu, przed zejściem do pisania w assemblerze, powinieneś prześledzić wygenerowany kod, sprawdzając czy problem nie leży faktycznie w złej generacji kodu, co jest możliwe ale nie w wypadkach: kod wygenerowany przez kompilator może być lepszy niż mógłbyć napisać, w szczególności na nowoczesnych architekturach! Wolne części programu mogą być równie zagmatwane. Największym problemem nowoczesnych architektur z szybkimi procesorami są pewne opóźnienia dostępu do pamięci, nietrafiony dostęp do cache, i TLB oraz błędy stronnicowania; optymalizacja z użyciem rejestrów staje się wtedy mniej użyteczna, i zyskałbyć więcej po przemyśleniu struktury danych oraz wykorzystując wątkowanie gdyż uzyskałbyś lepsze umiejscowienie w dostępie do pamięci. Być może poźniej dopiero całkowicie odmienne spojrzenie na problem, pomoże go rozwiązać.

### Sprawdzanie kodu generowanego przez kompilator

Jest wiele powodów do sprawdzenia kodu generowanego przez kompilator. Tu jest zawarte co robić z takim kodem:

- sprawdzić czy generowany kod może być wzmocniony ręcznym kodem assemblera (lub przełączaniem przełączników kompilatora)
- gdy zachodzi taka możliwość rozpocząć z tak wygenerowanego kodu i zmodyfikować go; zamiast rozpoczynać wszystko od początku
- bardziej ogólnie, używać generowanego kodu jako kawałków do modyfikacji, który co najmniej daje właściwą drogę twoim funkcjom w assemblerze interfejs do świata zewnętrznego
- wyłapać błędy w kompilatorze (oby jak najrzadziej)

Standardową metodą uzyskania kodu assemblera jest wywołanie twojego kompilatora z flagą `-S`. Działa to dla większości Unix-owych kompilatorów, włączając w to GNU C Compiler (GCC), ale YMMV. Dla GCC, bardziej zrozumiały kod assemblera będzie wyprodukowany po użyciu opcji `-fverbose-asm`. Oczywiście, jeśli chcesz dostać dobry kod assemblera, nie zapomnij użyć opcji optymalizacji i wskazówek!

## 3. ASSEMBLERY

## 3.1 Inline Assemblera GCC

Dobrze znany kompilator GNU C/C++ (GCC), zoptymalizowany 32-bitowy kompilator będący sercem projektu GNU, wspiera całkiem dobrze architekturę x86, włączając w to zdolność wstawiania kodu assemblera w programach w C, w sposób gdzie zarządzanie rejestrami może być wyspecyfikowane lub pozostawione GCC. GCC działa na większości dostępnych platform, dla godnych uwagi Linux-a, *BSD, VST, OS/2, *DOS-a, WIN*, itd.

### Gdzie znaleźć GCC

Orginalny adres GCC jest adresem FTP GNU ftp://prep.ai.mit.edu/pub/gnu/ razem ze wszystkimi wersjami aplikacji z projektu GNU. Przekompilowane i skonfigurowane dla Linux-a wersje są w ftp://sunsite.unc.edu/pub/Linux/GCC/ Istnieje wiele kopii FTP obu adresów, na całym świecie a także na nośnikach CD.

Rozwój GCC został podzielony niedawno na dwie części. Więcej na temat eksperymentalnej wersji egcs mozna znaleźć na http://www.cygnus.com/egcs/

Źródła przystosowane do twojej ulubionego OS, oraz przekompilowane binaria można znaleźć na zwykłych adresach FTP.

Najbardziej popularny port GCC dla DOS-a nosi nazwę DJGPP i może być znaleziony w katalogach o takiej nazwie na adresach FTP. Zobacz:

http://www.delorie.com/djgpp/

Jest także port GCC na OS/2 nazwany EMX, działający także pod DOS-em, zawierający wiele bibliotek emulujących wywołania funkcji unix-a. Zobacz:

http://www.leo.org/pub/comp/os/os2/gnu/emx+gcc/

http://warp.eecs.berkeley.edu/os2/software/shareware/emx.html

ftp://ftp-os2.cdrom.com/pub/os2/emx09c/

### Gdzie znaleźć dokumentacje GCC Inline Asm

Dokumentacja GCC zawiera pliki w formacie texinfo. Możesz przekompilować je TeX-em i wydrukować rezultat, lub przekonwertować je do .info i oglądać emacs-em, lub przekonwertować je do .html. Możesz przekonwertować je (właściwymi narzędziami) do tego co lubisz najbardziej, lub czytać takie jakie są. Pliki .info są ogólnie dostarczane z każdą dobrą instalacją GCC.

Właściwą sekcją do sprawdzenia jest: `C Extensions::Extended Asm::`

Sekcja `Invoking GCC::Submodel Options::i386 Options::` może być ci także pomocna. W szczególności, podaje ci specyficzne ograniczenia nazw rejestrów: abcdSDB korespondują do `%eax`, `%ebx`, `%ecx`, `%edx`, `%esi`, `%edi`, `%ebp` wyłączając (nie ma litery dla `%esp`).

Zasoby gier dla DJGPP (nie tylko dla hackerów gier) mają swoją stronę specjalnie o assemblerze:

http://www.rt66.com/~brennan/djgpp/djgpp_asm.html

Jest jeszcze strona www nazwana ``DJGPP Quick ASM Programming Guide'', zawierająca od URL-i do FAQ, AT&T Składnia ASM x86 , Pewne informacje o inline ASM, i konwertowanie plików .obj/.lib:

http://remus.rutgers.edu/~avly/djasm.html

GCC zależy od GAS podczas assemblacji, i śledzi jego składnię (patrz poniżej); pamiętając że inline asm wymaga znaków procent podczas cytowania by mogły przejść do GAS. Zobacz poniższą sekcję o GAS.

Znajdziesz pełno użytecznych przykładów w podkatalogu `linux/include/asm-i386/` źródeł jądra Linux-a.

### Jak właściwie wywoływać GCC z kodem inline assemblera.

Ponieważ funkcje assemblera w źródłach jądra (i bardzo prawdopodobnie twoje własne nagłówki, jeśli spróbujesz stworzyć twoje oprogramowanie w assemblerze tak czyste jak to jest w jądrze linuxa) są osadzone w funkcjach `extern inline`, GCC musi zostać wywołąny z `-O` flag (or `-O2`, `-O3`, itd), by te funkcje były dostępne. Jeśli nie, twój kod może się skompiluje, ale nie zostanie właściwie zlinkowany, gdyż będzie szukał funkcji `extern` które nie są inline w bibliotekach z którymi twój program będzie linkowany !!!. Innym sposobem jest zlinkowanie z bibliotekimi zawierającymi wycofane wersje tych funkcji.

Assemblacja inline może zostać wyłączona opcją `-fno-asm`, która każe zaprzestać kompilatorowi działania gdy zostanie użyte rozszerzenie składni o inline asm, w przeciwnym wypadku wygeneruje wywołanie funkcji zewnętrznej o nazwie `asm()`, która nie zostanie właściwie rozwiązana przez linker. Opcja `-fasm` przywraca działanie słowa kluczowego `asm`.

Bardziej ogólnie, dobrymi opcjami dla GCC na platformie x86 są

            gcc -O2 -fomit-frame-pointer -W -Wallpp

`-O2` jest dobrym poziomem optymalizacji w większości przypadków.

Optymalizacja ponadto zajmuje więcej czasu, otrzymując kod który jest mocno dłuższy, ale tylko trochę szybszy; taka optymalizacja może być użyteczna tylko dla ciasnych pętli (jeśli takie są), którą możesz jakkolwiek zrealizować w assemblerze. W przypadkach gdy koniecznie potrzebujesz silnej optymalizacji ze strony kompilatora dla kilku plików, rozważ użycie `-O6`.

`-fomit-frame-pointer` pozwala generować kod omijający głupie zarządzanie ramką wskaźników, co daje mniejszy i szybszy kod, i zwalnia rejestry do dalszych optymalizacji. Wyklucza to łatwe użycie narzędzi odpluskwiających (`gdb`), ale kiedy chcesz ich użyć, nie martw się o rozmiar i prędkość kodu.

`-W -Wall` włącza generowanie wszytkich ostrzeżeń i pomaga wychwycić głupie błędy.

Możesz dodać specyficzne dla danego procecora `-m486` lub inne flagi tak, że GCC wyprodukuje kod bardziej zaadaptowany dla danego komputera. Zauważ, że EGCS (i chyba GCC 2.8) mają `-mpentium` i tego typu flagi, podczas gdy GCC 2.7.x i starsze wersje nie. Niezły wybór flag specyfikujących procesor powinien być w jądrze Linux-a. Sprawdź dokumentację texinfo o zainstalowanej u ciebie wersji GCC.

`-m386` pomoże zoptymalizować wielkość, a także prędkość na komputerach gdzie pamięć jest w pełni wykorzystana, odkąd wielkie programy są przyczyną wymiany pamięci, jakakolwiek "optymalizacja" jest sensowna dla większego kodu. Przy takich ustawieniach, może być pomocne przestanie korzystania z C, i w zamian skorzystanie z języka ułatwiającego kod faktoryzujący (przyp.tłum.) taki jak funkcjonalny język i/lub FORTH; i używać implementacji bazującej na wykorzystaniu bajtów i słów.

Zapamiętaj, że możesz używać rożnych flag dla różnych plików, więc używaj maksymalnej optymalizacji tam, gdzie program wykonuje się najdłużej, podczas gdy pozostałe pliki optymalizuj pod względem rozmiaru.

Do optymalizacji może być pomocna opcja `-mregparm=2` i/lub korespondujące atrybuty funkcji, ale mogą stwarzać wiele problemów podczas linkowania obcego kodu, włączająć w to libc. Są sposoby by właściwie zadeklarować użycie obcych funkcji, tak, że zostaną wygenerowane właściwe wywołania, lecz możesz być zmuszony rekompilować obce biblioteki tak, by używały takich samych konwencji wywołań opartych na rejestrach...

Zapamiętaj, że możesz ustawić te flagi jako domyślne edytując plik `/usr/lib/gcc-lib/i486-linux/2.7.2.3/specs` lub gdziekolwiek on jest w twoim systemie (lepiej nie dodawaj tam -Wall). Dokładną lokalizację plików specyfikatorów GCC w twoim systemie możesz uzyskać wołająć `gcc -v`.

## 3.2 GAS

GAS jest GNU Assemblerem, na którym opiera się GCC.

### Gdzie go znaleźć

Znajdziesz go w tym samym miejscu gdzie GCC, w paczce o nazwie binutils.

### Jaka jest składnia AT&T

W związku z tym, że GAS został pomyślany by wspierać 32-bitowe kompilatory unixowe używa on standardowej składni ``AT&T'', która składnią mocno przypomina standardowe assemblery m68k, i jest standardem w świecie UNIX-a. Składnia nie jest ani gorsza, ani lepsza niż składnia ``Intel-owska''. Jest po prostu inna. Kiedy będziesz zamierzał używać jej, zauważysz bardziej regularna składnię niż w Intel-u, chociaż trochę nudniejszą.

Oto najważniejsze ostrzeżenia odnośnie składni GAS:

- Nazwy rejestrów są poprzedzone `%`, więc wygląd rejestrów `%eax`, `%dl` itd zamiast tylko `eax`, `dl`, itd. Dzięki temu możliwe jest włączanie zewnętrznych symboli w C bezpośrednio w kodzie assemblera, bez zamieszania i konieczności stosowania okropnych podkreśleń jako przedrostków.
- Kolejność operandów jest następująca: pierwsze źródło, ostatnie przeznaczenie, w przeciwieństwie do konwencji intel-a, gdzie pierwsze jest przeznaczenie, a ostatnie źródło. Odtąd, to co w składni intel-a jest `mov ax,dx` (wstaw rejestr `dx` w rejestr `ax` w składni att będzie wyglądało następująco: `mov %dx, %ax`.
- Długość operandu jest wyspecyfikowana przez przyrostek w nazwie instrukcji. Przyrostkiem jest `b` dla (8-bitów) bajtu, `w` dla (16-bitów) słowa, i `l` dla (32-bitów) podwójnego słowa. Na przykład, właściwą składnią powyższej instrukcji będzie `movw %dx,%ax`. Jakkolwiek, gas nie wymaga ścisłej składni att, więc przyrostek jest opcjonalny, kiedy długość operandu może być wywnioskowana z rejestrów, w przeciwnym przypadku, domyślnie zostanie wstawiony 32-bitowy operand (z ostrzeżeniem).
- Wymuszające operandy zaznaczone są przyrostkami `$`, tak jak w `addl $5,%eax` (dodaj wymuszające long dla wartość 5 do rejestru `%eax`).
- Brak przedrostka w operandzie wskazuje, że jest to adres w pamięci; stąd `movl $foo,%eax` wstawia zawartość adresu zmiennej `foo` w rejestr `%eax`, ale `movl foo,%eax` wstawia zawartość zmiennej `foo` w rejestr `%eax`.
- Indeksacja lub wskazanie pośrednie jest realizowane przez umieszczenie rejestru indeksowego lub wskazania pośredniego (komórki wskazania pośredniego) w nawiasach, np `testb $0x80,17(%ebp)` (sprawdza najstarszy bit bajtu o offsecie 17 z komórki wskazanej przez `%ebp`).

Istnieje program pomagający w konwersji programów ze składni TASM do składni AT&T. Zobacz

ftp://x2ftp.oulu.fi/pub/msdos/programming/convert/ta2asv08.zip

GAS ma obszerną dokumentację w formacie TeXinfo, którą można znaleźć co najmniej w dystrybucji źródłowej. Przegląd wyciągniętych stron .info z Emacs-a lub innych programów. Zdarzały się pliki o nazwach gas.doc lub as.doc gdzieś w pakietach źródłowych GAS, ale zostały włączone w dokumentacje TeXinfo. Oczywiście, w razie wątpliwości, alternatywną dokumentacją są same źródła! Sekcją, która szczególnie cię zainteresuje to `Machine Dependencies::i386-Dependent::`

Znowu, źródła Linux-a (jądra systemu), są dobrymi przykładami; zobacz w linux/arch/i386, następujące pliki: `kernel/*.S, boot/compressed/*.S, mathemu/*.S`

Jeśli piszesz jakiś język, pakiet obsługi wątków, itd. możesz obejrzeć jak inne języki (OCaml, gforth, itd.), lub pakiety obsługi wątków (QuickThreads, MIT pthreads, LinuxThreads, itd), lub cokolwiek, zrób to.

Na końcu, po prostu skompiluj program w C do assemblera dzięki czemu zobaczysz interesującą cię składnię. Zobacz sekcję Czy potrzebuję Assemblacji?.

### Ograniczony tryb 16-bitowy

GAS jest 32-bitowym assemblerem, zadaniem którego jest wspomóc 32-bitowy kompilator. Aktualnie ma on jedno ograniczenie 16-bitowego trybu, który zawiera niedokończone użycie 32-bitowych przedrostków do instrukcji, tak więc piszesz 32-bitowy kod, który chodzi w 16-bitowym trybie na 32 bitowym procesorze. W obu trybach, wspiera on 16-bitowe używanie rejestrów, ale nie wspiera 16-bitowego adresowania. Użycie dyrektywy `.code16` and `.code32` przełącza pomiędzy trybami. Zapamiętaj, że dyrektywa inline assembly `asm(".code16\n")` pozwoli GCC wygenerować 32-bitowy kod, który uruchomi się w trybie rzeczywistym!

Stwierdziłem już, że większa część kodu potrzebnego do pełnego wspomagania 16-bitowego trybu programowania została dodana do GAS przez Bryan'a Ford'a (proszę o potwierdzenie?), ale ostatecznie, nie pojawiła się w żadnej dystrybucji którą sprawdziłem, aż do binutils-2.8.1.x ... więcej informacji na ten temat będzie mile widziane.

Cienkim rozwiązaniem jest definiowanie makr (patrz poniżej), które produkuja kod binarny (z `.byte`) który potrzebujesz tylko dla 16-bitowych instrukcji (prawie żadnych jeśli użyjesz code16 jak powyżej, i możesz spokojnie założyć, że kod będzie działał na zgodnych 32-bitowych procesorach x86). By znaleźć właściwe kodowanie, możesz zainspirować się źródłami 16-bitowych assemblerami.

## 3.3 GASP

GASP jest Preprocesorem GAS. Dodaje makra i trochę milszą składnię do GAS.

### Gdzie znaleźć GASP

GASP jest zawarty razem z GAS w archiwum GNU binutils.

### Jak to działa

Działa jako filtr, w stylu cpp i jemu podobnym. Nie pamiętam szczegółów, ale przychodzi on z własną dokumentacją w texinfo, więc przejrzyj ją (w .info), wydrukuj, prześledź (?). GAS z GASP-em według mnie jest typowym makro-assemblerem.

## 3.4 NASM

Projekt Netwide Assembler wypuszcza jeszcze jeden assembler, napisany w C, który powinien być dość modelowy do ewentualnego wsparcia znanych składni i formatów obiektów.

### Gdzie znaleźć NASM

http://www.cryogen.com/Nasm

Wersja binarna jest na kopii sunsite w `devel/lang/asm/` Powinna być także dostępna jako .rpm lub .deb w dystrybucjach RedHat/Debian w dystrybucyjnym contrib.

### Co to robi

W momencie pisania tego HOWTO, wersja NASM to 0.97.

Składnia jest w stylu Intel-a. Część makroprocesora jest zintegrowana.

Wspierane formaty plików obiektowych to `bin`, `aout`, `coff`, `elf`, `as86`, (DOS) `obj`, `win32`, (ich własny format) `rdf`.

NASM może być używany jako wspomaganie dla wolnego kompilatora LCC (pliki wspierające są zawarte).

NASM rozwija się zbyt szybko by to HOWTO było aktualne. Jeżeli nie używasz BCC jako 16-bitowego kompilatora (który wykracza poza to 32-bitowe HOWTO), powinieneś używać NASM zamiast powiedzmy AS86 lub MASM, ponieważ jest mocno wspierany online i chodzi na wszystkich platformach.

Uwaga: NASM przychodzi także z disassemblerem, NDISASM.

Jego ręcznie napisany parser powoduje, że pracuje szybciej niż GAS, chociaż oczywiście nie wspiera trzech bilionów różnych architektur. Do x86, on powienien być assemblerem wyboru...

## 3.5 AS86

AS86 jest 80x86 16- i 32-bitowym assemblerem i jest częścią kompilatora języka C (BCC) Bruce'a Evans'a. Ma on głównie składnię Intel-owską, chociaż różni się nieznacznie np w trybach adresowania.

### Gdzie dostać AS86

Całkowicie przestarzała wersja AS86 jest dystrybuowana przez HJLu tylko do kompilacji jądra Linux-a, w pakiecie o nazwie bin86 (aktualna wersja 0.4), dostępnej w dowolnym magazynie oprogramowania GCC dla Linux-a.

Ale nie radzę nikomu używania go do czegokolwiek innego niż przekompilowania Linux-a. Ta wersja wspiera tylko plik obiektowy hacked minix, który nie jest wspierany przez GNU binutils ani nic innego, i ma parę błędów w trybie 32-bitowym, więc powienieneś lepiej trzymać go tylko do kompilacji Linux-a.

Ostatnie wersje Bruce'a Evans'a (bde@zeta.org.au) są publikowane wraz z dystrybucją FreeBSD. No, były: Nie mogę znaleźć źródeł z dystrybucji 2.1 na :( Odtąd, wkładam źródła w moim miejscu:

http:///www.tunes.org/~fare/files/bcc-95.3.12.src.tgz

Projekt Linux/8086 (aka ELKS) jest w pewnym stopniu pozostałością bcc (chociaż nie sądze by zawierał 32-bitowe łaty). Obejrzyj http://www.linux.org.uk/Linux8086.html ftp://linux.mit.edu/.

Między innymi, ostatnie wersje, w przeciwieństwie do HJLu's, wspierają Linux-owy format GNU a.out, więc możesz linkować twój kod z programami Linux-owymi, i/lub używać zwykłych narzędzi z pakietu GNU binutil do manipulacji danymi. Ta wersja może ko-egzystować bez szkody z poprzednią wersją (zobacz poniższe pytanie).

BCC z 12 marca 1995 roku i wcześniejsze jego wersje mają brak składnika jakim jest odkładanie/pobieranie ze stosu rejestrów segmentowych jako 16-bitowych, co jest uciążliwe gdy programujesz w trybie 32-bitowym. Łata jest opublikowana w projekcie Tunes http://www.tunes.org/ podstrona `files/tgz/tunes.0.0.0.25.src.tgz` w rozpakowanym katalogu `LLL/i386/` Łata powinna być także dostępna bezpośrednio z http://www.tunes.org/~fare/files/as86.bcc.patch.gz Bruce Evans zaakceptował tę łatę, więc jeśli któregoś dnia pojawi się nowa wersja bcc, powinna zawierać tę łatę...

### Jak wywołać assembler?

Oto wpis GNU Makefile do używania bcc do transformacji `.s` asm w oba GNU a.out `.o` obiekt i `.l` listing:

    %.o %.l:        %.s
            bcc -3 -G -c -A-d -A-l -A$*.l -o $*.o $<

Usuń `%.l`, `-A-l`, and `-A$*.l`, jeśli nie chcesz listingu. Jeśli chcesz czegoś więcej niż GNU a.out, możesz przejrzeć dokumentację bcc o wspieranych formatach, i/lub użyć objcopy z pakietu GNU binutils.

### Gdzie znaleźć dokumentacje

Dokumentacje które są, zawierają się w pakiecie bcc. Podręczniki są także dostępne gdzieś pod adresem FreeBSD. Kiedy masz wątpliwości, źródła same w sobie są często dobrą dokumentacją: to nie jest zbyt dobrze komentowane, ale styl programowania jest zrozumiały. Możesz spróbować obejrzeć jak as86 jest używany w Tunes 0.0.0.25...

### Co jeśli nie mogę już skompilować Linux-a z nową wersją ?

Linus jest zasypywany listami i moja łata kompilująca Linux-a z Linuxowym a.out as86 chyba do niego nie dotarła (!) (od tłum. trudno to przetłumaczyć - proszę o poprawki). Teraz, nie powinno to mieć znaczenia: trzymaj tylko as86 z pakietu bin86 w /usr/bin i daj zainstalować bcc dobry as86 w /usr/local/libexec/i386/bcc/as gdzie powinien być. Nie będziesz nigdy wołał wprost tego ``dobrego'' as86, ponieważ bcc robi wszystko właściwie, włączając konwersję to Linux-owego a.out, gdy jest wywołany z właściwymi opcjami; więc assembluj pliki wyłącznie z bcc jako głownym assemblerem, nie bezpośrednio z as86.

## 3.6 INNE ASSEMBLERY

To są inne, nieregularne, opcje, w przypadku, gdy powyższe cię niesatysfakcjonowały (dlaczego?), których nie zalecam w przypadku użytkowania (?), ale mogę udowodnić użyteczność jeśli assembler musi być zintegrowany w oprogramowaniu które rozwijasz (np. OS lub aplikacje rozwojowe).

### Win32Forth assembler

Win32Forth jest wolnym 32-bitowym systemem ANS FORTH który działa pod Win32s, Win95, Win/NT. Zawiera wolny 32-bitowy assembler (zawiera przed/przyrostkową składnię) zintegrowany w języku FORTH. Przetwarzanie makr jest przez pełną moc języka FORTH; jakkolwiek, jedynym wspieranym wejścia i wyjścia jest Win32For (żadnego zrzutu do plików .obj -- możesz oczywiście dodać to samemu). Znajdziesz to na ftp://ftp.forth.org/pub/Forth/win32for/

### Terse

Terse jest narzędziem programowania dostarczającym NAJBARDZIEJ zwartą składnie assemblera dla rodziny x86! Zobacz http://www.terse.com. Mówiono, że jest gdzieś jakiś wolny klon który został porzucony po pustych pretensjach, że składnia powinna być własnością autora; i zapraszam cię do przejęcia tego, jeśli taka składnia cię interesuje.

### Nie-wolne i/lub Nie-32bitowe x86 assemblery.

Możesz znaleźć więcej o nich, wraz z podstawami programowania w assemblerze x86 w FAQ Raymond'a Moon'a dla comp.lang.asm.x86 http://www2.dgsys.com/~raymoon/faq/asmfaq.zip

Zapamiętaj, że wszystkie bazujace na DOS-ie assemblery powinny pracować w Linuxowym emulatorze DOS-u tak dobrze jak inne podobne emulatory, więc jeśli już masz jakiś możesz go nadal używać w prawdziwym OS. Ostatnie assemblery bazujące na DOS-ie także wspierają COFF i/lub inne formaty plików obiektowych, które są wspierane przez bibliotekę GNU BFD, więc możesz używać ich razem z wolnymi 32-bitowymi wolnymi narzędziami, być może używająć GNU objcopy (część binutils) jako filtr konwertujący.

## 4. METAPROGRAMOWANIE/MAKROPRZETWARZANIE

Assemblacja programów jest nudna, ale do krytycznych części programów.

Powinieneś używać właściwego narzędzia do właściwego zadania, więc nie wybieraj assemblacji kiedy nie jest stosowna; C, OCAML, perl, Scheme, mogą być lepszym wyborem dla większości twojego programowania.

Jakkolwiek, są wypadki gdy te narzędzia nie dają ci wystarczającej kontroli nad maszyną, i assemblacja jest wtedy użyteczna i konieczna. W takich wypadkach, docenisz system makroprzetwarzania i metaprogramowania które pozwolą ci wracać do raz przygotowanych wzorców z których każdy z nich jest przygotowany jako wielokrotna definicja, co pozwala bezpiecznie programować i automatycznie przechodzić modyfikację takich wzorców itd. "Goły" assembler jest często niewystarczający, nawet jeśli chcesz robić tylko małe operacje w połączeniu z C.

## 4.1 Co jest zintegrowane w powyższym

Tak, wiem że ta sekcja nie zawiera użytecznych informacji. Masz swobodę do prowadzenia jej, jeśli odkryjesz coś ciekawego...

### GCC

GCC pozwala (i wymaga) wyspecyfikować ograniczenia rejestrów w twoim kodzie ``inline assembly'', więc optymalizer zawsze wie o tym. W ten sposób, assemblacja kodu inline jest tak naprawdę realizowana przez wzorce, a nie wymuszana.

Później możesz umieścić twój kod assemblera w makrach CPP, i funkcjach inline w C, więc każdy może użyć go jako funkcje w C lub makro.

Funcje inline są bardzo podobne do makr, ale są czasami czystsze w użyciu. Strzeż się tych wypadków, kod będzie zduplikowany, tak więc tylko lokalne etykiety (w stylu `1:`) powinny być definiowane w kodzie assemblera. Jakkolwiek, makro powinno pozwolić nazwie dla nie lokalnej etykiety być przekazaną jako parametr (lub inaczej, powinienes używać dodatkowych meta-programowych metod). Zapamiętaj także, że rozejście się kodu jako inline assemblera będzie potencjalnie rozprowadzał nim błędy, więc uważaj dokładnie w kwestii ograniczeń rejestu w kodzie inline asm.

Ostatecznie, język C w sobie może być rozważany jako dobra abstrakcja programowania w assemblerze, co przyniesie ci ulgę z większością kłopotów z assemblacją.

Strzeż się pewnych optymalizacji które zawile przekazują argumenty do funkcji; przez rejestry mogą powodować niedopasowanie tych funkcji do wywołań z zewnętrznych (w szczególności ręcznie napisanego kodu assemblera) funkcji w standardowy sposób; atrybut "asmlinkage" może chronić funkcję przed kłopotami z taką flagą optymalizacyjną; obejrzyj źródła jądra linux-a dla przykładów.

### GAS

GAS ma możliwość włączania pewnych makr, jak opisano w dokumentacji texinfo. Oprócz tego, podczas gdy GCC rozpoznaje pliki .s jako surowy assembler do wysłania do GAS, także rozpoznaje pliki .S jako pliki do przepuszczenia przez CPP przed wpuszczeniem ich do GAS. Znowu, znowu, zobacz źródła Linux-a dla przykładów.

### GASP

Dodaje wszelkie użyteczne dodatki makroassemblacji do GAS. Obejrzyj jego dokumentację texinfo.

### NASM

NASM także zawiera pewne wsparcie makr. Zobacz dokumentację. Jeśli masz jakieś dobre pomysły, możesz chcieć skontaktować się z autorami, jako, że oni aktywnie go rozwijają. W międzyczasie, zobacz poniżej zewnętrzne filtry.

### AS86

On także ma trochę prostego wsparcia makrami, ale nie mogłem nigdzie znaleźć dokumentacji. Teraz źródła są bardzo przejrzyste, więc jeśli jesteś zainteresowany, łatwo powienieneś je zrozumieć. Jeśli potrzebujesz więcej niż tylko bazę, powinieneś użyć zewnętrznego filtra (zobacz poniżej).

### INNE ASSEMBLERY

- Win32FORTH: CODE i END-CODE są normalne więc nie przełączaj ich z trybu interpretacji to trybu kompilacji, będziesz miał wtedy dostęp do całej mocy FORTH podczas assemblacji.
- TUNES: nie działa jeszcze, ale język Scheme jest prawdziwym wysokopoziomowym językiem który pozwala na meta-programowanie.

## 4.2 Zewnętrzne Filtry

Jakiekolwiek jest wsparcie makr twojego assemblera, lub jakikolwiek język używasz (nawet C !), jeśli język nie jest dla ciebie wystarczająco wyrazisty, możesz chcieć przepuścić pliki przez zewnętrzny filtr z regułami w Makefile takimi jak te:

    %.s:    %.S other_dependencies
            $(FILTER) $(FILTER_OPTIONS) < $< > $@

### CPP

CPP nie jest bardzo wyrazisty, ale wystarczający do wielu łatwych rzeczy, jest standardem, i jest przezroczyście wywoływany przez GCC.

Dla przykładu jego ograniczeń, nie możesz deklarować obiektów, takich że destruktory wywoływane automatycznie na końcu deklarowanego bloku; nie możesz więc zmieniać kierunki widoczności, itd.

CPP przychodzi wraz z kompilatorem C. Jeśli mógłbyś robić to bez niego, nie zawracaj sobie głowy przynoszeniem CPP (chociaż myślę jakbyś mógł).

### M4

M4 daje ci pełną moc makroprzetwarzania, z językiem równym Turingowi, rekursją, wyrażeniami regularnymi, itd. Możesz robić wszystko czego CPP nie.

Zobacz macro4th/This4th z ftp://ftp.forth.org/pub/Forth/ in Reviewed/ ANS/ (?), lub źródła Tunes 0.0.0.25 jako przykłady zaawansowanego makroprogramowania z użyciem m4.

Jakkolwiek, jego niefunkcjonalna semantyka cytowania i odcytowywania zmusza cię do używania jawnego ogonkowo-kontynuacyjno-przejściowego (przyp. tłum.) stylu makr jeśli chcesz robić zaawansowane makro programowanie (czego przypomnieniem jest TeX -- BTW, czy ktoś próbował używać TeX-a jako makroprocesora do czegoś innego niż typesetting ?) To NIE jest gorsze niż CPP, który nie pozwala na cytowanie i rekursję.

Właściwą wersją m4 jest GNU m4 1.4 (lub późniejsza jeśli istnieje) która zawiera większość składników i mniej błędów lub ograniczeń. m4 został pomyślany jakko wolny do czegokolwiek ale prosty w użyciu, może być więc nadal dobry dla większości programów w assemblerze (chyba nie piszesz programów z milionami linii w assemblerze?).

### Makroprzetwarzanie z twoim własnym filtrem

Możesz pisać twój własny prosty filtr rozszerzający makra z użyciem zwykłych narzędzi: perl, awk, sed, itd. To jest szybki sposób i możesz wszystko kontrolować. Ale oczywiście, moc makroprzetwarzania musi coś kosztować.

### Metaprogramowanie

Zamiast używania zewnętrznych filtrów które rozszerzają makra, jedną z dróg jest pisanie programów, które piszą część lub całość innych programów.

Dla przykładu, mógłbyś użyć programu produkującego kod źródłowy

- do generowania tablic sinus/cosinus/cokolwiek,
- do wyciągania reprezentacji źródłowej pliku binarnego,
- do kompilacji bitmap w szybkie funkcje wyświetlające,
- do wyciągania dokumentacji, kodu początkowego/końcowego, tablic opisowych, tak dobrze jak normalnego kodu z samych plików źródłowych,
- do zwykłego kodu assemblera, generowanego ze skryptów perl/shell/scheme które robi przetwarzanie,
- do rozchodzenia danych zdefiniowanych w jednym punkcie w różne krzyżowe wg odwołań tablice i nagłówki.
- itd.

Pomyśl o tym!

### Część wspomagająca z dostępnych kompilatorów

Kompilatory takie jak SML/NJ, Objective CAML, MIT-Scheme, itd, mają własną część wspomagającą assembler, którą możesz ale nie musisz wykorzystywać, jeśli zamierzasz generować kod półautomatycznie z wymienionych języków.

### Zestaw narzędzi Machine-Code z New-Jersey

Jest projekt, używający języka programowania Icon, do budowy podstawowych rzeczy do produkcji manipulacji na kodzie assemblera. Zobacz http://www.cs.virginia.edu/~nr/toolkit/

### Tunes

Projekt Tunes OS rozwija swój własny assembler jako rozszerzenie języka Scheme i jako część procesu rozwojowego. Nie działa to jeszcze, ale pomoc jest widziana.

Assembler manipuluje symbolicznymi drzewami składni, więc możesz prawie mieć podstawę do translacji składni assemblera, disassembler, wspólną część wspomagającą assembler/kompilator, itd. Także, pełna moc języka Scheme czyni go nie do pokonania z makroprzetwarzaniem/metaprogramowaniem.

http://www.tunes.org/

## 5. KONWENCJE WYWOŁAŃ

## 5.1 Linux

### Połączenie z GCC

To jest preferowany sposób. Sprawdź dokumentację i przykłady GCC z plików `.S` jądra Linux-a które są przepuszczane przez gas (nie takie, które są przepuszczane przez as86).

32-bitowe argumenty są odkładane na stos w odwrotnej kolejności występowania (stąd dostęp / pobieranie jest we właściwej kolejności), zwracając bliski 32-bitowy adres. `%ebp`, `%esi`, `%edi`, `%ebx` są zapamiętywane, inne rejestry też są zapamiętywane podczas wywołania; `%eax` jest używany do przechowywania wyniku, a `%edx:%eax` do przechowywania wyników 64-bitowych.

FP stack: Nie jestem pewien, ale myślę że wynik jest w `st(0)`, cały stos jest zapamiętany.

Pamiętaj, że GCC ma opcje modyfikujące konwencje wywołań przez rezerwowanie rejestrów, przekazywanie argumentów w rejestrach, nie używanie FPU, itd. Sprawdź strony .info i386.

Pamiętaj, że musisz zadeklarować atrybut `cdecl` dla funkcji używających standardowej konwencji wywołań GCC (nie wiem co daje użycie zmodyfikowanej konwencji wywołań). Zobacz w stronach info GCC sekcję: `C Extensions::Extended Asm::`

### ELF kontra a.out - problemy

Pewne kompilatory poprzedają podkreśleniem każdy symbol, podczas gdy inne nie.

W szczególności, Linux-owy GCC a.out ma takie poprzedniki, podczas gdy Linux-owy ELF GCC nie.

Jeśli musisz poradzić sobie z wykorzystaniem obu formatów zobacz jak robią to istniejące pakiety. Dla przykładu, weź stare drzewo źródłowe Linux-a z pakietami Elk, qthreads lub OCAML...

Możesz także nadpisać niejawnie C`->`asm zmieniając nazwę przez wstawienie wyrażeń takich jak to

            void foo asm("bar") (void);

by upewnić się, że wywołanie funkcji C foo będzie zabronione w assemblerze.

Zapamiętaj, że program `objcopy`, z pakietu `binutils`, powinien pozwolić ci przekonwertować obiekty a.out w obiekty ELF, i być może w przeciwną stronę także, w pewnych wypadkach. Bardziej ogólnie, program ten realizuje konwersję formatów wielu plików.

### Bezpośrednie wywołania systemowe Linux-a

To NIE jest rekomendowane, ponieważ konwencje zmieniają się od czasu do czasu od jądra do jądra (cf L4Linux), dodatkowo to nie jest przenośne, i niezyskowne w pisaniu biorąc pod uwagę libc, I wyłącza poprawki i rozszerzenia które pojawiają się w libc, takie, jak np. biblioteka `zlibc`, która w locie przezroczyście dekompresuje spakowane gzip-em pliki. Standardem i rekomendowaną drogą wywołań systemowych usług Linux-a jest i tak zostanie, przejście przez libc.

Obiekty dzielone powinny trzymać twoje programy małymi. I jeśli naprawdę chcesz mniejszych binariów, używaj `#!` , z interpretera mającego nad sobą wszystko czego nie chcesz w swoich binariach.

Teraz, jeśli z pewnych powodów nie chcesz linkować programów z libc weź się za nią i zrozum jak działa! Po tym wszystkim, nadal zamierzasz zamienić ją ?

Możesz zerknąć także jak mój eforth 1.0c robi to.

Źródła Linux-a są także użyteczne, szczególnie plik nagłówkowy asm/unistd.h który opisuje jak wywoływać funkcje systemowe... Podstawowo, wywołujesz `int $0x80` z `__NR_`numerem funkcji systemowej (z `asm/unistd.h`) w `%eax`, i parametrami (do pięciu) w `%ebx`, `%ecx`, `%edx`, `%esi`, `%edi`. Rezultat jest zwracany w `%eax` z wartością ujemną w przypadku błędu której przeciwną wartość libc umieszcza w errno. Stos użytkownika jest nietknięty więc nie musisz mieć go właściwego podczas wywołania systemowego.

### I/O pod Linux-em

Jeśli chcesz korzystać bezpośrednio z I/O pod Linux-em jest coś prostego co nie uzależnia od OS, i powinieneś obejrzeć `IO-Port-Programming` mini-HOWTO; lub potrzebuje to sterownik urządzenia, powinieneś spróbować nauczyć się o łamaniu jądra, rozwijaniu sterowników urządzeń, modułów jądra itd, dla których są inne wspaniałe HOWTO i dokumenty z LDP.

W szczególności, jeśli chcesz zająć się programowaniem Grafiki przyłącz się do projektu GGI: http://www.ggi-projectorg/

Jakkolwiek, we wszystkich przypadkach, zrobisz lepiej używając GCC inline assembly z makrami z linux/asm/*.h, niż pisząc pliki źródłowe w samym assemblerze.

### Dostęp do 16-bitowych sterowników z Linux-a/i386

Taka rzecz jest teoretycznie możliwa (dowód: zobacz jak DOSEMU może selektywnie dawać dostęp portów do urządzeń programom), i słyszałem pogłoskę że ktoś gdzieś już to zrobił (w sterowniku PCI? W dostępie do VESA ? ISA PnP ? nie wiem). Jeśli masz więcej precyzyjnych informacji na ten temat będa mile widziane. Jakkolwiek, by uzyskać więcej informacji dobrymi miejscami są źródła jądra Linuxa, źródła DOSEMU (i innych programów w DOSEMU repository), oraz źródła różnych niskopoziomowych programów działających pod Linux-em... (być może GGI jeśli wspiera standard VESA).

Zasadniczo, musisz używać 16-bitowego trybu chronionego lub trybu vm86.

Na początku jest w miarę prosto to ustawić, ale będzie to działać tylko z dobrze-zrobionym kodem The first is simpler to setup, but only works with well-behaved code nie wykorzystującym jakiejkolwiek arytmetyki segmentowej that won't do any kind of segment arithmetics lub bezwzględnego adresowania segmentu (w szczególności adresowania segmentu 0), or absolute segment addressing (particularly addressing segment 0), do czasu zmian że wszystkie używane segmenty mogą być ustawione w zaawansowany sposób w LDT.

Później pozwala się na większą zgodność z vanilla 16-bitowym otoczeniem (? przyp.tłum.), ale wymaga to bardziej skomplikowanej manipulacji.

W obu przypadkach, przed wykonaniem skoku do 16-bitowego kodu musisz

- mmap każdy absolutny adres używany w 16-bitowym kodzie (taki jak ROM, bufory video, docelowe DMA, i mapowane-do-pamięci I/O) z /dev/mem to przestrzeni adresowej twojego procesu,
- ustawić LDT i/lub monitor trybu vm86.
- pobrać właściwe prawa dostępu do I/O z jądra (patrz powyższa sekcja)

I znowu, ostrożnie czytaj źródła do rzeczy zawartych w powyższych informacjach o magazynie DOSEMU, w szczególności te mini-emulatory do uruchomiania ELKS i/lub prostych programów .COM pod Linux-em/i386.

## 5.2 DOS

Większość DOS-owych extenderów zawiera interfejs do usług DOS-a. Poczytaj dokumentacje na ich temat, ale często, symulują one tylko `int $0x21` i inne, więc robisz ``jakbyś'' był w trybie rzeczywistym (mam wątpliwości czy nie są tylko łącznikami i rozszerzają rzeczy by pracowały z 32-bitowymi operandami; najczęściej są tylko przejściem w przerwanie do trybu rzeczywistego lub przez uchwyt vm86).

Dokumentacja na temat DPMI i inne (oraz znacznie więcej) możesz znaleźć na ftp://x2ftp.oulu.fi/pub/msdos/programming/

DJGPP przychodzi z własną (ograniczoną) glibc pochodną/podzestawem/wymienioną, także.

Jest możliwa cross-kompilacja z Linux-a do DOS-a, zobacz katalog devel/msdos/ najbliższej kopii FTP serwera sunsite.unc.edu Zobacz także ekstender-dosa MOSS z projektu Flux w utah.

Inne dokumenty i FAQ są bardziej skoncentrowane na DOS-ie. Nie zalecamy rozwoju pod DOS.

## 5.3 Winwybuchy i takie

(od tłum. Autor tego dokumentu nie przepada za Windows, słusznie zresztą, i dlatego część tej podsekcji nie będzie mile widziana przez zwolenników tego systemu :). Hej, ten dokument zawiera tylko wolne oprogramowanie. Zadzwoń kiedy Winwybuchy staną się wolne, lub gdzie będą dostępne wolne narzędzia do tego!

No, po tym wszystkim, jest : Cygnus Solutions rozwijający bibliotekę cygwin32.dll, dla programów GNU to uruchomienia pod platformami MakroGówna.

Jakkolwiek, możesz używać GCC, GAS, wszytkich narzędzi GNU, i wielu innych Unix-owych aplikacji. Zerknij na ich stronę domową. Ja (Faré) nie zamierzam rozszerzać Losedoze (od tłum. Windows -> Windoze -> Losedoze (Lose) - przegrywać) programowania. ale jestem pewny że wszędzie możesz znaleźć pełno dokumentów na tem temat...

## 5.4 Twój własny OS

Kontrola jest tym co przyciąga wielu programistów do assemblacji, chcących najczęściej rozwijać OS co prowadzi lub pochodzi od łamania w assemblerze. Zapamiętaj, że każdy system pozwalający na samorozwój może być określony jako "OS" nawet mimo tego, że może chodzić "nad" pracującym systemem z wielozadaniowością lub I/O (takim jak Linux na Mach lub OpenGenera na Unix-ie), itd. Stąd, dla łatwiejszego usuwania błędów, możesz rozwijać twój ``OS'' najpierw jako proces chodzący pod Linux-em (pomimo powolnego działania), a potem użyć Flux OS kit (co daje możliwość użycia sterowników Linux-a i BSD w twoim własnym OS) by zrobić go niezależnym. Gdy twój OS jest stabilny, jest jeszcze czas by napisać sterowniki jeśli naprawdę to lubisz.

To HOWTO nie zawiera wewnątrz tematów takich jak kod Boot loadera & wchodzenie w tryb 32-bitowy, Zarządzanie Przerwaniami, Podstawy o intelowskim ``trybie chronionym'' lub ``V86/R86'', definiowania twoich formatów obiektów i konwencji wywołań. Głównym miejscem gdzie możesz znaleźć pochodne informacje o tym wszystkim to kody źródłowe istniejących OS i bootloaderów. Masa wskaźników jest na poniższej stronie WWW: http://www.tunes.org/~tunes/doc/Review/OSes.html

## 6. DO ZROBIENIA & WSKAZANIA

- wypełnić niekompletne sekcje
- dodać więcej wskaźników na oprogramowanie i dokumentację
- dodać proste przykłady z życia do zilustrowania składni, mocy, i ograniczeń proponowanych rozwiązań.
- poprosić ludzi o pomoc w tym HOWTO
- znaleźć kogoś kto ma czas by przejąć zarządzanie tym HOWTO
- być może napisać parę słów o assemblacji na innych platformach?
- Trochę wskazań (dodatkowo oprócz tych już wymienionych w tym HOWTO)
  - podręczniki pentium
  - błędy cpu w rodzinie x86
  - hornet.eng.ufl.edu dla koderów w assemblerze
  - ftp.luth.se
  - PM FAQ
  - Strona Assemblera 80x86
  - Courseware
  - programowanie gier
  - eksperymenty z programowaniem w linux-ie w tylko-asm
- I oczywiście, używać twoich zwykłych Internetowych Narzędzi Przeszukiwań by znaleźć więcej informacji, i dać mi znać jeśli znajdziesz coś interesującego!

Author's .sig:

    ## Faré | VN: ĐŁng-Vű Bân   | Join the TUNES project!  http://www.tunes.org/ ##
    ## FR: François-René Rideau |    TUNES is a Useful, Not Expedient System     ##
    ## Reflection&Cybernethics  | Project for a Free Reflective Computing System ##

## 7. Od tłumacza

To jest pierwsze tłumaczenie tego HOWTO. Z pewnością zawiera ono masę błędów i niektóre sentencje mogą mieć inne znaczenie niż ja im nadałem. Dlatego proszę o email jeśli znajdziesz jakieś błędy (merytoryczne, gramatyczne i inne). Postaram się poprawić dokument w jak najkrótszym czasie i opublikować. Uwagi i komentarze ślij na Zbigniew Michał Kempczyński. Szczególne podziękowania składam mojej koleżance Annie Dzieniszewskiej za pomoc w trudnych gramatycznych kawałkach tego tekstu. Jeśli ktoś wie jak przetłumaczyć Legal Blurp to proszę o email.