Asembler ATamp;T i wstawki w GCC
ic3
Na wstępie zaznaczam, iż nie jest to kurs asemblera a jedynie
porównanie dwóch jego "wersji". Większość z was zapewne - o ile
miała okazję poznać asemblera - jest przyzwyczajona do notacji
Intela używanej przez takie kompilatory jak NASM, TASM czy
MASM (czyli większość działajacych pod windowsem). Natomiast
kompilator GNU używa składni AT&T, także wstawki w kodzie
pod GCC pisze sie w tejże składni.
Główne różnice
Zaczne od rzeczy, która zapewne będzie się wam ciągle mylić,
podam przykład:
mov eax , ebx
Zawartość rejestru ebx zostanie przeniesiona do rejestru eax.
W asemblerze AT&T jest odwrotnie, najpierw podajemy źródło a
potem cel. Teraz "prefixy" - w skladni Intela nie ma czegoś
takiego jak prefix, natomiast w AT&T dodajemy przed nazwą
rejestru %, przed nazwą zmiennej lub stałej wartości $. Następną
ważną rzeczą są tzw. sufiksy. Jest to specyfikacja wielkości
danych którą przetważamy. Żeby to wyjaśnić podam przykład:
Intel:
mov eax , ebx
mov ax , bx
mov al , bl
AT&T:
movl %ebx , %eax
movw %bx , %ax
movb %bl , %al
Jak widać dla operacji na liczbach 32 bitowych używamy sufiksu
l, dla liczb 16 bitowych - w, dla liczb 8 bitowych - b. Teraz
adresowanie pamięci :-). Intelowy "prototyp" adresowania wygląda
tak:
[wskaźnik bazowy + wskaźnik do indeksu*skala indeksowania + adres]
w AT&T wygląda to troche inaczej:
adres(wskaźnik bazowy , wskaźnik do indeksu , skala indeksowania)
Do deklaracji zmiennych nie używamy tak jak w składni intela db,
dw, dd, tutaj korzystamy odpowiednio ze słów .byte , .word , .long
dla danych 8, 16 i 32 - bitowych.
Przykład
Oczywiście bez przykładu sie nie obejdzie, pokaże tu prosty program, który
można skompilować na DOSowym pakiecie DJGPP (port narzędzi GNU):
# example.s
.section .text
.p2align 1
.globl _main
_main:
xorl %ecx , %ecx
movl $tablica , %eax
loop:
movb 0(%eax,%ecx,1) , %bl
cmpb %cl , %bl
incl %ecx
je loop
leave
ret
.section .data
tablica:
.byte 0,1,2,3,4,5,6,7,8,9,0
# gcc example.s -o example.exe
Program będzie kopiował kolejne bajty "tablicy" do rejestru BL i porównywał
wartość z wartością rejetru CL, więc dopóki elementy "tablicy" będą rosły pętla
będzie powtarzana, ostatnie 0 przerwie pętle.
Ogólnie o wstawkach
Czasami potrzebujemy wstawić do naszego programu w C/C++ kod asemblera, w kompilatorze
GNU nie skorzystawmy z tradycyjnej składi, musimy wykorzystać (poznaną wcześniej :)) AT&T. Aby wstawić pojedynczą
instrukcje piszemy np.:
asm("xorl %eax , %eax");
Aby wstawić kilka instrukcji robimy troche inaczej:
asm("xorl %eax , %eax\n\t"
"xorl %ebx , %ebx\n\t"
"xorl %ecx , %ecx\n\t");
Do czego nam te \n i \t? Dlatego, że "string" w funkcji asm będzie wstawiony
bezpośrednio do kodu programu, możemy to sprawdzić generując kod asemblera
zamiast kompilować programu do postaci wykonywalnej, weźmy na przykład:
// example2.c
int main()
{
asm("\txorl %eax , %eax\n\t\t"
"xorl %ebx , %ebx\n" );
return 0;
}
// gcc -S example2.c
Powinien powstać plik example2.s, możecie zauważyć, że dwie linijki
xorl %eax , %eax
xorl %ebx , %ebx
będą bardziej wysunięte od innych, dzieki temu, że dodaliśmy dwa razy znak
\t , oczywiście nie musimy przesadzać, ten przykład był aby nam pokazac
jak kod jest wstawiany :), \n jest raczej wymagane ;) natomiast \t możemy pominąć.
Przykład
Teraz przykład użycia asemblera w kodzie C:
// example3.c
#include <stdio.h>
char tab[] = "ABCD";
int main()
{
printf("%s -> ", tab );
asm(" movl $_tab , %eax \n\t"
" xorl %ecx , %ecx\n\t"
"loop1:\n\t "
" cmpb $0 , 0(%eax,%ecx,1)\n\t"
" je end1\n\t"
" incb 0(%eax,%ecx,1)\n\t"
" incl %ecx\n\t"
" jmp loop1\n\t"
"end1:\n\t" );
printf("%s \n" , tab );
return 0;
}
// gcc example3.c
Program najpierw wyświetla tablice tab potem (wstawka asemblera) zwiększa
każdy jej element o 1 i wyświetla tablice jeszcze raz. Należy zauważyć, że
w kodzie asemblera użyłem _tab a nie tab, zrobiłem to dlatego, iż kompilator C sam
dodaje _ przed nazwami zmiennych, należy o tym pamiętać! Warto też zrobić
gcc -S example3.c :).
Zakończenie
Za jakiś czas może dodam coś jeszcze... Narazie mam ogromny brak czasu nawet na
myślenie :D. Ale mam nadzieję, że artykuł się spodobał, jeżeli masz jakieś pytania
lub znalazłeś błąd w artykule to koniecznie daj mi znać ( ice_man11@wp.pl )!
tez sie nad tym zastanawialem, dzieki za pomysl, postaram sie go urzeczywistnic. :) tabelki rulez :D
świetne! możnaby jeszcze zrobić tabelkę z porównaniem obu składni - jak to psory mówią: "tabelka najlepszym przyjacielem ucznia" :D
Dzieki Wolverine :). Jest to moj pierwszy art wiec wszystkie uwagi mile widziane ! W koncu czlowiek uczy sie na bledach... :)
ode mnie 6 :) fajny art
Popraw błędy ortograficzne!!!