2007.01_Assembler i biblioteka GTK+_[Programowanie].pdf

(1454 KB) Pobierz
439030744 UNPDF
dla programistów
Biblioteka GTK+/ASM
i biblioteka GTK+
Marek Sawerwain
Assembler zawsze kojarzy się z najwyższą szybkością działania. Dziś, mimo zaawansowanych
kompilatorów języka C (i wielu innych), nadal program napisany bezpośrednio w assemblerze będzie
mniejszy i zazwyczaj znacznie bardziej sprawny od programu napisanego w języku wysokiego
poziomu. Oczywiście, w obydwu przypadkach musimy stosować te same algorytmy rozwiązujące
dany problem. Nawet assembler nie pomoże, jeśli algorytm zastosowany do rozwiązania danego
problemu jest mało wydajny.
blerze jest ilość potrzebnego czasu, który trzeba po-
święcić na opracowanie aplikacji. W przypadku każ-
dego języka wysokiego poziomu proces pisania ko-
du będzie znacznie szybszy. Jednak, nieco przekornie,
w tym artykule postaram się pokazać, iż nawet w assem-
blerze można tworzyć typowe aplikacje z interfejsem gra-
icznym. Jako bibliotekę GUI wykorzystamy pakiet GTK+
który z powodu, iż został opracowany w ANSI C, znako-
micie współpracuje z wieloma różnymi językami progra-
mowania, także z assemblerem. Postaramy się opraco-
wać aplikację, która będzie wyświetlać aktualnie urucho-
mione na komputerze procesy. Będzie to niewielki odpo-
wiednik programu top , dostępnego we wszystkich dystry-
bucjach Linuksa.
Niestety, artykuł wymaga choćby podstawowej wie-
dzy o programowaniu w assemblerze procesorów Intela
x86. Jednak, z racji jego objętości, niestety nie podam zbyt
wielu podstawowych informacji, poza dwoma dość pro-
stymi przykładami. Dlatego, zachęcam do poszukiwań
w Internecie. Bez trudu można tam odszukać kilka war-
tościowych kursów programowania, które dostarczą
wszystkich potrzebnych informacji. Jednak osoby, któ-
re nigdy nie miały styczności z assemblerem, a znają bi-
bliotekę GTK+ mogą przeczytać ten artykuł aby przeko-
nać się, iż wszystkie przedstawione informacje będą im
dobrze znane.
Jaki assembler?
Istnieją cztery godne polecenia kompilatory języka assem-
bler (czyli, tzw. assemblery) dla Linuksa. Pierwszy to as
wchodzący w skład każdej dystrybucji, ponieważ jest nie-
odłącznym elementem pakietu kompilatorów GCC. Dru-
gi ważnym assemblerem, znacznie wygodniejszym w sto-
sowaniu niż as jest nasm , a jego bezpośrednim następcą
jest assembler yasm . Assembler nasm jest godny polecenia
O autorze
Autor zajmuje się tworzeniem oprogramowania dla Li-
nuksa oraz WIN32. Zainteresowania: teoria języków
programowania oraz dobra literatura.
Kontakt z autorem: msawe@go.onet.pl
64
styczeń 2007
Assembler
J ednak, zasadniczą wadą programowania w assem-
439030744.034.png 439030744.035.png 439030744.036.png 439030744.037.png 439030744.001.png
 
dla programistów
Biblioteka GTK+/ASM
z wielu powodów, jest bardziej „inteligent-
ny” niż as , prostszy w użyciu i podobny do
assemblerów tasm czy masm , które każdy, kto
pisze programy w assemblerze na PC'ty do-
brze zna. Do tych trzech pakietów warto do-
łączyć także assembler fasm , również opra-
cowany w duchu programów tasm i masm .
W przeciwieństwie do wymienionych linuk-
sowych assemblerów został napisany (a jak-
że by inaczej) w assemblerze, co powoduje
iż jest mały (plik binarny waży około 70 kb)
a sam proces kompilacji jest bardzo szybki.
Posiada naturalnie podobne możliwość jak
nasm, ale potrai generować naprawdę ma-
łe pliki binarne (nie jest potrzebny program
konsolidujący -- linker). Jeden z przykładów
po kompilacji nasm'em oraz usunięciu infor-
macji dla debuggera liczy około 440 bajtów,
tymczasem ten sam program kompilowany
za pomocą fasm'a to tylko 163 bajty.
Generowanie informacji dla debugge-
ra jest wielką zaletą nasm'a czy as'a. Skom-
pilowany za pomocą tych narzędzi program
można później śledzić za pomocą debugge-
ra gdb albo za pomocą jednej z nakładek, jak
DDD czy Insight . Niestety, fasm nie daje nam
takiej możliwości, co powoduje, że trzeba ko-
rzystać z bardziej hardcore'wych ;-) narzędzi
jak np.: LinICE.
Jednak w naszym przypadku fasm bę-
dzie łatwiejszy w użyciu, dlatego nasze pro-
gramy napiszemy za pomocą właśnie tego as-
semblera. Niektóre, przykłady, które znajdu-
ją się na płycie CD/DVD mają też odpowied-
niki dla nasm'a.
Kolejnym istotnym założeniem jest uży-
cie konwencji Intela do zapisu instrukcji as-
semblera. Jest ona łatwiejsza - szczególnie
dla osób początkujących - niż składnia AT-
&T stosowana przez as'a. Co więcej, więk-
szość programów w assemblerze na PC'ty
jest pisana właśnie w konwencji Intela a nie
AT&T.
�����
����������
����������������������
��������������������
��
���
�������������
����������
���
�������������������
������������
���
�����������������
���
������������������
����
Rysunek 1. Schemat aplikacji pview
semblera. Po pierwsze, musimy uzyskać spis
aktualnie działających procesów. W przypad-
ku Linuksa wymaga to odczytu katalogu proc .
Trzeba przejrzeć cały katalog i zainteresować
się podkatalogami które mają nazwy składa-
jące się wyłącznie z cyfr, bowiem są to iden-
tyikatory poszczególnych procesów (pomija-
my procesy potomne których spis znajduje się
w katalogu task , choć nie jest to trudne dopi-
sanie kodu do naszego przykładu, który bę-
dzie analizował również tego typu procesy).
W każdym z tych katalogów o „cyfrowej” na-
zwie interesują nas trzy pliki: stat , statm i cmdli-
ne . Pierwszy zwiera wiele cennych informacji
o procesie np.: czasy działania w przestrze-
ni użytkownika, w przestrzeni jądra, priory-
tet procesu, oraz jego stan – uruchomiony/
uśpiony. Drugi z plików, statm, zawiera infor-
macje o pamięci, w ostatnim, cmdline, znajdzie-
my dokładną postać polecenia które urucho-
miło dany proces. Oddzielnym zadaniem - ale
dość łatwym do zrealizowania - jest problem
uzyskania nazwy użytkownika który jest wła-
ścicielem danego procesu.
Naszym zadaniem jest wyciągnięcie tych
informacji z poszczególnych plików, co wy-
daje się dość łatwe do realizacji w dowolnym
języku wysokiego poziomu. Jednak konstru-
ując odpowiednie pętle, również w asemble-
rze, to zadanie nie będzie trudne do wykona-
nia, choć z pewnością mniej czytelne na przy-
słowiowy pierwszy rzut oka.
#include <stdio.h> void main() {
printf(”Hello World!\n”); }
w przypadku assemblera, będzie wymagać
nieco więcej wysiłku ;-). Przykład takiej aplika-
cji prezentuje Listing 1. Polecenie kompilacji te-
go programu to tylko wywołanie fasm'a np.:
fasm hello_en.asm
Nie trzeba oddzielnie konsolidować progra-
mu poleceniem ld . Jedną z wymienionych
zalet fasm'a jest tworzenie plików binarnych
i powyższe polecenie, jeśli nie popełniliśmy błę-
dów, utworzy plik wynikowy zgodnie z po-
Listing 1. Wyświetlenie komunikatu na ekranie
(format ELF executable)
entry start
segment readable executable
start :
Główne danie
Kod programu do śledzenia procesów (o na-
zwie pview ) który napiszemy liczy ponad
1000 linii. Co oznaczałoby, iż nie jest to zu-
pełnie trywialny program ale z drugiej strony
jest to kod assemblera, więc linii zawsze bę-
dzie znacznie więcej niż w analogicznym pro-
gramie napisanym w np.: w języku C. Sche-
mat programu pview jaki chcemy zaprojekto-
wać przedstawia Rysunek 1.
Jak widać ze schematu (ML to skrót od
ang. main loop -- pętla główna), nasza aplika-
cja ma trywialny charakter i opracowanie jej
nie powinno sprawiać żadnych kłopotów. Jed-
nak, nie jest to łatwe zadanie w przypadku as-
mov eax , 4
mov ebx , 1
mov ecx , msg
mov edx , msg_size
int 0x80
mov eax , 1
mov ebx , 0
int 0x80
Pierwszy przykład
Jeśli zaczynamy pisać programy w assemble-
rze, koniecznie trzeba rozpocząć od najmniej-
szych i najprostszych programów. Wyświe-
tlenie komunikatu na ekranie, czyli program
w stylu:
segment readable writeable
msg db 'Witaj Świecie!' , 0xA
msg_size = $ - msg
www.lpmagazine.org
65
439030744.002.png 439030744.003.png 439030744.004.png 439030744.005.png 439030744.006.png 439030744.007.png 439030744.008.png 439030744.009.png 439030744.010.png 439030744.011.png 439030744.012.png 439030744.013.png 439030744.014.png 439030744.015.png
 
dla programistów
Biblioteka GTK+/ASM
leceniami zawartymi w kodzie źródłowym.
W naszym przypadku po kompilacji progra-
mu z Listingu 1 utworzony zostanie plik wy-
konawczy.
Kod źródłowy programu składa się z trzech
części: pierwsza to nagłówek. Informujemy, że
po kompilacji fasm, jak to przed chwilą zostało
powiedziane, ma utworzyć plik wykonywal-
ny w formacie ELF. Odpowiedzialna jest za to
pierwsza linia na Listingu 1. Następna linia jest
również istotna, ponieważ określa etykietę od
której program rozpocznie pracę.
Po nagłówku występuje segment kodu
programu. Komunikat tekstowy przeznaczo-
ny do wyświetlenia znajduje się w ostatniej
części naszej aplikacji po linii segment re-
adable writeable . Jest to sekcja zmiennych
(w assemblerze trudno naturalnie mówić
o zmiennych w takim sensie jak w C, ale poję-
cie zmiennej jest wygodniejsze niż słowo ety-
kieta, czy też mówienie o danych umieszczo-
nych pod określonym adresem), bowiem jak
wskazują na to słowa readable , writeable
możemy pod określone etykiety zapisywać
oraz odczytywać dane.
Ogólnie, nasz program wywołuje dwa
razy systemowe przerywanie jądra o nume-
rze 0x80 (jest to liczba zapisana w systemie
szesnastkowym). Pierwsze wywołanie re-
alizuje wyświetlenie komunikatu na ekra-
nie. Jednak, co trzeba wiedzieć, w rzeczywi-
stości wysyłamy dane do pliku o deskrypto-
rze równym jedności (jest to tzw. standardo-
wy strumień wyjściowy, dane zapisywane do
tego strumienia zazwyczaj są kierowane na
ekran terminala).
Przed wywołaniem przerywania, do czte-
rech rejestrów (uwaga dla początkujących:
rejestr ecx i pozostałe jak eax , edx są reje-
strami 32-bitowymi), ładujemy odpowied-
nie parametry. Do rejestru eax wczytujemy
numer funkcji systemowej jaką chcemy wy-
wołać. Wartość cztery oznacza funkcję odpo-
wiedzialną za wysłanie danych do pliku. Do
ebx przesyłamy numer deskryptora pliku,
w ecx adres bufora w którym znajdują się
dane, a w rejestrze edx powinna się znaleźć
wielkość bufora w bajtach.
Warto zwrócić uwagę na to, w jaki spo-
sób, w sekcji danych została wyznaczona
wielkość komunikatu. Sam komunikat został
zadeklarowany w następujący sposób:
i tak eax to tzw. akumualator - wiele operacji
arytmetycznych, logicznych jest wykonywa-
nych z pomocą tego rejestru, o czym świad-
czy poniższy kod:
msg db 'Witaj Świecie!',0xA
msg_size = $-msg
mov eax, 10
mov ebx, 20
mul ebx
Po etykiecie msg następuje ciąg bajtów. Mo-
żemy samodzielnie policzyć ilość znaków,
ale lepiej to zadanie pozostawić assemble-
rowi, który wyznaczy wielkość samodziel-
nie. Znak „ $ ” oznacza aktualne miejsce w
sekcji liczone w bajtach; jeśli odejmiemy
od tego adres etykiety, to otrzymamy na-
turalnie długość komunikatu, przy czym
znak dolara musi zostać zastosowany tuż
po etykiecie dla której chcemy wyznaczyć
długość.
Drugie wywołanie przerywania syste-
mowego oznacza wykonanie funkcji exit,
której zadaniem jest poprawne zakończenie
aktualnego procesu, czyli w efekcie nasz pro-
gram zakończy działanie.
Nasz program, choć napisany w assem-
blerze, traktowany jest jak każda inna aplika-
cja. Możemy go uruchomić z poziomu kon-
soli (oczywiście nasza główna aplikacja dzia-
ła w środowisku X-Window). Nie musimy
się martwić, czy czegoś nie zepsujemy pisząc
np.: błędną aplikację, ponieważ uruchamia-
my nasze programy na poziomie zwykłego
użytkownika (nawet na koncie root aplikacje
w assemblerze nie są bardziej niebezpieczne
niż aplikacje w C).
Prawdziwie niebezpiecznie są progra-
my uruchamiane w trybie jądra (np.: modu-
ły), wtedy istotne błędy związane z obsługą
pamięci mogą zagrozić bezpieczeństwu ca-
łego systemu. Programy opisywane w tym
artykule, nie mają jednak takiej siły przebi-
cia.
Do akumulatora wczytujemy wartość dzie-
sięć, a do rejestru ebx dwadzieścia i mnoży-
my rejestr eax przez ebx. Wynik jest ponow-
nie umieszczany w rejestrze eax . Warto też
wiedzieć, że rozkaz mul wykonuje mnożenie
liczb bez znaku, więc jeśli ważny jest dla nas
znak liczby, mnożymy dane rozkazem imul .
Jeśli mnożymy duże liczby i wynik jest więk-
szy niż liczba 32bitowa, dodatkowo używany
jest rejestr edx .
Rejestry edi oraz esi to tzw. rejestry in-
deksowe, które pomagają w przetwarzaniu
ciągów danych, z tą operacją związany jest
także rejestr ecx w którym umieszcza się
ilość elementów do przetworzenia.
Szczególnie ważny jest rejestr esp , który
wskazuje na aktualną pozycję początku stosu.
Rozkazem push umieszczamy dane na stosie,
a rozkazem pop zdejmujemy dane i umie-
szczamy w podanym rejestrze lub pod poda-
nym adresem w pamięci.
Element cztery to nowo dodany element
za pomocą rozkazu push , ale jeśli chcemy
uzyskać dostęp do elementu trzy musimy
ściągnąć element cztery za pomocą instruk-
cji pop .
Inaczej mówiąc, dostęp do danych ma-
my tylko z jednej strony – od góry stosu.
Dane zmieniamy za pomocą dwóch wy-
mienionych rozkazów.
Łatwo wyobrazić sobie stos procesora
jako np.: stos książek – raczej nie wyciąga-
my książek ze środka, a tylko od góry. Jed-
nak, dzięki rejestrowi esp, możemy właści-
wie dowolnie modyikować stos, ale trzeba
to robić uważnie, bowiem program może
odmówić posłuszeństwa jeśli będziemy nie-
rozważnie modyikować stos (nie musimy
się martwić o bezpieczeństwo, gdyż system
pilnuje w jakim zakresie możemy to zrobić).
W naszym programie dość często korzysta-
my z rozkazów pushad i popad które zapi-
sują na stosie stan wszystkich ogólnych re-
jestrów.
W procesorze występuje też stos kopro-
cesora matematycznego (do którego mamy
także dostęp przez rejestry st0, st1, ..., st7)
z którego korzystamy w dość podobny spo-
sób, choć mamy inne rozkazy ld oraz fstp .
Warto wspomnieć o rejestrach MMX, które
Rejestry, stos i operacje
na pamięci
Programowanie na poziomie assemblera to
wykorzystywanie trzech elementów: reje-
strów procesora, stosu maszynowego oraz
pamięci RAM. W trybie trzydziestodwubito-
wym, zwanym też trybem chronionym ma-
my bezpośredni dostęp do ośmiu rejestrów
ogólnego przeznaczenia: eax , ecx , edx , ebx ,
esp , ebp , esi , edi . Istnieją także inne bar-
dzo ważne rejestry, ale z racji ograniczone-
go miejsca nie będę o nich wspominał. Reje-
stry możemy dzielić na mniejsze części, np.:
al to pierwsze osiem bitów rejestru eax na-
tomiast ah to pierwsze szesnaście bitów. Każ-
dy z tych rejestrów ma swoje przeznaczenia,
����
���
Rysunek 2. Zasada działania stosu
66
styczeń 2007
439030744.016.png 439030744.017.png 439030744.018.png
 
dla programistów
Biblioteka GTK+/ASM
Listing 2. Nieskomplikowany przykład użycia GTK+ w assemblerze (format ELF)
nowszych procesorach AMD i Intel. W tym
trybie mamy szesnaście rejestrów 64-bitowych
ogólnego przeznaczenia. Pierwsze osiem no-
si nazwy rax , rdx czy rsi , a nowe to r8 ,
..., r15 . Rejestry SSE również rozszerzono
o osiem nowych rejestrów. Powoduje to, iż
odpowiednio opracowane programy 64bito-
we będą pracować wyraźnie szybciej niż od-
powiedniki 32-bitowe.
Same rejestry i stos wbrew pozorom wy-
starczą do opracowania każdego progra-
mu ale byłoby to dość niewygodne. Dlatego
dodatkowo możemy modyikować w spo-
sób bezpośredni dane w pamięci RAM. Roz-
kaz typu:
include 'cdecl.inc'
include 'gtk.inc'
public main
extrn g_print
extrn g_signal_connect_data
; pozostałe symbole zewnętrzne
extrn gtk_main
section '.data' writeable
szDeleteEvent db " delete_event ", 0
szClicked db " clicked ", 0
; inne komunikaty
mov eax, [etykieta]
section '.bss' writeable
powoduje, że do rejestru eax zostanie wczy-
tana wartość znajdująca się pod adresem
etykieta . Instrukcja mov eax, etykieta po-
woduje, iż do rejestru eax zostanie załadowa-
ny adres etykiety. Nie sposób krótko przed-
stawić wszystkich najważniejszych informa-
cji, dlatego zachęcam do prześledzenia kil-
ku kursów assemblera. Wbrew pozorom to
dość prosty język, choć nauczenie się pisania
w nim programów to już zupełnie inny pro-
blem. Godna polecenia jest darmowa książka:
Art of Asembly Language Programming .
hWindow dd ?
hButton dd ?
section '.text' executable
proc main argc , argv
lea eax , [ argc ]
lea ebx , [ argv ]
ccall gtk_init , eax , ebx
ccall gtk_window_new , GTK_WINDOW_TOPLEVEL
mov [ hWindow ] , eax
Pierwsze okno i przycisk
Pisanie programu w assemblerze, który wy-
korzystuje bibliotekę GTK+, wbrew pozorom
nie jest zbyt skomplikowane. Dość łatwo wy-
woływać poszczególne funkcje oraz przeka-
zywać niezbędne dane. Kłopoty sprawiają
różnego rodzaju stałe, które są zdeiniowane
przez autorów GTK+. Niestety, musimy po-
nownie utworzyć odpowiednie stałe, oczy-
wiście najlepiej tylko potrzebnej wielkości.
W naszym przypadku potrzebne wielko-
ści zostały zgromadzone w pliku o nazwie
gtk.inc . Niezbędny będzie też drugi plik,
cdecl.inc , w którym znajdują się makra uła-
twiające tworzenie własnych funkcji, zgod-
nych z językiem C oraz wywoływanie funkcji
które zostały opracowane w języku C.
Listing 2 zawiera najważniejsze fragmen-
ty programu (pełny kod źródłowy jak zawsze
na płycie CD/DVD). Zawiera on kilka istot-
nych różnic. Inaczej przedstawia się nagłó-
wek. Znajduje się tam informacja, iż plik po
kompilacji ma mieć postać pliku obiektowe-
go w formacie ELF. Następnie za pomocą po-
lecenia include włączamy pliki z dodatkowy-
mi makrami oraz deinicjami stałych. Inaczej
przedstawiają się też deinicje sekcji. Wystę-
pują trzy sekcje: pierwsza .data , gdzie znaj-
ccall gtk_button_new_with_label , szClickMe
mov [ hButton ] , eax
ccall g_signal_connect_data , [ hWindow ] , szDeleteEvent , DeleteEvent , 0 , 0
ccall g_signal_connect_data , [ hButton ] , szClicked , ButtonClick , 0 , 0
ccall gtk_container_add , [ hWindow ] , [ hButton ]
ccall gtk_container_set_border_width , [ hWindow ] , 15
ccall gtk_widget_show_all , [ hWindow ]
call gtk_main
ret
endp
proc DeleteEvent widget , gdata
endp
proc ButtonClick widget , gdata
endp
niestety są dzielone z koprocesorem mate-
matycznym, dlatego jeśli używamy rejestrów
MMX, nie możemy korzystać z koproceso-
ra. Tej wady są pozbawione rejestry SSE, któ-
re są niezależne i też jest ich osiem (xmm0,...,
xmm7) oraz są to rejestry 128bitowe.
Koniecznie trzeba wspomnieć o nowym
trybie 64-bitowym który jest dostępny w naj-
www.lpmagazine.org
67
439030744.019.png 439030744.020.png 439030744.021.png 439030744.022.png 439030744.023.png 439030744.024.png 439030744.025.png 439030744.026.png 439030744.027.png 439030744.028.png 439030744.029.png 439030744.030.png 439030744.031.png
 
dla programistów
Biblioteka GTK+/ASM
dują się dane przeznaczone wyłącznie odczy-
tu, .bss to zmienne wykorzystywane pod-
czas pracy programu (obiekt okna oraz przy-
cisku), ostatnia trzecia sekcja .text reprezen-
tuje kod naszego programu.
Nim krótko przedstawię najważniejsze
fragmenty kodu, naszą aplikację trzeba będzie
w odpowiedni sposób zbudować. W pierwszej
kolejności kompilujemy plik assemblera:
fasm button.asm button.o
Następnie, tworzymy ostateczną postać pliku
binarnego za pomocą polecenia gcc wywoła-
nego w następujący sposób:
gcc -Wall -s button.o -o button `pkg-
conig --libs gtk+-2.0`
Zastosowanie gcc uprasza proces konsoli-
dacji, gdyż w rzeczywistości nasza aplikacja,
choć napisana w assemblerze, „udaje” pro-
gram napisany w języku C. Dlatego, zosta-
ła zdeiniowana funkcja main z dwoma argu-
mentami argc oraz argv .
Istotny jest sposób, w jaki wywołuje-
my funkcję języka C z poziomu assemblera.
Zdradza nam to następująca linia:
Rysunek 3. Aplikacja do podglądania aktualnie uruchomionych procesów
ccall gtk_init, eax, ebx
Makro ccall wywołuje funkcję gtk_init;
dwa argumenty a właściwie adresy argumen-
tów, czyli argc , argv zostały wcześniej umiesz-
czone w rejestrach eax i ebx . W podobny spo-
sób, postępujemy w przypadku pozostałych
funkcji GTK+. W programie tworzymy okno,
przycisk, podłączamy sygnały, a następnie do-
konujemy kilku kosmetycznych zmian, w in-
terfejsie naszego „programiku”.
Więcej uwagi wymaga proces utworze-
nia nowego widgetu GTK+. Dla przycisku
i podobnie dla okna przedstawia się to na-
stępująco:
cja do podłączania sygnałów. Jest tak, ponie-
waż g_signal_connect to tylko makro pre-
procesora języka C. Podłączenie sygnału do
obiektu w rzeczywistości realizuje się właśnie
za pomocą g_signal_connect_data . Zera za-
stosowane podczas wywołań poszczególnych
funkcji GTK+ to naturalnie odpowiednik war-
tości NULL w języku C.
W naszym drugim przykładzie znajdują
się dwie funkcje: DeleteEvent oraz ButtonC-
lick . Zastosowanie makra proc oraz endp
zapewnia nam, iż obydwie funkcje zachowu-
ją się identycznie jak odpowiedniki funkcji
utworzonych w języku C. W obydwu przy-
padkach treść tych funkcji jest następująca:
nas najważniejsze, odnotujemy tylko iż okno
zostało zbudowane w oparciu o komponent
GtkVBox o trzech polach. W pierwszym polu
znajduje się etykieta, w drugim pośrednio wid-
get GtkTreeView (pośrednio, gdyż mamy tam
jeszcze dodatkowy widget GtkScrolledWin-
dow ), w trzecim, ostatnim polu mamy inny
obiekt pakujący GtkHBox , w którym umiesz-
czono trzy komponenty - pole GtkSpinBox,
w którym możemy w sekundach regulować
czas odświeżania spisu procesów oraz dwa
przyciski.
Wykonywanie naszego programu roz-
poczyna się od etykiety main . Większość wy-
wołań funkcji, w tej części naszego progra-
mu, tworzy interfejs użytkownika. Poszczegól-
ne wywołania są dokonywane za pomocą ma-
kra ccall , w sposób opisany już w poprzed-
nim przykładzie. Z jednym wyjątkiem, a jest
nim wywołanie funkcji gtk_adjustment_new .
Funkcja ta oczekuje danych w postaci liczb
zmiennoprzecinkowych. Ponieważ ccall nie
obsługuje tego typu danych, to musimy wy-
wołanie tej funkcji zakodować w sposób bez-
pośredni. W sekcji zmiennych zostały zadekla-
rowane dodatkowe parametry adj_a1 , adj_a2
aż do adj_a6 . Przekazanie, ich na stos repre-
zentowany przez rejestr esp (stos maszyno-
wy) wymaga w pierwszej kolejności wczytania
ccall gtk_button_new_with_label,
szClickMe
mov [hButton], eax
ccall g_print, adres_komunikatu
ccall exit, 0
ret
Funkcja gtk_button_new_with_label utwo-
rzy widget reprezentujący przycisk. Ponieważ
obiekt w rzeczywistości jest wskaźnikiem,
czyli adresem zapamiętanym w rejestrze eax ,
więc bez kłopotów możemy ten adres zapa-
miętać w innym miejscu pamięci. W naszym
przypadku pod etykietą hButton - a dokład-
niej, pod adresem etykiety hButton . Pozostałe
wywołania od programu w C różnią się tylko
notacją. Jednak nieco inaczej nazywa się funk-
Wywołujemy g_print , aby wyświetlić ko-
munikat (inny dla obydwu funkcji). Następ-
nie za pomocą funkcji exit z parametrem
zero (tym razem, zero to zero a nie wartość
NULL) kończymy działanie naszej aplikacji.
Spis procesów
Ponieważ tworzenie interfejsu (uruchomiony
program przedstawia Rysunek 3), nie jest dla
68
styczeń 2007
439030744.032.png 439030744.033.png
 
Zgłoś jeśli naruszono regulamin