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-
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
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
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
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
Plik z chomika:
SOLARIX33
Inne pliki z tego folderu:
2006.01_Koder plików w formacie OGG_[Programowanie].pdf
(722 KB)
2007.06_Piękno fraktali_[Programowanie].pdf
(1778 KB)
2008.11_GanttProject_[Programowanie].pdf
(1014 KB)
2007.04_USB Device Explorer_[Programowanie].pdf
(1134 KB)
2006.09_QT, PyQT – szybkie tworzenie baz danych_[Programowanie].pdf
(1319 KB)
Inne foldery tego chomika:
Administracja
Aktualnosci
Audio
Bazy Danych
Bezpieczenstwo
Zgłoś jeśli
naruszono regulamin