Windows Altında Win32Assembly Programlama
Artık masm ile nasıl program yazılır bir gözatalım. Aşağıdaki küçük
bir windows uygulaması yer almakta:
.386
.model flat, stdcall
option casemap :none ; case sensitive
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
baslik db
"İlk Assembly Programımız",0
yazi db
"Merhaba Dünya",0
.code
start:
push MB_OK
push offset
baslik
push offset
yazi
push NULL
call MessageBox
push NULL
call ExitProcess
end start
|
; --------------- Data section
.data
baslik db
"İlk Assembly Programımız",0
yazi db
"Merhaba Dünya",0
; --------------- Code section
.code
; --------------- Program startup
start:
invoke MessageBox,NULL,offset
yazi,offset baslik, MB_OK
invoke ExitProcess,0
end start |
Yukarıdaki ilk örnek qeditor.exe ile derlenebilecek haldedir. Biz eğer
notepad kullanmış olsaydık bu şekilde kodlayacak idik. Ben derledim ve boyutu
2.5kbyte olan bir exe dosyası oluştu. Yukarıdaki hem soldaki hemde sağdaki
assembly kodu aynı işi yapıyor. Yaptığı iş baslik ismi ile belirtilen başlığa
sahip, yazi ismi ile yine data segmentte belirtilen yazıya sahip bir mesaj
kutusu gösteriyor. OK'e tıklandıktan sonra program sonlanıyor. İsterseniz hemen
açıklamaya başlayayım. İlk üç satıra uzun süre hiç dokunmayacaksınız, burayı
geçiyorum. Include satırları ile içinde windows api fonksiyonlarının ve bazı
sabit değerlerin isimleri bulunan inc uzantılı dosyaları tanımlıyoruz.
Includelib fonksiyonu ile kullandığımız api fonksiyonlarını içeren kütüphaneleri
tanımlıyoruz. Windows.inc dosyasında NULL ve
MB_OK tanımlamalarının matematiksel
eşitlikleri bulunuyor. Birçok özel durumun hangi sayılar ile belirtildiğini
ezberlemektense bunların karşılıklarını bilmek daha kolaydır, hemde programın
okunurluğunu artırır. .data ile data segment tanımlanıyor ve bu data segment
içinde baslik ve yazi adreslerinde ilgili string ifadeler yer alıyor. Dikkat
ederseniz stringlerin bittiğini belirtmek için ayrıca 0h degeri ekleniyor. Daha
sonra .code ifadesi ile cede segment tanımlanıyor. start: ve end start ifadeleri
arasına kodlarımızı yazıyoruz. Dört adet push komutu alt alta yazılmış.
PUSH
komutu ile stack segmente bazı değerler gönderiyoruz. Bunlar mesaj kutusu ile
ilgili özellikler. İlk özellik mesaj kutusunda sadece OK tuşu bulunacağı
anlamında. İkinci özellik olan mesajın başlık bölümünde yer alacak yazının
adresini stacka yolluyoruz. (adresi anlamına gelen offset terimi kullanılmıştır)
Üçüncü yollanan özellik mesaj olarak gösterilecek string ifadenin adresi. Son
yollanan ifade NULL yani sıfırdır, buraya bir değer girmemize şu anda gerek yok.
Gerekli parametreler stacka yollandıktan sonra fonksiyonumuzu çağırıyoruz.
CALL
komutu bir fonksiyonun yada bir altprogramın çağırılmasında kullanılır.
Çağırılan yerdeki işler bittikten sonra programımız bir sonraki ifade ile devam
edecektir. Fonksiyonumuz MessageBox apisidir . Bu api
user32.inc içinde
tanımlanmış ve ilgi kutuphane user32.lib eklenmiştir. Bu apiyi kullandığımızı
belirtmek için yukarıdaki ifadeleri include ile tanımlamaktayız. Daha sonraki
bölümde programdan çıkış kodları bulunuyor. Öncelikle çıkış kodu stacka
yollanır. Normal sonlanmalarda bu NULL yani sıfırdır. Daha sonra
kernel32.inc ve
kernel32.lib ile tanımladığımız fonksiyonlardan
ExitProcess çağırılıyor.
İşletim sistemimizde user32.dll içinde MesageBox apisi,
kernel32.dll içinde
ise ExitProcess apisi bulunmaktadır. Dos altında yaptığımız interrup çağrıları
gibi windows altında api fonksiyonları bulunur. Bunlar disk erişiminden, ekrana
resim çizdirmeye, buttonlar ve kutucuklar hazırlamaya kadar binlerce fonksiyon
içeririler. Tabii sadece bu iki dll dosyasıyla sınırlı değil apiler. Ayrıca
yukarıdaki komutları yazarken dikkatli olmanız gerekiyor. Derleyicimiz büyük
küçük harf ayrımı yapabiliyor. Özellikle api fonksiyonların isimlerini aynen
yazın.
Soldaki kod ise işlev olarak aynıdır. Farkı ise MAsmEd altında yukarıdaki
gibi yazılması yeterlidir. Include tanımlamalarını programda sol taraftaki ağaç
şeklindeki kısımdan ekleyerek yapıyoruz. Data segmentin içeriği aynı. Code
segmentde ise küçük bir değişiklik var. Alt alta yazdiğimiz fonksiyon çağırma
işinde call yerine invoke ile tek satırda tüm parametreleri yazdık. Böylece
daha kolay okunur oldu. Bunu qeditor.exe içinde de yapabilirdik, yinede eski
şekilde kullanılan örnekler daha çok olduğu için ikisini de göstermek istedim.
Yoksa yazım farkından başka ikiside aynen ilk örnekteki gibi çalışmaktadır.
Birde editörümüz programımız için ikon ve ek bazı versiyon bilgileri
eklemektedir. Bu nedenle editör içinden derlenen aynı program 5.5kbyte
boyuta sahip olacaktır.
|